mk_yo
mk_yo

Reputation: 780

.Net Core 3.1 - Set ForContext for Serilog with Microsoft Ilogger interface

How do I use the ForContext method for a Serilog logger using the ILogger interface from Microsoft.Extensions.Logging?

Here's the code:

private readonly ILogger<UserService> _logger;

//DI code here

....

//inside some method
_logger.ForContext("CorrelationId", correlationId); // Ilogger doesn't contain ForContext extension method 

_logger.LogInformation("message");

I don't really want to use the ILogger interface from the Serilog as I don't want it to be Serilog-specific and it's not generic.

Upvotes: 10

Views: 5684

Answers (1)

codea
codea

Reputation: 1549

ForContext with Microsoft.Extensions.Logging

The Microsoft ILogger interface does not have the ForContext property, however, according to several readings I could find on the topic, the proper way to pass additional context information via this interface is to use its BeginScope method to pass a dictionary of values and then call your Logging method.

using (logger.BeginScope(new Dictionary<string, object>{ { "ParameterName", 999 } }))
{
    logger.LogInformation(
        "This log entry and any other ones wrapped within this using statement will" +
        "have context added similar to .ForContext with Serilog");
}

Using an extension method on ILogger

I found myself preferring to write an extension method for this purpose to avoid having using statements everywhere and make the intention more clear in my code when I want to add context information to my structured logging:

public static void LogWithContext(this ILogger logger, Action LogAction,
    params KeyValuePair<string, object>[] contextDataParam)
{
    Dictionary<string, object> contextData = new Dictionary<string, object>();
    foreach (KeyValuePair<string,object> kvp in contextDataParam)
    {
        contextData.TryAdd(kvp.Key, kvp.Value);
    }

    using (logger.BeginScope(contextData))
    {
        LogAction.Invoke();
    };
}

And this can be called like this:

logger.LogWithContext(
    () => logger.LogError("Error with {Database}", _options.database),
    new KeyValuePair<string, object>("CallingFunction", nameof(thisFunction)),
    new KeyValuePair<string, object>("UserErrorType", "DB"))

Upvotes: 12

Related Questions