代码之家  ›  专栏  ›  技术社区  ›  onefootswill

使用Serilog为消息属性使用消息模板

  •  0
  • onefootswill  · 技术社区  · 6 年前

    我已经采用Serilog来满足我的日志需求。 我(尽我所能)遵循坚实的原则,并因此采纳了这些原则 Steven's adapter 这是一个很好的实现。

    在大多数情况下,这是伟大的。我有一门课叫 LogEntryDetail 其中包含某些属性:

    class LogEntryDetail
    {
        public string Message {get;set;}
        public string MessageTemplate {get;set;}
        public string Properties {get;set;}
    
        // etc. etc.
    }
    

    我会像这样记录LogEntryDetail:

        public void Log(LogEntryDetail logEntryDetail)
        {
            if (ReferenceEquals(null, logEntryDetail.Layer))
            {
                logEntryDetail.Layer = typeof(T).Name;
            }
    
            _logger.Write(ToLevel(logEntryDetail.Severity), logEntryDetail.Exception, logEntryDetail.MessageTemplate, logEntryDetail);
        }
    

    我使用MSSqlServer接收器(Serilog.Sinks.MSSqlServer)记录错误,一切正常。

    我有一个性能记录器,我把它插入我的请求管道。对于这个记录器,我不想保存LogEntry对象中的所有属性。我只想在我创建的表的Message列中保存Message属性。

    所以,通常你打电话的时候 write 在serilog logger上,并传入一个复杂对象,消息列包含整个对象,序列化为JSON。

    我想知道是否有办法指定 MessageTemplate 就像 {Message} {@Message} ,这样数据库中的消息列只包含存储在 Message 财产 对数细节 对象任何其他财产都是多余的,浪费了存储空间。

    当我指定 消息模板 成为 {Message} 这个 消息 属性包含文件的全名 对数细节 类型(包括名称空间)。

    我觉得我离Serilog的MessageTemplate功能很近,只是在理解中遗漏了一些小东西。

    1 回复  |  直到 6 年前
        1
  •  0
  •   onefootswill    6 年前

    我只想解释一下我在这里做了些什么,试图让这两个世界都变得最好。在这里,我们似乎遇到了一个由来已久的开发难题,即牺牲库的特定功能来遵守可靠的原则。我们以前在存储库抽象之类的东西中看到过这一点,这使得不可能利用它们抽象的一些ORM的粒度特性。

    我的SerilogAdapter如下所示:

    public class SerilogLogAdapter<T> : ILogger
    {
        private readonly Serilog.ILogger _logger;
    
        public SerilogLogAdapter(Serilog.ILogger logger)
        {
            _logger = logger;
        }
    
        public void Log(LogEntryDetail logEntryDetail)
        {
            if (ReferenceEquals(null, logEntryDetail.Layer))
            {
                logEntryDetail.Layer = typeof(T).Name;
            }
    
            if (logEntryDetail.MessageTemplate.Equals(MessageTemplates.LogEntryDetailMessageTemplate, StringComparison.Ordinal))
            {
                _logger.Write(ToLevel(logEntryDetail.Severity), logEntryDetail.Exception, logEntryDetail.MessageTemplate, logEntryDetail);
            }
            else
            {
                _logger.Write(ToLevel(logEntryDetail.Severity), logEntryDetail.MessageTemplate, logEntryDetail.Message, logEntryDetail.AdditionalInfo);
            }
        }
    
        private static LogEventLevel ToLevel(LoggingEventType severity) =>
            severity == LoggingEventType.Debug ? LogEventLevel.Debug :
                severity == LoggingEventType.Information ? LogEventLevel.Information :
                    severity == LoggingEventType.Warning ? LogEventLevel.Warning :
                        severity == LoggingEventType.Error ? LogEventLevel.Error :
                            LogEventLevel.Fatal;
    }
    

    如果MessageTemplate是一个代表整个对象的模板,那么它将被记录。否则,可以使用自定义MessageTemplate并记录Message属性以及AdditionalInfo属性(字典)。

    我们至少还从Serilog中挤出了一件事,这是它的优势之一——能够使用不同的消息模板记录日志,并可以按消息模板搜索日志。

    无论如何让我知道它是否能更好!