有什么方法可以稍后在下游 class 中读取 Serilog 的 LogContext?

Any way to read Serilog's LogContext later in a downstream class?

我正在将值推送到 .NET Core Web 应用程序的中间件 class 中的 Serilog LogContext:-

using LogContext.PushProperty("MyAct", "some clever joke") ...

是否可以在下游 class 中读取 MyAct 属性 的值?我在 LogContext 上看不到任何有前途的东西 class - 似乎是一个只写实体,但也许我遗漏了什么?

Serilog 不提供让您只读取 LogContext 中的值。

通常 PushProperty 将其隐藏,并且 Enrich.FromLogContext 负责获取上下文信息,这些信息将伴随解构的消息和令牌,因为日志记录调用是 捕获 他们进入 LogEvent 然后将被传递到链 sinks.

这真的引出了一个问题:why do you feel you need to do this?


实际回答问题:虽然底层 API 可能以可用的方式公开;我会去 https://github.com/serilog/serilog - LogContext 实现和测试都在那个核心仓库中。

我也有类似的问题。我想为我的中间件编写一个单元测试来推送上下文,并想测试我是否推送了正确的上下文信息。

我通过创建一个写入观察者的记录器解决了这个问题。 (将 Serilog.Sinks.Observable 添加到我的测试依赖项中)

private class LogEventStoreObserver : IObserver<LogEvent>
{
   public LogEvent LastEvent { get; set; }
   public void OnCompleted() { }
   public void OnError(Exception error) { }
   public void OnNext(LogEvent value) 
   {
       LastEvent = value;
    }
}

Log.Logger = new LoggerConfiguration().WriteTo.Observers(events =>
                 events.Subscribe(logObserver))
                       .Enrich.FromLogContext()
                       .CreateLogger();

现在我可以像这样读取包含 LogContext 的 LogEvent 属性:

// Setup
LogEvent testLogEvent = null;
nextMock.Setup(_ => _(It.IsAny<HttpContext>())).Callback<HttpContext>((_) =>
    {
        Log.Information("Test");
        testLogEvent = logObserver.LastEvent;
    });

// Act
await middleware.InvokeAsync(httpContext);

// Verify
testLogEvent.Properties.Should().ContainKey("mySpecialContext");