[英]Why the DictionaryValue is converted to ScalarValue in Serilog in ASP.NET Core
我的 Serilog 配置如下:
LevelSwitch.MinimumLevel = LogEventLevel.Verbose;
var loggerConfiguration =
new LoggerConfiguration()
.MinimumLevel.ControlledBy(LevelSwitch)
.Enrich.FromLogContext()
.WriteTo.Conditional(
IsDictionaryValue,
cfg => cfg.Console());
services.AddLogging(configure => configure.AddSerilog());
其中IsDictionaryValue
定義為:
static bool IsDictionaryValue(LogEvent logEvent)
{
if (logEvent.Properties.TryGetValue("LOG_TEST", out LogEventPropertyValue value))
{
return value is DictionaryValue;
}
return false;
}
嘗試記錄跟蹤和信息消息:
var logger = loggerFactory.CreateLogger<Program>();
var dict = new Dictionary<string, object>
{
{ "val1", 1 },
{ "val2", 2 },
{ "val3", "_3" },
};
logger.LogTrace("{@LOG_TEST}", dict);
logger.LogInformation("{@LOG_TEST}", dict);
問題是:
為什么在 ASP.NET Core web 應用程序中,日志跟蹤消息正確創建DictionaryValue
並且IsDictionaryValue
的結果為true
,但是當我記錄信息消息時, LogEventPropertyValue
值為ScalarValue
。
但
此“錯誤”僅存在於 ASP.NET Core web 應用程序中。 當我在控制台應用程序中使用相同的 Serilog 配置時,LogTrace 和 LogInformation 都正確地將dict
字典表示為DictionaryValue
。
更新:
DictionaryValue
中LogEventPropertyValue
的類型
日志方法 | 控制台應用 | Web 應用程序 |
---|---|---|
日志跟蹤 | 字典值 | 字典值 |
日志調試 | 字典值 | 字典值 |
日志信息 | 字典值 | 標量值 |
日志警告 | 字典值 | 標量值 |
日志錯誤 | 字典值 | 標量值 |
邏輯臨界 | 字典值 | 標量值 |
問題:
在 ASP.NET Core 中注冊了一些默認LoggerProviders
,例如:
1. Microsoft.Extensions.Logging.Console.ConsoleLogger
2. Microsoft.Extensions.Logging.Debug.DebugLogger
3. Microsoft.Extensions.Logging.EventSource.EventSourceLogger
4. Microsoft.Extensions.Logging.EventLog.EventLogLogger
當你配置 serilog
services.AddLogging(configure => configure.AddSerilog());
添加了第五個LoggerProvider
:
5. Serilog.Extensions.Logging.SerilogLogger
其他提供者的默認配置是LogLevel:Information
。 這就是LogTrace
和LogDebug
在 Web 應用程序中工作的原因。 因此,如果您調用LogInformation
,前四個記錄器提供程序會命中TState
namespace Microsoft.Extensions.Logging
{
internal class Logger : ILogger
{
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
}
}
並將原始dictionary
轉換為string
。 當第五個記錄器提供程序(出SerilogLogger
)開始播放時,它無法解析DictionaryValue
因為TState
是string
解決方案:
將SerilogLogger
設置為第一個LoggerProvider
:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging(cfg => cfg
.ClearProviders()
.AddSerilog()
.AddConsole()
.AddDebug()
.AddEventSourceLogger()
.AddEventLog());
}
並且因為SerilogLoggerProvider
是在IHostBuilder
的Program.cs
中注冊的,所以在services.AddLogging(configure => configure.AddSerilog());
中的AddSerilog()
沒有必要。
services.AddLogging();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.