1
votes

I am using serilog with asp net core 3

It is setup and logging exceptions automatically - so i have no error handling to log the errors.

I was attempting to add extra context properties to logged items, and have added middleware to log these.

LogContext.PushProperty("Email", email);
LogContext.PushProperty("Url", url);

These are added if i manually log myself but any logs added automatically when an error occurs does not have these items added.

Any ideas?

NOTE: i have read this... https://blog.datalust.co/smart-logging-middleware-for-asp-net-core/ This is the closest i have found to working around the issue, but this catches the exception and manually logs it, which is a shame if this is the only way it can be done.

1
similar yes but hopefully i have added some more detail. If i catch the error and log it myself my code works - if i log an information or any other type of log it works. what doesnt work is it doesnt add the context items for errors its logged itself. As i have read, its in a different "context" or its "popped off the stack" but this doesnt help, you would think that this was a basic requirement for error logging? - sianabanana
Definitely not saying this is a dup (for a start the question is asked more directly). LogContext.PushProperty / Enrich.FromLogContext definitely work on the assumption of a using and/or stackiness; the values are (and can only be) captured when a Logging call is made (which requires that to be still in the same context, not having unrolled everything and completed the teardown). I've not delved into the things one can do with asp.net core to stash context such that it can travel from such an inner context out to an exception handler middleware, but for me thats not Serilog dept. - Ruben Bartelink
Ok so what i have implemented is the only solution i guess. I have a middleware class that wraps execution, captures the errors and manually logs them, then doesnt re throw, so the automatic error logging is then not called) To me this is a shame, as things seem really good/useful, but this seems like a hack/workaround to me - sianabanana
Hm I'm pretty sure the DiagnosticContext or something can flow context from request processing out to global request logging and global exception logging. I remain hopeful you'll get a proper answer. Also not sure if yoiu're aware but the most recent overview article by Nick covers ASP.NET Core 3 - Ruben Bartelink

1 Answers

0
votes

At first, LogContext is a stack; properties that are pushed onto the stack must be popped back off by disposing the object returned from PushProperty():

using (LogContext.PushProperty("Email", email))
using (LogContext.PushProperty("Url", url)){
   
    // middleware code
   ...
}

Otherwise, the behavior may be non-deterministic.

but any logs added automatically when an error occurs does not have these items added

I assume that error logging occurs outside of the scope, where these properties don't exist. In this case, try ThrowContextEnricher to enrich the exception log with properties from the original context where the exception was thrown.

// call it once on app startup
ThrowContextEnricher.EnsureInitialized();

...


// then each throwing will capture context,
// so you can enrich log in exception handler:
catch (Exception ex)
{
    using (LogContext.Push(new ThrowContextEnricher()))
    {
        Log.Error(ex, "Exception!"); 
    }
}

Or simply register ThrowContextEnricher globally at LoggerConfiguration (in this case ThrowContextEnricher.EnsureInitialized() is not required). So every exception log will be enriched:

Log.Logger = new LoggerConfiguration()
    .Enrich.With<ThrowContextEnricher>()
    .Enrich.FromLogContext()
    ...
    .CreateLogger();

Disclaimer: I am the author of that library, and I also left an example in this answer.