始终使用serilog记录上下文数据

LP1*_*P13 4 logging serilog

我正在使用Serilog进行日志记录。对于每个日志,我想记录上下文信息,例如用户名和一些其他上下文信息。所以我用下面的静态方法创建了包装器

public static class MyLogger
{    
    public static void Error(Exception ex, string messageTemplate, params object[] propertyvalues)
    {
        var properties = new List<object>(propertyvalues);
        if (HttpContext.Current != null && HttpContext.Current.User != null && HttpContext.Current.User.Identity != null)
        {
            var contextInfo = new
            {                    
                UserName = HttpContext.Current.User.Identity.Name
            };
            messageTemplate += "{@ContextInfo}";
            properties.Add(contextInfo);
        }

        //serilog log
        Log.Error(ex, messageTemplate, properties.ToArray());
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将错误记录为

      MyLogger.Error(exception,"{@SomeMetadata}",metadata);
Run Code Online (Sandbox Code Playgroud)

这是可行的,但是有没有更好的方法在serilog中包含上下文信息

更新1

所以我根据建议创建了一个浓缩器

public class HttpContextEnricher: ILogEventEnricher
{
    LogEventProperty _cachedProperty;

    public const string EnvironmentUserNamePropertyName = "UserName";

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        _cachedProperty = _cachedProperty ?? propertyFactory.CreateProperty(EnvironmentUserNamePropertyName, GetUserName());
        logEvent.AddPropertyIfAbsent(_cachedProperty);
    }

    private string GetUserName()
    {
        if (HttpContext.Current != null && HttpContext.Current.User != null && HttpContext.Current.User.Identity != null)
        {
            return HttpContext.Current.User.Identity.Name;
        }

        return string.Empty;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我该如何调用它?With我应该使用哪种方法?

  Log.Logger = new LoggerConfiguration()
            .Enrich.With???????
            .ReadFrom.AppSettings()
            .CreateLogger();
Run Code Online (Sandbox Code Playgroud)

更新2
我创建了扩展方法,然后在配置日志记录时使用它

public static class HttpContextLoggerConfigurationExtensions
{
    public static LoggerConfiguration WithUserName(
        this LoggerEnrichmentConfiguration enrichmentConfiguration)
    {
        if (enrichmentConfiguration == null) throw new ArgumentNullException(nameof(enrichmentConfiguration));
        return enrichmentConfiguration.With<HttpContextEnricher>();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在Application_Start事件中的global.asax中配置记录器

 Log.Logger = new LoggerConfiguration()
            .Enrich.WithUserName()
            .ReadFrom.AppSettings()
            .CreateLogger();
Run Code Online (Sandbox Code Playgroud)

我注意到每次登录时,richer都会被调用,它返回UserName,但不会在日志中记录UserName。我在日志中看到了我的消息,但没有看到UserName属性。我正在使用Windows EventLog Sink

我正在记录信息

       Log.Information("Some message");
Run Code Online (Sandbox Code Playgroud)

和错误为

       Log.Error(exception, "ErrorID={ErrorID}",someid);
Run Code Online (Sandbox Code Playgroud)

我想念什么?

Cai*_*ete 6

使用Serilog有几种不同的方法。您可以使用在应用程序启动时配置的Enricher(配置日志记录时),并且在记录消息时会自动调用它,并且可以将所需的其他属性添加到Log上下文中。

另一种方法是在每个请求的开始时挂入Web应用程序框架调用的事件,然后将属性添加到Log上下文。

另一种方法是在由DI容器解析记录器实例时添加上下文属性(如果使用的是)。


  • 浓缩样品

https://github.com/serilog-web/owin/blob/master/src/SerilogWeb.Owin/Owin/RequestContextMiddleware.cs

https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpRequestClientHostIPEnricher.cs


  • 上下文PushProperty示例

https://web.archive.org/web/20171207095449/http://mylifeforthecode.com/enriching-serilog-output-with-httpcontext-information-in-asp-net-core/


  • Autofac Serilog集成

https://github.com/nblumhardt/autofac-serilog-integration