Das System, an dem ich gerade arbeite, verwendet eine ereignisgesteuerte Architektur und Messaging, sodass die meisten Aktionen in unserem System das Ergebnis eines Befehls sind und zu Ereignissen führen (als ausgelöste DTO-Klassen anstelle eines Standarddelegatenereignisses). Wir fügen Ereignishandler hinzu, deren einziger Zweck die Protokollierung ist. Dieses Design hilft uns, uns nicht zu wiederholen und muss auch keinen vorhandenen Code ändern, um Funktionen hinzuzufügen / zu ändern.
Hier ist ein Beispiel für eine solche Protokollierungsklasse, die alle Ereignisse behandelt, die aus einem engen Abschnitt unserer Anwendung protokolliert werden sollen (diejenigen, die sich auf eine bestimmte Inhaltsquelle beziehen, aus der wir importieren).
Ich werde nicht unbedingt sagen, dass dies zweifellos eine bewährte Methode ist, da ich meine Meinung darüber zu ändern scheine, was und wie ich häufig protokolliere - und jedes Mal, wenn ich ein Protokoll zur Diagnose eines Problems verwenden muss, finde ich unweigerlich Möglichkeiten, Verbesserungen am zu vornehmen Informationen, die ich aufzeichne.
Ich werde jedoch sagen, dass das Aufzeichnen der relevanten Informationen (insbesondere in Strg-F / Suche durchsuchbar) der wichtigste Teil ist.
Der zweitwichtigste Teil besteht darin, den Protokollierungscode von Ihrer Hauptlogik zu entfernen - dies kann eine Methode hässlich und lang und sehr schnell verschlungen machen .
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));
}
}