স্বাগতম! আজকে আমরা খুব ইন্টারেস্টিং এবং অত্যন্ত গুরুত্বপূর্ণ একটি টপিক শিখতে যাচ্ছি—Logging

আপনার দেওয়া Outline অনুযায়ী, আমরা এখন Section 20: Logging-এর একেবারে প্রথম লেকচার “266. Introduction Logging”-এ আছি। এর আগে আপনি xUnit, Tag Helpers এবং EntityFrameworkCore নিয়ে চমৎকার কিছু কাজ করেছেন। এখন সময় এসেছে আপনার Application-কে রিয়েল-ওয়ার্ল্ডের জন্য আরও শক্তিশালী করার, যাতে যেকোনো সমস্যা আপনি সহজেই ট্র্যাক করতে পারেন।

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

📝 Short Summary for Quick Revision

  • Logging-এর উদ্দেশ্য: Application execution-এর সময় সফল কাজ এবং Error-গুলোর রেকর্ড রাখা।
  • Tracking Execution: Controller থেকে Service—প্রতিটি Layer-এ Application-এর অবস্থা ট্র্যাক করার জন্য Log message রাখা।
  • Mediator Role: Logging Framework মূলত আপনার Application এবং Log Store-এর মাঝে Mediator হিসেবে কাজ করে।
  • Log Persistence: Console logs শুধু রানটাইমে (Kestrel) দেখা যায়, কিন্তু অন্যান্য Logs ভবিষ্যতে রিভিউ করার জন্য সেভ (Persist) করা থাকে।
  • Serilog: ASP.NET Core-এ অত্যন্ত জনপ্রিয় একটি থার্ড-পার্টি Logging Framework যা সামনে বিস্তারিত শেখানো হবে।

🧠 Comprehensive Breakdown

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

১. Logging কী এবং কেন এটি প্রয়োজন? (Priority: 10/10)

রিয়েল-ওয়ার্ল্ড Application-এ আপনি কীভাবে নিশ্চিত হবেন যে আপনার কোড কোনো Error ছাড়াই সফলভাবে রান করছে? আর যদি কোনো Error আসেও, সেটি কীভাবে ট্র্যাক করবেন?

Why we need it: যখন কোনো ইউজার আপনার Application ব্যবহার করার সময় কোনো পেইজে Error ফেস করে কমপ্লেইন করে, তখন ঠিক কী কারণে সমস্যাটি হয়েছে তা খুঁজে বের করা কঠিন। Logging এই কাজটিই সহজ করে দেয়। এটি আপনার Application-এর Execution টাইমে ঘটা সমস্ত Actions এবং Errors-এর একটি ধারাবাহিক রেকর্ড রাখে।

২. Application Execution Tracking (Priority: 8/10)

লেকচারে বলা হয়েছে যে, Execution sequence যখন কোনো নির্দিষ্ট Method-এ পৌঁছায়, তখন আমরা একটি Log message রেখে দিই।

কীভাবে কাজ করে?

  • প্রথমে Request যখন Controller Action method-এ আসে, তখন আপনি Logging Framework ব্যবহার করে একটি Log message রাখেন।
  • এরপর Controller যখন কোনো Service-কে কল করে, তখন Service-এর ভেতর থেকেও আপনি আরেকটি Log message রাখেন।
  • এভাবে Application-এর প্রতিটি Layer থেকে ডেটা রেকর্ড করা হয়।

Code Implementation (Basic Concept): যদিও লেকচারে কোড দেখানো হয়নি, তবে কনসেপ্টটি প্র্যাকটিক্যালি এমন দেখায়:

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
    private readonly ILogger<UserController> _logger;
 
    // Dependency Injection-এর মাধ্যমে ILogger আনা হচ্ছে
    public UserController(ILogger<UserController> logger)
    {
        _logger = logger;
    }
 
    [HttpGet("{id}")]
    public IActionResult GetUser(int id)
    {
        // Controller-এ Request আসার পর Log message
        _logger.LogInformation("GetUser action method triggered for User ID: {UserId}", id);
 
        try
        {
            // Service কল করার লজিক এখানে থাকবে...
            return Ok();
        }
        catch (Exception ex)
        {
            // Error হলে লগ করা
            _logger.LogError(ex, "An error occurred while fetching User ID: {UserId}", id);
            return StatusCode(500);
        }
    }
}
 

৩. Logging Framework এবং Data Stores (Priority: 9/10)

Logging Framework হলো একটি Mediator (মধ্যস্থতাকারী)। এটি আপনার Application Layers এবং Logs (যেখানে ডেটা স্টোর হয়)-এর মাঝে সংযোগ স্থাপন করে। Logs হলো মূলত Data Stores যেখানে আপনার Log message-গুলো স্থায়ীভাবে (Persisted) সেভ করা থাকে, যেন আপনি যেকোনো সময় সেগুলো রিভিউ করতে পারেন।

৪. Console Logs বনাম Persisted Logs (Priority: 7/10)

  • Console Logs: এগুলো Kestrel Server-এর উইন্ডোতে তাৎক্ষণিকভাবে Error বা Message দেখায়। কিন্তু এগুলো কোথাও সেভ হয় না। একবার টার্মিনাল বা কনসোল বন্ধ হয়ে গেলে এই ডেটা হারিয়ে যায়।
  • Persisted Logs: File, Database বা অন্য কোনো স্টোরেজে সেভ করা Logs। এগুলো পরবর্তীতে রিভিউ করার জন্য সবসময় এভেইলেবল থাকে। প্রোডাকশন লেভেলে সবসময় Persisted Logs ব্যবহার করা হয়।

৫. Serilog: The Third-Party Framework (Priority: 10/10)

এই সেকশনে আপনারা Serilog নিয়ে কাজ করবেন। ASP.NET Core স্পেসে এটি অত্যন্ত জনপ্রিয় একটি থার্ড-পার্টি Logging Framework। কারণ এটি “Structured Logging” সাপোর্ট করে, যার মানে হলো লগগুলো শুধু প্লেইন টেক্সট না হয়ে, JSON-এর মতো স্ট্রাকচার্ড ডেটা হিসেবে সেভ হয়, যা পরবর্তীতে সার্চ বা ফিল্টার করা খুব সহজ। ইন্টারভিউয়ের জন্যও এটি খুবই গুরুত্বপূর্ণ একটি টপিক।


🚀 Best Practices & .NET Modern Updates

Best Practices for Logging:

  • Use Proper Log Levels: সবসময় সঠিক Log Level ব্যবহার করবেন। যেমন সাধারণ ইনফরমেশনের জন্য LogInformation, কোনো সমস্যার ইঙ্গিতের জন্য LogWarning, এবং অ্যাপ্লিকেশন ক্র্যাশ বা ফেইলিউরের জন্য LogError বা LogCritical
  • Never Log Sensitive Data: কখনোই Passwords, Credit Card Numbers বা ইউজারের অত্যন্ত ব্যক্তিগত তথ্য Log ফাইলে রাখবেন না।
  • Structured Logging: সবসময় ভ্যারিয়েবল পাস করার সময় {VariableName} টেমপ্লেট ব্যবহার করবেন, স্ট্রিং কনক্যাটেনেশন (String Concatenation) করবেন না।
  • Good: _logger.LogInformation("User {UserId} logged in.", userId);
  • Bad: _logger.LogInformation("User " + userId + " logged in.");

Modern .NET Updates (High-Performance Logging): .NET 6 থেকে শুরু করে .NET 10 পর্যন্ত Logging-এ পারফরম্যান্স অপ্টিমাইজেশনের উপর অনেক জোর দেওয়া হয়েছে। ট্র্যাডিশনাল _logger.LogInformation()-এর বদলে এখন Compile-time Source Generation ব্যবহার করা হয়, যা অত্যন্ত ফাস্ট এবং মেমরি এফিশিয়েন্ট।

.NET 10-এ আধুনিক Code Implementation (LoggerMessage Attribute):

public partial class UserService
{
    private readonly ILogger _logger;
 
    public UserService(ILogger<UserService> logger)
    {
        _logger = logger;
    }
 
    // Source Generator - এটি কম্পাইল টাইমে হাই-পারফরম্যান্স লগিং কোড জেনারেট করে
    [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Fetching data for user {UserId}")]
    public partial void LogUserFetch(int userId);
 
    public void GetUserData(int userId)
    {
        // কল করার সময় শুধু মেথড কল করতে হবে
        LogUserFetch(userId);
    }
}
 

এটি ট্র্যাডিশনাল পদ্ধতির চেয়ে অনেক বেশি অপ্টিমাইজড, বিশেষ করে বড় স্কেলের অ্যাপ্লিকেশনে। লেকচারে সামনের দিকে আপনারা ILogger এর বেসিক থেকে শুরু করে ধাপে ধাপে অ্যাডভান্সড টপিকে যাবেন।