[英]Why the DictionaryValue is converted to ScalarValue in Serilog in ASP.NET Core
My Serilog configuration is the following:我的 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());
where the IsDictionaryValue
is defined as:其中
IsDictionaryValue
定义为:
static bool IsDictionaryValue(LogEvent logEvent)
{
if (logEvent.Properties.TryGetValue("LOG_TEST", out LogEventPropertyValue value))
{
return value is DictionaryValue;
}
return false;
}
trying to log trace and information message:尝试记录跟踪和信息消息:
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);
The question is:问题是:
Why in ASP.NET Core web app the log trace message correctly creates DictionaryValue
and the result of IsDictionaryValue
is true
, but when I log information message, the LogEventPropertyValue
value is ScalarValue
.为什么在 ASP.NET Core web 应用程序中,日志跟踪消息正确创建
DictionaryValue
并且IsDictionaryValue
的结果为true
,但是当我记录信息消息时, LogEventPropertyValue
值为ScalarValue
。
BUT但
This "bug" is only in ASP.NET Core web app.此“错误”仅存在于 ASP.NET Core web 应用程序中。 When I use the same Serilog configuration in Console app, both LogTrace and LogInformation, correctly represents the
dict
dictionary as DictionaryValue
.当我在控制台应用程序中使用相同的 Serilog 配置时,LogTrace 和 LogInformation 都正确地将
dict
字典表示为DictionaryValue
。
Update:更新:
type of LogEventPropertyValue
in DictionaryValue
DictionaryValue
中LogEventPropertyValue
的类型
Log method![]() |
Console App![]() |
Web app ![]() |
---|---|---|
LogTrace![]() |
DictionaryValue![]() |
DictionaryValue![]() |
LogDebug![]() |
DictionaryValue![]() |
DictionaryValue![]() |
LogInformation![]() |
DictionaryValue![]() |
ScalarValue![]() |
LogWarning![]() |
DictionaryValue![]() |
ScalarValue![]() |
LogError![]() |
DictionaryValue![]() |
ScalarValue![]() |
LogCritical![]() |
DictionaryValue![]() |
ScalarValue![]() |
The problem:问题:
In ASP.NET Core are registered some default LoggerProviders
like:在 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
and when you configure serilog当你配置 serilog
services.AddLogging(configure => configure.AddSerilog());
the fifth LoggerProvider
was added:添加了第五个
LoggerProvider
:
5. Serilog.Extensions.Logging.SerilogLogger
The default configuration for other providers is LogLevel:Information
.其他提供者的默认配置是
LogLevel:Information
。 This is the reason why LogTrace
and LogDebug
works in Web app.这就是
LogTrace
和LogDebug
在 Web 应用程序中工作的原因。 So if you call LogInformation
the first four logger providers hits the TState
in因此,如果您调用
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)
}
}
and it converts the original dictionary
to string
.并将原始
dictionary
转换为string
。 And when the fifth logger provider (out SerilogLogger
) comes to play, it cannot resolve DictionaryValue
because the TState
is string
当第五个记录器提供程序(出
SerilogLogger
)开始播放时,它无法解析DictionaryValue
因为TState
是string
The solution:解决方案:
Set the SerilogLogger
as the first LoggerProvider
:将
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());
}
and because the SerilogLoggerProvider
is registered in Program.cs
within IHostBuilder
, the AddSerilog()
in services.AddLogging(configure => configure.AddSerilog());
并且因为
SerilogLoggerProvider
是在IHostBuilder
的Program.cs
中注册的,所以在services.AddLogging(configure => configure.AddSerilog());
中的AddSerilog()
is not necessary.没有必要。
services.AddLogging();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.