वर्तमान में मैं जिस सिस्टम पर काम कर रहा हूं, वह एक इवेंट संचालित आर्किटेक्चर और मैसेजिंग का उपयोग करता है, ताकि हमारी प्रणाली में अधिकांश क्रियाएं एक कमांड का परिणाम हो और वे घटनाओं (डीटीओ कक्षाओं के रूप में जो एक मानक प्रतिनिधि घटना के बजाय भेजे जाते हैं) के परिणामस्वरूप होती हैं। हम ईवेंट हैंडलर संलग्न करते हैं जिसका एकमात्र उद्देश्य लॉगिंग को संभालना है। यह डिज़ाइन हमें स्वयं को दोहराने में मदद नहीं करता है, और कार्यक्षमता को जोड़ने / बदलने के लिए मौजूदा कोड को संशोधित करने की भी आवश्यकता नहीं है।
यहां एक ऐसे लॉगिंग क्लास का उदाहरण दिया गया है, जो हमारे एप्लिकेशन के एक संकीर्ण अनुभाग से लॉग किए जाने वाले सभी ईवेंट को हैंडल करता है (उन विशेष सामग्री स्रोत के बारे में जिन्हें हम आयात करते हैं)।
मैं जरूरी नहीं कहूंगा कि यह सबसे अच्छा अभ्यास है, जैसा कि मुझे लगता है कि मैं क्या और कैसे अक्सर लॉग ऑन करने के लिए अपना मन बदल रहा हूं - और हर बार जब मुझे एक समस्या का निदान करने के लिए लॉग का उपयोग करने की आवश्यकता होती है, तो मैं अनिवार्य रूप से सुधार करने के तरीके ढूंढता हूं। जानकारी मैं रिकॉर्ड।
हालांकि, मैं कहूंगा कि प्रासंगिक जानकारी दर्ज करना (विशेष रूप से एक Ctrl-F / खोजा तरीका) सबसे महत्वपूर्ण हिस्सा है।
दूसरा सबसे महत्वपूर्ण हिस्सा अपने मुख्य तर्क से दूर लॉगिंग कोड हो रही है - यह एक विधि बदसूरत और लंबी और घुमावदार कर सकते हैं बहुत जल्दी।
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));
}
}