System, nad którym obecnie pracuję, wykorzystuje architekturę i komunikację sterowaną zdarzeniami, dzięki czemu większość działań w naszym systemie jest wynikiem polecenia i powoduje zdarzenia (jako wysyłane klasy DTO, a nie standardowe zdarzenie delegowane). Dołączamy procedury obsługi zdarzeń, których jedynym celem jest obsługa rejestrowania. Ten projekt pomaga nam się nie powtarzać, a także nie musi modyfikować istniejącego kodu, aby dodać / zmienić funkcjonalność.
Oto przykład jednej z takich klas rejestrowania, która obsługuje wszystkie zdarzenia, które mają być rejestrowane z wąskiej sekcji naszej aplikacji (dotyczące jednego konkretnego źródła treści, z którego importujemy).
Nie muszę koniecznie mówić, że jest to najlepsza praktyka, ponieważ wydaje mi się, że zmieniam zdanie na temat tego, co i jak często rejestrować - i za każdym razem, gdy muszę używać dziennika do diagnozowania problemu, nieuchronnie znajduję sposoby na ulepszenie informacje, które rejestruję.
Powiem jednak, że najważniejsze jest zapisywanie istotnych informacji (zwłaszcza w Ctrl-F / znajdź wyszukiwalny sposób).
Drugą najważniejszą częścią jest usunięcie kodu logowania z głównej logiki - może to uczynić metodę brzydką, długą i skomplikowaną bardzo szybko.
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));
}
}