如何使用 Serilog 在 Json 中获取日志级别 - .NET Core 3.1
How To Get Log Level in Json with Serilog - .NET Core 3.1
我是 Serilog
的新手,我正在尝试确定如何使用 log level
和 date time
将序列化的 json
发送到 console
场地。 structured data
下的文档中似乎没有任何信息。
这是我在 Startup.cs
:
中调用的代码
private void LoggerLoop(ILogger<Startup> logger)
{
RabbitModel rb = new RabbitModel
{
Id = 1,
DeviceNum = 1,
DeviceName = "Device 1",
InputNum = 1,
InputName = "Input 1",
InputState = 1,
OnPhrase = "On",
OffPhrase = "Off",
When = "2020-01-01T22:45:00.1124303+00:00"
};
while (true)
{
logger.LogInformation("{@rb}", rb);
Thread.Sleep(1000);
}
}
这是我的输出:
[14:28:22 INF] {"Id": 1, "DeviceNum": 1, "DeviceName": "Device 1", "InputNum": 1, "InputName": "Input 1", "InputState": 1, "OnPhrase": "On", "OffPhrase": "Off", "When": "2020-01-01T22:45:00.1124303+00:00", "$type": "RabbitModel"}
我确实注意到它添加了一个字段 $type
,想知道是否可以将 [14:28:22 INF]
添加到 json
?
根据12 factor app,应用程序应将所有日志写入stdout
/stderr
。
然后您需要将所有日志收集在一起,并为此目的提供到一个或多个最终目的地以供查看(Elasticserach). Open-source log routers (such as FluentBit, Fluentd and Logplex)的路由。
因此,该应用从不关心其日志的路由或存储。在 dotnet 应用程序中,您可以使用 Serilog
轻松实现它
假设我们在 appsettings.json
中有以下记录器设置
"Logging": {
"OutputFormat": "console",
"MinimumLevel": "Information"
}
我们可以创建一个扩展方法
private static IWebHostBuilder CreateWebHostBuilder() =>
WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.UseLogging();
}
可以以纯文本和elasticsearch 格式将日志写入控制台。纯文本日志对开发很有用,因为它更易于阅读。在生产环境中,我们启用 elasticsearch 格式并仅在 Kibana 中查看所有日志。
带注释的扩展代码:
public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder, string applicationName = null) =>
webHostBuilder
.UseSetting("suppressStatusMessages", "True") // disable startup logs
.UseSerilog((context, loggerConfiguration) =>
{
var logLevel = context.Configuration.GetValue<string>("Logging:MinimumLevel"); // read level from appsettings.json
if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))
{
level = LogEventLevel.Information; // or set default value
}
// get application name from appsettings.json
applicationName = string.IsNullOrWhiteSpace(applicationName) ? context.Configuration.GetValue<string>("App:Name") : applicationName;
loggerConfiguration.Enrich
.FromLogContext()
.MinimumLevel.Is(level)
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.Enrich.WithProperty("Environment", context.HostingEnvironment.EnvironmentName)
.Enrich.WithProperty("ApplicationName", applicationName);
// read other Serilog configuration
loggerConfiguration.ReadFrom.Configuration(context.Configuration);
// get output format from appsettings.json.
var outputFormat = context.Configuration.GetValue<string>("Logging:OutputFormat");
switch (outputFormat)
{
case "elasticsearch":
loggerConfiguration.WriteTo.Console(new ElasticsearchJsonFormatter());
break;
default:
loggerConfiguration.WriteTo.Console(
theme: AnsiConsoleTheme.Code,
outputTemplate: "[{Timestamp:yy-MM-dd HH:mm:ss.sssZ} {Level:u3}] {Message:lj} <s:{Environment}{Application}/{SourceContext}>{NewLine}{Exception}");
break;
}
});
当 OutputFormat
为 elasticsearch
时,日志将像
{"@timestamp":"2020-02-07T16:02:03.4329033+02:00","level":"Information","messageTemplate":"Get
customer by id: {CustomerId}","message":"Get customer by id:
20","fields":{"CustomerId":20,"SourceContext":"Customers.Api.Controllers.CustomerController","ActionId":"c9d77549-bb25-4f87-8ea8-576dc6aa1c57","ActionName":"Customers.Api.Controllers.CustomerController.Get
(Customers.Api)","RequestId":"0HLTBQP5CQHLM:00000004","RequestPath":"/v1/customers","CorrelationId":"daef8849b662117e","ConnectionId":"0HLTBQP5CQHLM","Environment":"Development","ApplicationName":"API","Timestamp":"2020-02-07T14:02:03.4329033Z"}}
其他情况(仅用于调试)
[20-02-07 13:59:16.16Z INF] Get customer by id: 20
然后你应该配置日志路由器从容器中收集日志并将其发送到 Elasticsearch。
如果所有日志都是 structured,它会改进 Kibana 中的搜索和创建索引。
我是 Serilog
的新手,我正在尝试确定如何使用 log level
和 date time
将序列化的 json
发送到 console
场地。 structured data
下的文档中似乎没有任何信息。
这是我在 Startup.cs
:
private void LoggerLoop(ILogger<Startup> logger)
{
RabbitModel rb = new RabbitModel
{
Id = 1,
DeviceNum = 1,
DeviceName = "Device 1",
InputNum = 1,
InputName = "Input 1",
InputState = 1,
OnPhrase = "On",
OffPhrase = "Off",
When = "2020-01-01T22:45:00.1124303+00:00"
};
while (true)
{
logger.LogInformation("{@rb}", rb);
Thread.Sleep(1000);
}
}
这是我的输出:
[14:28:22 INF] {"Id": 1, "DeviceNum": 1, "DeviceName": "Device 1", "InputNum": 1, "InputName": "Input 1", "InputState": 1, "OnPhrase": "On", "OffPhrase": "Off", "When": "2020-01-01T22:45:00.1124303+00:00", "$type": "RabbitModel"}
我确实注意到它添加了一个字段 $type
,想知道是否可以将 [14:28:22 INF]
添加到 json
?
根据12 factor app,应用程序应将所有日志写入stdout
/stderr
。
然后您需要将所有日志收集在一起,并为此目的提供到一个或多个最终目的地以供查看(Elasticserach). Open-source log routers (such as FluentBit, Fluentd and Logplex)的路由。
因此,该应用从不关心其日志的路由或存储。在 dotnet 应用程序中,您可以使用 Serilog
轻松实现它假设我们在 appsettings.json
中有以下记录器设置"Logging": {
"OutputFormat": "console",
"MinimumLevel": "Information"
}
我们可以创建一个扩展方法
private static IWebHostBuilder CreateWebHostBuilder() =>
WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.UseLogging();
}
可以以纯文本和elasticsearch 格式将日志写入控制台。纯文本日志对开发很有用,因为它更易于阅读。在生产环境中,我们启用 elasticsearch 格式并仅在 Kibana 中查看所有日志。
带注释的扩展代码:
public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder, string applicationName = null) =>
webHostBuilder
.UseSetting("suppressStatusMessages", "True") // disable startup logs
.UseSerilog((context, loggerConfiguration) =>
{
var logLevel = context.Configuration.GetValue<string>("Logging:MinimumLevel"); // read level from appsettings.json
if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))
{
level = LogEventLevel.Information; // or set default value
}
// get application name from appsettings.json
applicationName = string.IsNullOrWhiteSpace(applicationName) ? context.Configuration.GetValue<string>("App:Name") : applicationName;
loggerConfiguration.Enrich
.FromLogContext()
.MinimumLevel.Is(level)
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.Enrich.WithProperty("Environment", context.HostingEnvironment.EnvironmentName)
.Enrich.WithProperty("ApplicationName", applicationName);
// read other Serilog configuration
loggerConfiguration.ReadFrom.Configuration(context.Configuration);
// get output format from appsettings.json.
var outputFormat = context.Configuration.GetValue<string>("Logging:OutputFormat");
switch (outputFormat)
{
case "elasticsearch":
loggerConfiguration.WriteTo.Console(new ElasticsearchJsonFormatter());
break;
default:
loggerConfiguration.WriteTo.Console(
theme: AnsiConsoleTheme.Code,
outputTemplate: "[{Timestamp:yy-MM-dd HH:mm:ss.sssZ} {Level:u3}] {Message:lj} <s:{Environment}{Application}/{SourceContext}>{NewLine}{Exception}");
break;
}
});
当 OutputFormat
为 elasticsearch
时,日志将像
{"@timestamp":"2020-02-07T16:02:03.4329033+02:00","level":"Information","messageTemplate":"Get customer by id: {CustomerId}","message":"Get customer by id: 20","fields":{"CustomerId":20,"SourceContext":"Customers.Api.Controllers.CustomerController","ActionId":"c9d77549-bb25-4f87-8ea8-576dc6aa1c57","ActionName":"Customers.Api.Controllers.CustomerController.Get (Customers.Api)","RequestId":"0HLTBQP5CQHLM:00000004","RequestPath":"/v1/customers","CorrelationId":"daef8849b662117e","ConnectionId":"0HLTBQP5CQHLM","Environment":"Development","ApplicationName":"API","Timestamp":"2020-02-07T14:02:03.4329033Z"}}
其他情况(仅用于调试)
[20-02-07 13:59:16.16Z INF] Get customer by id: 20
然后你应该配置日志路由器从容器中收集日志并将其发送到 Elasticsearch。
如果所有日志都是 structured,它会改进 Kibana 中的搜索和创建索引。