স্বাগতম! আজকে আমরা রিয়েল-ওয়ার্ল্ড প্রজেক্টের জন্য অত্যন্ত দরকারি একটি ফিচার শিখতে যাচ্ছি—Serilog File Sink

আপনার Outline অনুযায়ী, আমরা এখন Section 20: Logging-এর নবম লেকচার “274. Serilog File Sink”-এ আছি। আগের লেকচারে আমরা Serilog-এর বেসিক এবং Console-এ লগ দেখানো শিখেছিলাম। কিন্তু Console বন্ধ করলেই লগ মুছে যায়। আজকে আমরা শিখব কীভাবে সেই লগগুলোকে একটি টেক্সট ফাইলে (Text File) স্থায়ীভাবে সেভ করা যায়, যাতে ভবিষ্যতে যেকোনো সময় সেগুলো চেক করা যায়। এরপরের লেকচারেই আমরা Database Sink নিয়ে কাজ করব!

চলুন শুরু করা যাক!

📝 Short Summary for Quick Revision

  • Why File Sink: Console লগ অস্থায়ী (Temporary)। কিন্তু File Sink লগগুলোকে ফাইলে সেভ করে রাখে, ফলে ভবিষ্যতে যেকোনো Exception বা Error ট্র্যাক করা যায়।
  • No Extra Package: এর জন্য নতুন কোনো NuGet Package ইনস্টল করতে হবে না। আগের Serilog এবং Serilog.AspNetCore প্যাকেজ দুটিই যথেষ্ট।
  • Configuration: appsettings.json ফাইলে Using-এ "Serilog.Sinks.File" অ্যাড করতে হবে এবং WriteTo-তে File Sink-এর ডিটেইলস দিতে হবে।
  • Rolling Interval: সময়ের ভিত্তিতে (যেমন: প্রতি ঘণ্টায় বা দিনে) স্বয়ংক্রিয়ভাবে নতুন লগ ফাইল তৈরি করার সুবিধা।
  • File Size Limit: ফাইলের সাইজ নির্দিষ্ট (যেমন: 1 MB) করে দেওয়া যায়, যা পূর্ণ হলে নতুন ফাইল তৈরি হবে।
  • File Lock: অ্যাপ্লিকেশন রান থাকা অবস্থায় Serilog ফাইলটি ব্যবহার করে, তাই তখন সেটি ওপেন করা যায় না। ফাইলটি পড়তে হলে আগে অ্যাপ্লিকেশন (Debugging) স্টপ করতে হবে।

🧠 Comprehensive Breakdown

এখানে আমরা লেকচারের প্রতিটি বিষয় বিস্তারিতভাবে আলোচনা করব এবং সাথে Code Implementation দেখব।

১. File Sink কেন প্রয়োজন? (Priority: 10/10)

Console Sink-এর সবচেয়ে বড় সমস্যা হলো, যখনই আপনি টার্মিনাল বা Kestrel উইন্ডো ক্লোজ করবেন, সমস্ত লগ মুছে যাবে। কিন্তু প্রোডাকশন লেভেলে যখন হাজার হাজার রিকোয়েস্ট আসে, তখন কোনো Error হলে তা তাৎক্ষণিকভাবে চেক করা সম্ভব হয় না। File Sink ব্যবহার করলে সমস্ত লগ একটি ফাইলে সেভ হয়ে থাকে। ফলে কিছুদিন বা কয়েক মাস পরও আপনি সেই ফাইল খুলে দেখতে পারবেন যে অ্যাপ্লিকেশন ঠিকমতো কাজ করছিল কি না, কোন মেথডগুলো এক্সিকিউট হয়েছিল এবং কোথায় Exception হয়েছিল।

২. Configuration in appsettings.json (Priority: 10/10)

Serilog File Sink ব্যবহার করার জন্য appsettings.json ফাইলে কনফিগারেশন আপডেট করতে হবে।

Code Implementation:

{
  "Serilog": {
    "MinimumLevel": "Information",
    "Using": [
      "Serilog.Sinks.Console",
      "Serilog.Sinks.File"
    ],
    "WriteTo": [
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/log.txt",
          "rollingInterval": "Hour",
          "fileSizeLimitBytes": 1048576,
          "rollOnFileSizeLimit": true
        }
      }
    ]
  },
  "AllowedHosts": "*"
}
 

৩. File Sink Arguments (Args) ব্যাখ্যা (Priority: 9/10)

উপরের JSON কনফিগারেশনের Args অবজেক্টটিতে কিছু গুরুত্বপূর্ণ সেটিংস রয়েছে। সতর্কতা: Args-এর ভেতরের প্রোপার্টিগুলো case-sensitive এবং এগুলো অবশ্যই camelCase-এ লিখতে হবে (যেমন: path, rollingInterval), যেখানে বাইরের প্রোপার্টিগুলো PascalCase (যেমন: Name, Args)।

  • path: লগের ডেস্টিনেশন। "logs/log.txt" মানে হলো প্রজেক্টের ভেতরে logs নামে একটি ফোল্ডার তৈরি হবে এবং সেখানে log.txt নামে ফাইল সেভ হবে। (Visual Studio-তে প্রজেক্টের ওপর রাইট-ক্লিক করে logs ফোল্ডারটি ম্যানুয়ালি তৈরি করে নিতে হবে। ভেতরের টেক্সট ফাইলটি স্বয়ংক্রিয়ভাবে তৈরি হবে)।
  • rollingInterval: এটি অত্যন্ত গুরুত্বপূর্ণ একটি প্রোপার্টি। এর ভ্যালু Hour, Day, Month ইত্যাদি দেওয়া যায়। Hour দিলে প্রতি ঘণ্টায় একটি করে নতুন ফাইল তৈরি হবে। ফাইলের নামের শেষে স্বয়ংক্রিয়ভাবে টাইমস্ট্যাম্প যুক্ত হবে (যেমন: log2023102514.txt)।
  • fileSizeLimitBytes: একটি ফাইলের সাইজ সর্বোচ্চ কত বড় হতে পারবে। এখানে 1048576 দেওয়া হয়েছে, যা 1 MB-এর সমান (1024 bytes * 1024 = 1048576 bytes)।
  • rollOnFileSizeLimit: এটি true করে দিলে, যদি এক ঘণ্টা পূর্ণ হওয়ার আগেই ফাইলের সাইজ 1 MB পার হয়ে যায়, তবে Serilog সাথে সাথে নতুন একটি লগ ফাইল তৈরি করে ফেলবে। অর্থাৎ, সময় বা সাইজ—যে শর্তটি আগে পূরণ হবে, তখনই নতুন ফাইল তৈরি হবে।

৪. লগ ফাইল দেখা এবং File Lock Issue (Priority: 8/10)

উপরের কনফিগারেশন করার পর আপনি যখন অ্যাপ্লিকেশন রান করবেন, তখন logs ফোল্ডারের ভেতর একটি টেক্সট ফাইল জেনারেট হবে। কিন্তু রান থাকা অবস্থায় আপনি যদি ফাইলটিতে ডাবল-ক্লিক করে ওপেন করার চেষ্টা করেন, তাহলে Visual Studio একটি Error দেবে: “The file cannot be opened because it is being used by another process.” কারণ হলো, অ্যাপ্লিকেশন রান থাকা অবস্থায় Serilog ক্রমাগত সেই ফাইলে ডেটা রাইট করতে থাকে, তাই ফাইলটি লক করা থাকে। লগ দেখতে হলে আগে অ্যাপ্লিকেশন বা ডিবাগিং স্টপ করতে হবে, এরপর ফাইলটি ওপেন করলে আপনি Console-এর মতোই সমস্ত Information এবং HTTP logs দেখতে পাবেন।


🚀 Best Practices & .NET Modern Updates

Best Practices for File Sink:

  • Use Day Interval: রিয়েল-ওয়ার্ল্ড অ্যাপ্লিকেশনে সাধারণত rollingInterval: "Day" ব্যবহার করা হয়। প্রতি ঘণ্টার লগ রাখা ম্যানেজ করা একটু কঠিন হয়ে যায়।
  • Retained File Count: খুব বেশি ফাইল জমে গেলে হার্ডডিস্ক ফুল হয়ে যেতে পারে। তাই retainedFileCountLimit নামে একটি অপশন ব্যবহার করে বলা যায় যে, সর্বোচ্চ কতগুলো ফাইল জমা থাকবে (যেমন: ৩১ দিনের লগ রেখে পুরোনো লগ ডিলিট করে দেওয়া)।

Modern .NET Updates (High-Performance Logging with Async Sink): যখন আপনার অ্যাপ্লিকেশনে প্রতি সেকেন্ডে হাজার হাজার রিকোয়েস্ট আসবে, তখন মেইন থ্রেড থেকে ডিরেক্ট ফাইলে লগ রাইট করা পারফরম্যান্স স্লো করে দিতে পারে। আধুনিক .NET 10 বা হাই-স্কেল প্রোজেক্টে Serilog.Sinks.Async নামের আরেকটি প্যাকেজ ব্যবহার করা হয়।

.NET 10 Code Implementation (Async File Wrapper): এটি মূলত File Sink-কে একটি Background Thread-এ পাঠিয়ে দেয়, ফলে ইউজারের রিকোয়েস্ট প্রসেসিংয়ে কোনো দেরি হয় না।

{
  "Serilog": {
    "WriteTo": [
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "File",
              "Args": {
                "path": "logs/log.txt",
                "rollingInterval": "Day"
              }
            }
          ]
        }
      }
    ]
  }
}
 

এটি প্রোডাকশন এনভায়রনমেন্টের জন্য অত্যন্ত রেকমেন্ডেড একটি প্র্যাকটিস। আশা করি File Sink-এর পুরো কনসেপ্টটি আপনি খুব ভালোভাবে বুঝতে পেরেছেন! সামনের লেকচারে Database-এ লগ স্টোর করা আরও বেশি রোমাঞ্চকর হবে।