【问题标题】:How to add my own properties to Serilog output template如何将我自己的属性添加到 Serilog 输出模板
【发布时间】:2018-07-13 11:50:34
【问题描述】:

我有一个从服务总线接收消息的小型应用程序,它可以通过几种不同类型的事件为不同的用户发送消息。根据事件的类型,调用不同的函数。我在每个函数中记录信息。

我目前有这个:

var logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console(outputTemplate:
        "[{Timestamp:HH:mm:ss} {Level:u3}] {Message}{NewLine}{Exception}")
    .WriteTo.Loggly()
    .CreateLogger();

...

// logging an event
Log.Information("{UserId} {Event} - Here is my message", "123", "Test Event");

这很好用,但是因为对于这个应用程序,每个日志都将包含日志中的 UserId 和 Event 数据,我想我可以将它们添加到我的输出模板中,以使我的日志记录代码更简洁一些。所以我试过这个:

var logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console(outputTemplate:
      "[{Timestamp:HH:mm:ss} {Level:u3}] {UserId} {Event} - {Message}{NewLine}{Exception}")
    .WriteTo.Loggly()
    .CreateLogger();

...

// logging an event
Log.Information("Here is my message", "123", "Test Event");
Log.Information("Here is my message", new { UserId = "123", Event = "Test Event"});

这些都不起作用,它输出的只是我的消息,它不会通过我传递给它的 UserId 或 Event。

我做错了吗?或者有没有办法做到这一点?

【问题讨论】:

    标签: c# logging serilog


    【解决方案1】:

    如果要添加不属于消息模板的属性,则需要丰富日志上下文。这意味着添加 FromLogContext 丰富器,并将您的属性添加到您记录的事件中。

    Log.Logger = new LoggerConfiguration()
        .Enrich.FromLogContext()
        .MinimumLevel.Information()
        .WriteTo.Console(outputTemplate:
        "[{Timestamp:HH:mm:ss} {Level:u3}] {UserId} {Event} - {Message}{NewLine}{Exception}")
        .CreateLogger();
    
    using (LogContext.PushProperty("UserId", "123"))
    using (LogContext.PushProperty("Event", "Test Event"))
    {
        Log.Information("Here is my message about order {OrderNumber}", 567);
        Log.Information("Here is my message about product {ProductId}", "SomeProduct");
    }
    

    您可以在the documentation 中了解更多关于充实的信息。

    现在我不确定 Loggly。我以前从未使用过它。但是,如果您使用的是 Seq(它来自 Serilog 的创建者并且最适合它),您甚至不需要修改输出模板。添加的属性将自动适用于每个事件。

    正如 Nicholas Blumhardt 通过评论指出的那样,如果您只需要一次性将属性添加到单个记录的事件,您也可以这样做。当我有很多事件属性时,我有时会这样做,这些属性不一定需要显示在消息中,并且仅适用于单个事件。

    Log
       .ForContext("OrderNumber", orderNumber)
       .ForContext("UserId", user.Id)
       .Information("Order submitted");
    

    【讨论】:

    • 虽然丰富器值的解析方式不同吗?它就像 ManagedThreadId,不能传递给 Log.Information。丰富器实现 Enrich 方法,在该方法中为该属性添加属性名称和值。
    • @VidmantasBlazevicius 当您使用 LogContext.PushProperty 时,它将向 using 块范围内的所有语句添加属性。如果这些属性是输出模板的一部分,它们将显示在记录的消息中。否则,它们只是记录事件的不同属性。
    • 感谢您的澄清,我还得出结论,您的答案可能与您获得 OP 想要的行为一样接近。
    • 另一个选项是Log.ForContext("UserId", 123).ForContext("Event", "Test Event").Information("Hello, world!") - 但LogContext.PushProperty() 可能是这个用例更好的API。
    • @NicholasBlumhardt 好点,我已经在答案中添加了示例,并解释了何时可能适合使用。
    【解决方案2】:

    你可以使用Enrich.WithProperty("ProperyName", "PropertyValue")

    观看 https://www.youtube.com/watch?v=OKITQsF6MNc&t=4831s 了解 Asp.Net MVC 中的各种记录器

    Log.Logger = new LoggerConfiguration()
                    .MinimumLevel.Information()
                    .MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning)
                    .MinimumLevel.Override("System", Serilog.Events.LogEventLevel.Warning)
                    .WriteTo.File(new Serilog.Formatting.Json.JsonFormatter(), "D:\\Temp\\Serilogs\\structuredLog.json", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information)
                    .Enrich.FromLogContext()
                    .Enrich.WithMachineName()
                    .Enrich.WithProcessId()
                    .Enrich.WithThreadId()
                    .Enrich.WithProperty("ApplicationName", "Serilogs DemoApplication")
                    .CreateLogger();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-11
      • 1970-01-01
      • 2012-07-25
      • 1970-01-01
      • 2018-04-27
      • 1970-01-01
      • 2015-03-09
      • 1970-01-01
      相关资源
      最近更新 更多