AngryHacker
AngryHacker

Reputation: 61636

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

I'm pushing values to the Serilog LogContext in a middleware class of a .NET Core web app:-

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

Is it possible to read the value for MyAct property in a downstream class? I don't see anything promising on the LogContext class - seems like a write only entity, but maybe I am missing something?

Upvotes: 4

Views: 2436

Answers (2)

geipette
geipette

Reputation: 31

I have a similar problem. I want to write a Unit test for my Middleware that pushes context and want to test if I am pushing the right context information.

I solved it by creating a Logger that writes to an observer. (Adding the Serilog.Sinks.Observable to my test dependencies)

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

Now I can read the LogEvent properties which contains the LogContext like this:

// 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");

Upvotes: 2

Ruben Bartelink
Ruben Bartelink

Reputation: 61865

Serilog does not provide for you to Just Read the values from the LogContext.

Normally the PushProperty stashes it, and Enrich.FromLogContext is charged with grabbing the contextual information that will accompany the destructured message and tokens as the logging call is capturing them into the LogEvent that'll then be passed to the chain of sinks.

Really this begs the question: why do you feel you need to do this?


Actually answering the question: It is possible the underlying APIs are exposed in a usable fashion though; I'd go to https://github.com/serilog/serilog - the LogContext impl and tests are all in that core repo.

Upvotes: 3

Related Questions