.Net Core 3.1 - 使用 Microsoft Ilogger 接口为 Serilog 设置 ForContext

mk_*_*_yo 7 c# logging serilog asp.net-core

如何使用来自 的接口来ForContext使用 Serilog 记录器的方法?ILoggerMicrosoft.Extensions.Logging

这是代码:

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");
Run Code Online (Sandbox Code Playgroud)

我真的不想使用ILoggerSerilog 的接口,因为我不希望它是 Serilog 特定的并且它不是通用的。

cod*_*dea 9

ForContextMicrosoft.Extensions.Logging

MicrosoftILogger接口没有该ForContext属性,但是,根据我在该主题上找到的几篇读物,通过此接口传递附加上下文信息的正确方法是使用其方法BeginScope传递值字典,然后调用您的 Logging 方法。

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");
}
Run Code Online (Sandbox Code Playgroud)

使用扩展方法ILogger

我发现自己更喜欢为此目的编写一个扩展方法,以避免到处 using都有语句,并在我想将上下文信息添加到结构化日志记录时使代码中的意图更加清晰:

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();
    };
}
Run Code Online (Sandbox Code Playgroud)

这可以这样调用:

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