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

serilog格式SourceContext,仅显示程序集名称

  •  19
  • mnieto  · 技术社区  · 6 年前

    我将我的项目配置为使用Serilog来使用依赖注入进行日志记录。 我在类构造函数中使用以下模式:

    namespace FlickPopper.API.Controllers {
    
        public class ValuesController : Controller {
            private ILogger<ValuesController> _logger;
            public MyClass(ILogger<ValuesController> logger) {
               _logger = logger;
            }
        }
    }
    

    通过这种方式,serilog创建记录器调用 Log.ForContext<classname>

    我的设置是:

      "Serilog": {
          "WriteTo": [
            {
              "Name": "RollingFile",
              "Args": {
                "pathFormat": "Logs\\log-{Date}.txt",
                "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] {Message}{NewLine}{Exception}"
              }
            }
          ],
          "Enrich": [ "FromLogContext" ]
        }
    

    因此,日志如下所示:

    2018-01-26 22:20:08 [INF] [FlickPopper.API.Controllers.ValuesController] Get all values
    

    有没有办法将SourceContext属性的格式设置为只在日志中显示程序集名称,比如这样的?

    2018-01-26 22:20:08 [INF] [FlickPopper.API] Get all values
    
    1 回复  |  直到 6 年前
        1
  •  24
  •   CodeFuller    6 年前

    当您使用injected时 ILogger<T> ,引擎盖下Serilog logger由创建 SerilogLoggerProvider 实现 ILoggerProvider 界面此接口只有一种方法:

    public interface ILoggerProvider : IDisposable
    {
        ILogger CreateLogger(string categoryName);
    }
    

    已通过 categoryName 用作的值 {SourceContext} 消息格式的属性。和ASP。NET Core将其作为完全限定名传递(例如。 FlickPopper.API.Controllers.ValuesController ).

    所以这个字符串值不应该在Serilog代码或配置中固定,而应该在ASP中固定。NET Core日志记录基础架构。

    首先,创造这种价值的责任阶层是 Logger<T> 班的实例 记录器(<);T> 在注入时实例化 i触发器(&L);T> 进入你的课堂。这里是 source code 其建造商:

    public class Logger<T> : ILogger<T>
    {
        public Logger(ILoggerFactory factory)
        {
            if (factory == null)
            {
                throw new ArgumentNullException(nameof(factory));
            }
    
            _logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T)));
        }
    
        //  ...
    }
    

    打电话给 TypeNameHelper.GetTypeDisplayName(typeof(T)) 返回传递给的完全限定名称 ILoggerFactory 最终 SerilogLoggerProvider .

    所以如果你想改变这种行为并调整 类别名称 传递给 iLogger工厂 ,您应该有自己的实现 i触发器(&L);T> 进行必要的调用 ILoggerFactory.CreateLogger() . 没那么难,因为 记录器(<);T> 类非常薄,基于 Microsoft.Extensions.Logging.Logger 实施这是一个 记录器(<);T> 除一行生成记录器类别名称外:

    public class LoggerEx<T> : ILogger<T>
    {
        private readonly ILogger _logger;
    
        public LoggerEx(ILoggerFactory factory)
        {
            if (factory == null)
            {
                throw new ArgumentNullException(nameof(factory));
            }
    
            _logger = factory.CreateLogger(typeof(T).Assembly.GetName().Name);
        }
    
        IDisposable ILogger.BeginScope<TState>(TState state)
        {
            return _logger.BeginScope(state);
        }
    
        bool ILogger.IsEnabled(LogLevel logLevel)
        {
            return _logger.IsEnabled(logLevel);
        }
    
        void ILogger.Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            _logger.Log(logLevel, eventId, state, exception, formatter);
        }
    }
    

    您还应该替换的标准实现 i触发器(&L);T> 在您的服务注册中使用此选项:

    services.AddSingleton(typeof(ILogger<>), typeof(LoggerEx<>));

    现在 LoggerEx<T> 将注入控制器和 {源上下文} 将为您创造价值:

    2018-01-27 09:54:21【INF】【测试项目。测试应用】您好!