如何在保持启动的同时让 serilog 丰富器与依赖注入一起工作?

Nib*_*Pig 9 dependency-injection serilog asp.net-core-mvc

这里有一个答案:如何将依赖项传递给 Serilog Enricher?这解释了您可以传入一个实例。

但是要做到这一点,我需要在我的依赖注入代码运行后移动我的记录器设置(在startup.cs

这意味着不会记录启动错误,因为记录器还没有准备好。

有没有办法以某种方式配置 serilog 以在我的Main()方法中运行,但也可以使用 DI 项目丰富数据?尽管 DI 项是单例,但它还有更多的依赖项(主要是数据库连接)。

我已经用谷歌搜索了这个并阅读了一些关于向上下文添加内容的内容,但我一直无法找到一个我可以适应的完整工作示例。

我发现的大多数示例都涉及将代码放入控制器以附加信息,但我希望这对每个日志条目全局可用。

我的主要开始于:

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(elasticUri))
    {
        AutoRegisterTemplate = true,
    })
    .CreateLogger();
Run Code Online (Sandbox Code Playgroud)

在进入 .NET Core MVC 代码之前

CreateWebHostBuilder(args).Build().Run();

我的 DI 对象基本上是一个“UserData”类,其中包含用户名、companyid 等。这些属性在访问时会访问数据库以获取基于某些当前身份的值(尚未实现)。它被我的 DI 注册为单身人士。

Cai*_*ete 10

我建议使用一个简单的中间件,插入到 ASP .NET Core 管道中,用你想要的数据丰富 Serilog 的LogContext,使用你需要的依赖项,让 ASP .NET Core 依赖项注入为你解析依赖项。 .

例如,假设IUserDataService是一个服务,你可以用它来获取你需要的数据,丰富日志,中间件看起来像这样:

public class UserDataLoggingMiddleware
{
    private readonly RequestDelegate _next;

    public UserDataLoggingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context, IUserDataService userDataService)
    {
        var userData = await userDataService.GetAsync();

        // Add user data to logging context
        using (LogContext.PushProperty("UserData", userData))
        {
            await _next.Invoke(context);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

LogContext.PushProperty上面是做丰富,添加一个属性调用UserData到当前执行的日志上下文。

IUserDataService只要您在.NET Core 中注册它,ASP .NET Core 就会负责解析Startup.ConfigureServices

当然,要使其正常工作,您必须:

1. 告诉 Serilog 从 Log 上下文中丰富日志,通过调用Enrich.FromLogContext(). 例如

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(Configuration)
    .Enrich.FromLogContext() // <<======================
    .WriteTo.Console(
        outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} " +
                        "{Properties:j}{NewLine}{Exception}")
    .CreateLogger();
Run Code Online (Sandbox Code Playgroud)

2. 将您的中间件添加到管道中,在您的Startup.Configure. 例如

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ...

    app.UseMiddleware<UserDataLoggingMiddleware>();

    // ...

    app.UseMvc();
}
Run Code Online (Sandbox Code Playgroud)

  • @MichaelFreidgeim LogContext 是一个静态类,但[它通过 `AsyncLocal`/`ThreadStatic` 是线程安全的](https://github.com/serilog/serilog/blob/5e2164756efb6023a548b4eb91a71ed7edc3d9e1/src/Serilog/Context/LogContext.cs# L54-L61)。即每个线程都有自己的 LogContext,尽管它是通过静态类访问的。请求不共享相同的 LogContext。 (3认同)