如何使serilog扩充程序与依赖项注入一起工作,同时又保持启动状态? [英] How do I get a serilog enricher to work with dependency injection while keeping it on startup?

查看:87
本文介绍了如何使serilog扩充程序与依赖项注入一起工作,同时又保持启动状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有一个答案:我如何将依赖项传递给Serilog Enricher吗?这说明您可以传入实例.

但是,在我的依赖项注入代码运行后(在 startup.cs 中),我需要移动记录器设置

这意味着不会记录启动错误,因为记录器尚未准备好.

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

我已经在Google上进行了搜索,并阅读了一些有关将内容添加到上下文中的内容,但是我一直找不到能够适应的完整工作示例.

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

我的主菜单以:

开头

  Log.Logger = new LoggerConfiguration().Enrich.FromLogContext().WriteTo.Elasticsearch(新的ElasticsearchSinkOptions(新的Uri(elasticUri)){AutoRegisterTemplate = true,}).CreateLogger(); 

在进入.NET Core MVC代码之前

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

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

解决方案

我建议您使用插入到ASP .NET Core管道中的简单中间件来丰富Serilog的

上面的

LogContext.PushProperty 正在做扩充,在当前执行的日志上下文中添加一个名为 UserData 的属性.

只要您在 Startup.ConfigureServices 中注册了 IUserDataService ,ASP .NET Core就会解决它.

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

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

  Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(配置).Enrich.FromLogContext()//<< ======================.WriteTo.Console(outputTemplate:"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}" +"{属性:j} {NewLine} {Exception}").CreateLogger(); 

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

  public void Configure(IApplicationBuilder应用程序,IHostingEnvironment env){//...app.UseMiddleware< UserDataLoggingMiddleware>();//...app.UseMvc();} 

There is an answer here: How do I pass a dependency to a Serilog Enricher? which explains you can pass an instance in.

However to do that I would need to move my logger setup after my dependency injection code has ran (in the startup.cs)

This means that startup errors won't be logged because the logger won't be ready yet.

Is there a way to somehow configure serilog to run in my Main() method, but also enrich data with a DI item? The DI item has further dependencies (mainly on database connection) although it is a singleton.

I've googled this and read something about adding things to a context, but I've been unable to find a complete working example that I can adapt.

Most of the examples I've found involve putting code into the controller to attach information, but I want this to be globally available for every single log entry.

My Main starts with :

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

Before going into the .NET Core MVC code

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

My DI object is basically a "UserData" class that contains username, companyid, etc. which are properties that hit the database when accessed to get the values based on some current identity (hasn't been implemented yet). It's registered as a singleton by my DI.

解决方案

I would suggest using a simple middleware that you insert in the ASP .NET Core pipeline, to enrich Serilog's LogContext with the data you want, using the dependencies that you need, letting the ASP .NET Core dependency injection resolve the dependencies for you...

e.g. Assuming IUserDataService is a service that you can use to get the data you need, to enrich the log, the middleware would look something like this:

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);
        }
    }
}

LogContext.PushProperty above is doing the enrichment, adding a property called UserData to the log context of the current execution.

ASP .NET Core takes care of resolving IUserDataService as long as you registered it in your Startup.ConfigureServices.

Of course, for this to work, you'll have to:

1. Tell Serilog to enrich the log from the Log context, by calling Enrich.FromLogContext(). e.g.

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();

2. Add your middleware to the pipeline, in your Startup.Configure. e.g.

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

    app.UseMiddleware<UserDataLoggingMiddleware>();

    // ...

    app.UseMvc();
}

这篇关于如何使serilog扩充程序与依赖项注入一起工作,同时又保持启动状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆