Hệ thống tôi hiện đang làm việc sử dụng kiến trúc và nhắn tin hướng sự kiện, do đó hầu hết các hành động trong hệ thống của chúng tôi là kết quả của một lệnh và chúng dẫn đến các sự kiện (như các lớp DTO được gửi đi, thay vì một sự kiện ủy nhiệm tiêu chuẩn). Chúng tôi đính kèm xử lý sự kiện với mục đích duy nhất là xử lý đăng nhập. Thiết kế này giúp chúng tôi không lặp lại chính mình và cũng không phải sửa đổi mã hiện có để thêm / thay đổi chức năng.
Đây là một ví dụ về một lớp ghi nhật ký như vậy, xử lý tất cả các sự kiện được ghi lại từ một phần hẹp trong ứng dụng của chúng tôi (những sự kiện liên quan đến một nguồn nội dung cụ thể mà chúng tôi nhập từ).
Tôi không nhất thiết phải nói rằng đây là cách thực hành tốt nhất, vì dường như tôi thay đổi suy nghĩ về những gì và cách đăng nhập thường xuyên - và mỗi khi tôi cần sử dụng nhật ký để chẩn đoán vấn đề, tôi chắc chắn sẽ tìm cách cải thiện thông tin tôi ghi lại.
Tuy nhiên, tôi sẽ nói rằng việc ghi lại thông tin thích hợp (đặc biệt là theo cách Ctrl-F / tìm cách tìm kiếm) là phần quan trọng nhất.
Phần quan trọng thứ hai là lấy mã đăng nhập ra khỏi logic chính của bạn - nó có thể làm cho một phương thức trở nên xấu và dài và bị sai lệch rất nhanh.
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));
}
}