স্বাগতম! আজকে আমরা পারফরম্যান্স ট্র্যাকিংয়ের জন্য অত্যন্ত চমৎকার একটি টুল নিয়ে আলোচনা করব—Serilog Timings।
আপনার Outline অনুযায়ী, আমরা এখন Section 20: Logging-এর একদম শেষ লেকচার “280. Serilog Timings”-এ আছি। এর আগে আমরা লগিংয়ের অনেক কিছু শিখেছি, কিন্তু যদি আপনাকে বলা হয়, “ডেটাবেস থেকে ডেটা আনতে কতটুকু সময় (মিলি সেকেন্ড) লাগছে তা বের করো”, তখন কী করবেন? ঠিক এই কাজটিই আমরা আজকের লেকচারে শিখব!
চলুন শুরু করা যাক!
📝 Short Summary for Quick Revision
- Purpose: কোডের কোনো নির্দিষ্ট ব্লক (যেমন: Database query) এক্সিকিউট হতে ঠিক কত মিলি সেকেন্ড (milliseconds) সময় নিচ্ছে, তা লগে রেকর্ড করা।
- Use Cases: Database operations, File operations, বা বড় কোনো Loop-এর পারফরম্যান্স পরিমাপ করতে এটি ব্যবহৃত হয়।
- Package Required:
SerilogTimingsনামের থার্ড-পার্টি NuGet প্যাকেজ ইন্সটল করতে হয়। - Implementation:
using (Operation.Time("Message"))ব্লক দিয়ে টার্গেট কোডকে র্যাপ (Wrap) করতে হয়। - Variable Scope Handling:
usingব্লকের ভেতরে ডিক্লেয়ার করা ভ্যারিয়েবল বাইরে অ্যাক্সেস করা যায় না, তাই ভ্যারিয়েবল আগে ডিক্লেয়ার করে ভেতরে শুধু ভ্যালু অ্যাসাইন করতে হয়। - Test Fixes: সার্ভিসে নতুন ডিপেন্ডেন্সি যুক্ত হওয়ার কারণে Unit Test প্রজেক্টে Mock অবজেক্ট আপডেট করতে হয়।
🧠 Comprehensive Breakdown
এখানে আমরা লেকচারের প্রতিটি বিষয় বিস্তারিতভাবে আলোচনা করব এবং সাথে Code Implementation দেখব।
১. Serilog Timings কী এবং কেন এটি প্রয়োজন? (Priority: 10/10)
রিয়েল-ওয়ার্ল্ড অ্যাপ্লিকেশনে অনেক সময় কিছু মেথড এক্সিকিউট হতে বেশ সময় নেয়। যেমন, Entity Framework ব্যবহার করে ডেটাবেস থেকে ডেটা আনা। একজন ডেভেলপার হিসেবে আপনার জানা উচিত এই কোডটি চলতে কতটুকু সময় (Execution time) নিচ্ছে। Serilog Timings ঠিক এই কাজটিই করে। এটি কোডের একটি নির্দিষ্ট অংশের এক্সিকিউশন টাইম ক্যালকুলেট করে স্বয়ংক্রিয়ভাবে একটি লগ জেনারেট করে।
২. NuGet Package Installation (Priority: 10/10)
যেহেতু আমরা PersonsService-এর ভেতরে ডেটাবেস কলের সময় মাপতে চাই, তাই Services প্রজেক্টে এই প্যাকেজটি ইন্সটল করতে হবে।
Visual Studio-এর NuGet Package Manager থেকে SerilogTimings (ট্রেইনার 3.0 ভার্সন ব্যবহার করেছেন) ইন্সটল করুন।
৩. Code Implementation: Operation.Time (Priority: 10/10)
প্যাকেজ ইন্সটল করার পর, আমরা আমাদের GetFilteredPersons মেথডে যাব। সেখানে switch এক্সপ্রেশনের মাধ্যমে ডেটাবেস কল করা হচ্ছে। এর ঠিক উপরে আমরা টাইমিং শুরু করব।
Code Implementation & Scope Fix:
using SerilogTimings; // Namespace ইমপোর্ট করতে হবে
public List<Person> GetFilteredPersons(string searchBy, string searchString)
{
// Scope Issue Fix: using ব্লকের বাইরে লিস্টটি ডিক্লেয়ার করতে হবে
List<Person> persons = null;
// Operation.Time দিয়ে টাইমার শুরু করা হলো
using (Operation.Time("Time for filtered persons from database"))
{
// ... (আগের switch case লজিক যা ডেটাবেস থেকে ডেটা আনে)
persons = _personsRepository.GetFilteredPersons(searchBy, searchString);
}
// using ব্লক শেষ হওয়ার সাথে সাথেই টাইমার বন্ধ হবে এবং লগ তৈরি হবে।
// ... (Diagnostic Context-এর কাজ)
return persons;
}
Why the Scope Fix? যদি আপনি List<Person> persons সরাসরি using ব্লকের ভেতরে ডিক্লেয়ার করেন, তবে ব্লকের বাইরে return persons; কাজ করবে না (Compilation Error দেবে)। তাই এটিকে আগে ডিক্লেয়ার করে নিতে হয়।
৪. Unit Test Fixes (Mocking update) (Priority: 8/10)
আগের লেকচারগুলোতে আমরা PersonsService-এর কনস্ট্রাক্টরে ILogger এবং IDiagnosticContext ইনজেক্ট করেছিলাম। এর ফলে আমাদের Unit Test প্রজেক্টে Error দেখা দেবে, কারণ টেস্ট প্রজেক্টে আমরা শুধু Repository Mock পাঠাচ্ছিলাম। এখন বাকি দুটোরও Mock পাঠাতে হবে।
Test Project Fix:
using Moq;
using Serilog;
using Microsoft.Extensions.Logging;
// টেস্ট মেথডের ভেতরে
var diagnosticContextMock = new Mock<IDiagnosticContext>();
var loggerMock = new Mock<ILogger<PersonsService>>();
// PersonsService তৈরি করার সময় সবগুলো Mock Object পাস করা হলো
var personsService = new PersonsService(
personsRepositoryMock.Object,
loggerMock.Object, // নতুন যোগ করা হলো
diagnosticContextMock.Object // নতুন যোগ করা হলো
);
৫. Seq Dashboard-এ Performance Monitoring এবং Insights (Priority: 9/10)
সব এরর ফিক্স করে অ্যাপ্লিকেশন রান করলে এবং Seq ড্যাশবোর্ডে গেলে আপনি নতুন একটি লগ দেখতে পাবেন: Time for filtered persons from database.
এর ওপর ক্লিক করলে দেখবেন এটি কত মিলি সেকেন্ড সময় নিয়েছে (যেমন: 1502 ms)।
Trainer’s Insight: ১০০০ মিলি সেকেন্ড = ১ সেকেন্ড। ট্রেইনারের ক্ষেত্রে ১.৫ সেকেন্ড সময় লেগেছে, যা ডেটাবেস কলের জন্য বেশ বড় সময়। ট্রেইনার বলেছেন, Entity Framework অনেক সময় ADO.NET বা Dapper-এর তুলনায় একটু স্লো পারফর্ম করে। তাই বড় অ্যাপ্লিকেশনে পারফরম্যান্স ইস্যু আইডেন্টিফাই করার জন্য এই টুলটি অসাধারণ!
🚀 Best Practices & .NET Modern Updates
Best Practices for Serilog Timings:
- Use Sparingly: প্রতিটি মেথডে টাইমিং ব্যবহার করবেন না। শুধু যেসব জায়গায় পারফরম্যান্স বটলনেক (bottleneck) হওয়ার সম্ভাবনা আছে (যেমন: 3rd party API calls, Database queries, Heavy loops), সেখানেই এটি ব্যবহার করুন।
- Meaningful Messages:
Operation.Time("...")-এর ভেতরে সবসময় অর্থবোধক মেসেজ দিন, যাতে লগে দেখলেই বোঝা যায় কোন অপারেশনের সময় মাপা হয়েছে।
Modern .NET Updates (.NET 10 - Built-in Metrics & OpenTelemetry):
SerilogTimings চমৎকার একটি থার্ড-পার্টি টুল, তবে আধুনিক .NET 10-এ পারফরম্যান্স এবং টাইম ট্র্যাকিংয়ের জন্য OpenTelemetry এবং **Built-in TimeProvider** অনেক বেশি স্ট্যান্ডার্ড হিসেবে ধরা হয়।
.NET 10 Code Implementation (Using Built-in Stopwatch & ILogger):
আপনার যদি কোনো থার্ড-পার্টি প্যাকেজ ব্যবহার করতে না ইচ্ছে করে, তবে .NET-এর নিজস্ব Stopwatch দিয়েই সহজে হাই-পারফরম্যান্স টাইমিং লগ করা যায়:
using System.Diagnostics;
public List<Person> GetFilteredPersons(string searchBy, string searchString)
{
var stopwatch = Stopwatch.StartNew(); // টাইমার শুরু
var persons = _personsRepository.GetFilteredPersons(searchBy, searchString);
stopwatch.Stop(); // টাইমার শেষ
// Structured Logging দিয়ে রেকর্ড করা
_logger.LogInformation("Database query took {ElapsedMilliseconds} ms", stopwatch.ElapsedMilliseconds);
return persons;
}
এটি অনেক বেশি লাইটওয়েট এবং আধুনিক মাইক্রোসার্ভিস আর্কিটেকচারে খুব পপ্যুলার।
অভিনন্দন! আপনি সফলভাবে Section 20: Logging শেষ করেছেন! রিয়েল-ওয়ার্ল্ড প্রজেক্টে এই কনসেপ্টগুলো আপনাকে একজন প্রো-লেভেলের ডেভেলপার হিসেবে আলাদা করে চেনাবে। এরপরের সেকশনটি কী নিয়ে হবে? চলুন শুরু করি!