আমি বর্তমানে যে সিস্টেমে কাজ করছি তাতে একটি ইভেন্ট চালিত আর্কিটেকচার এবং মেসেজিং ব্যবহার করা হয়, যাতে আমাদের সিস্টেমে বেশিরভাগ ক্রিয়াকলাপ একটি কমান্ডের ফলস্বরূপ হয় এবং এর ফলে ইভেন্ট হয় (ডিটিও ক্লাস যা প্রেরণ করা হয়, স্ট্যান্ডার্ড ডেলিগেট ইভেন্টের পরিবর্তে)। আমরা ইভেন্ট হ্যান্ডলারদের সংযুক্ত করি যার একমাত্র উদ্দেশ্য লগিং পরিচালনা করা। এই নকশাটি আমাদের নিজেদের পুনরাবৃত্তি না করতে এবং কার্যকারিতা যুক্ত করতে / পরিবর্তন করতে বিদ্যমান কোডটি সংশোধন করতে পারে না।
এখানে এই জাতীয় একটি লগিং ক্লাসের একটি উদাহরণ রয়েছে, যা আমাদের অ্যাপ্লিকেশনটির একটি সংকীর্ণ বিভাগ (আমরা যে কোনও নির্দিষ্ট সামগ্রীর উত্স থেকে আমদানি করি সেগুলি সম্পর্কিত) থেকে লগইন করা সমস্ত ইভেন্টকে পরিচালনা করে।
আমি অগত্যা বলব না যে এটি সর্বোত্তম অনুশীলনের হাতছাড়া হয়েছে, কারণ আমি কীভাবে এবং কীভাবে প্রায়শই লগ করতে হবে সে সম্পর্কে আমার মন পরিবর্তন করতে দেখা যায় - এবং প্রতিবারই কোনও সমস্যা নির্ণয় করার জন্য আমাকে লগ ব্যবহার করা দরকার আমি অবশ্যম্ভাবীভাবে উন্নতি করার উপায়গুলি খুঁজে পাই আমি রেকর্ড তথ্য।
আমি বলব, প্রাসঙ্গিক তথ্যের রেকর্ডিং (বিশেষত একটি সিটিআরএল-এফ / সন্ধানযোগ্য উপায়ে অনুসন্ধান করা) সবচেয়ে গুরুত্বপূর্ণ অংশ।
দ্বিতীয় সর্বাধিক গুরুত্বপূর্ণ অংশটি লগিং কোডটি আপনার মূল যুক্তি থেকে দূরে সরিয়ে নিয়েছে - এটি কোনও পদ্ধতিটিকে কুৎসিত এবং দীর্ঘ এবং জটিলভাবে খুব দ্রুত তৈরি করতে পারে।
public class MctLogger :
IEventHandler<StoryImported>,
IEventHandler<StoryScanned>,
IEventHandler<SourceDirectoryMissing>,
IEventHandler<SourceDirectoryAccessError>,
IEventHandler<CannotCreateScannedStoryDirectory>,
IEventHandler<CannotReadStoryDocument>,
IEventHandler<StorySkippedPastCutoff>,
IEventHandler<StorySkippedDuplicateUniqueId>,
IEventHandler<StorySkippedByFilter>
{
public void Observe(StoryImported e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.StoryImported");
log.Info("Story Unique ID: {Story.UniqueId}, Content ID: {ContentId}, Title: {Story.Headline}".SmartFormat(e));
}
public void Observe(StoryScanned e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.StoryScanned");
log.Info("Story Unique ID: {Story.UniqueId}, File: {FilePath}, Title: {Story.Headline}".SmartFormat(e));
}
public void Observe(SourceDirectoryMissing e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.SourceDirectoryMissing");
log.Error("Directory: " + e.Directory);
}
public void Observe(SourceDirectoryAccessError e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.SourceDirectoryAccessError");
log.Error(e.Exception, "Exception: " + e.Exception.Message);
}
public void Observe(CannotCreateScannedStoryDirectory e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.CannotCreateScannedStoryDirectory");
log.Error(e.Exception, "Directory: {Directory}, Exception: {Exception.Message}".SmartFormat(e));
}
public void Observe(CannotReadStoryDocument e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.CannotReadStoryDocument");
if (e.Exception == null) {
log.Warn("File: {FilePath}".SmartFormat(e));
}
else {
log.Warn(e.Exception, "File: {FilePath}, Exception: {Exception.Message}".SmartFormat(e));
}
}
public void Observe(StorySkippedPastCutoff e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.StorySkippedPastCutoff");
log.Warn("Story Unique ID: {Story.UniqueId}, File: {FilePath}, Title: {Story.Headline}".SmartFormat(e));
}
public void Observe(StorySkippedDuplicateUniqueId e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.StorySkippedDuplicateUniqueId");
log.Warn("Story Unique ID: {Story.UniqueId}, File: {FilePath}, Title: {Story.Headline}".SmartFormat(e));
}
public void Observe(StorySkippedByFilter e)
{
var log = Slf.LoggerService.GetLogger("RoboChef.Content.Mct.StorySkippedByFilter");
log.Warn("Story Unique ID: {Story.UniqueId}, Reason: {Reason}, File: {FilePath}, Title: {Story.Headline}".SmartFormat(e));
}
}