【.NET Core框架】日志(Logging)
简介
在ASP.NET 4.X中,我们通常使用 log4net, NLog 等来记录日志,但是当我们引用的一些第三方类库使用不同的日志框架时,就比较混乱了。而在 ASP.Net Core 中内置了日志系统,并提供了一个统一的日志接口,ASP.Net Core 系统以及其它第三方类库等都使用这个日志接口来记录日志,而不关注日志的具体实现,这样便可以在我们的应用程序中进行统一的配置,并能很好的与第三方日志框架集成。
涉及的nuget包:
Microsoft.Extensions.Logging.Abstractions:抽象定义;
Microsoft.Extensions.Logging:具体实现;
日志提供程序
日志提供程序就是最终为我们输出日志的组件,如:
- Console
日志将输出到控制台中。 - Debug
日志将通过System.Diagnostics.Debug类进行输出,可以通过VS输出窗口查看。
在 Linux 上,可以在/var/log/message或/var/log/syslog下找到 - EventSource
跨平台日志记录,在Windows上则使用 ETW - Windows EventLog
仅在Windows系统下生效,可通过“事件查看器”进行日志查看。 - 其他常见的三方日志提供程序:
- log4net:流行第三方日志记录提供程序,需引用 Microsoft.Extensions.Logging.Log4Net.AspNetCore
- Serilog:流行第三方日志记录提供程序,需引用 Serilog.AspNetCore
- NLog: 流行第三方日志记录提供程序,需引用 NLog.Web.AspNetCore
在 Host.CreateDefaultBuilder方法中,默认通过调用ConfigureLogging方法添加了Console、Debug、EventSource和EventLog(仅Windows)共四种日志记录提供程序(Logger Provider)
public static IHostBuilder CreateDefaultBuilder(string[] args)
{
//省略....
builder.ConfigureLogging((hostingContext, logging) =>
{
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
if (isWindows)
{
logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);
}
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
if (isWindows)
{
logging.AddEventLog();
}
});
//省略....
}
如果不想使用默认添加的日志提供程序,我们可以通过ClearProviders清除所有已添加的日志记录提供程序,然后添加自己想要的
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddConsole();
});
记录日志
可以使用以下两种方式记录日志:
- 注入ILogger
接口,调用相应方法 - 注入ILoggerFactory,调用ILoggerFactory.CreateLogger(string categoryName)方法创建ILogger
,调用相应方法
一般情况下使用第一种方式就可以,如果想显式的指定categoryName,可以使用ILoggerFactory
在父类中的方法,如果想记录日志,并且类别名称想指定子类名称,可以使用如下方法:
public class BaseClass
{
private ILogger _logger;
public BaseClass(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger(this.GetType().FullName);
}
protected void RecordLog(string log)
{
_logger.LogInformation(log);
}
}
日志类别:我们创建的每一个日志器都指定了一个类别。它可以是任意的字符串,但是约定使用写入类的完整限定名,如:“WebApp.Controllers.ValueController”。
日志级别(LogLevel)
在我们记录日志时,需要指定日志的级别,用于我们输出日志时进行过滤。比如在测试环境中,我们希望提供非常的详细的日志信息,包括一些敏感信息等,但是在生产环境中,我们希望只记录严重的错误,这时候只需要简单的通过配置文件或AddFilter()
方法对日志的过滤级别配置一下就行了。
日志级别按严重程度排序如下:
Trace 、Debug 、Information 、Warning 、Error 、Critical
配置日志
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"LogLevel": {
"Default": "Error"
}
},
"Debug": {
"LogLevel": {
"Microsoft": "None"
}
},
"EventSource": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Trace",
"Microsoft.Hosting.Lifetime": "Trace"
}
}
}
}
Logging结点用于配置日志
Logging.LogLevel:全局配置,对所有日志提供者都有效。Logging.LogLevel结点下的字段是对日志类别设置日志级别
- Default
默认情况下,如果分类没有进行特别配置(即没有在LogLevel中配置),则应用Default的配置。 - Microsoft
所有分类以Microsoft开头的日志均应用Microsoft的配置。例如,Microsoft.AspNetCore.Routing.EndpointMiddleware类别的日志就会应用该配置。 - Microsoft.Hosting.Lifetime
所有分类以Microsoft.Hosting.Lifetime开头的日志均应用Microsoft.Hosting.Lifetime的配置。例如,分类Microsoft.Hosting.Lifetime就会应用该配置,而不会应用Microsoft,因为Microsoft.Hosting.Lifetime比Microsoft更具体。
也可以针对日志提供者进行配置,如上面的Console、Debug、EventSource结点
就像appsettings.{Environment}.json
和appsettings.json
之间的关系一样,Logging.{Provider}.LogLevel
中的配置将会覆盖Logging.LogLevel
中的配置。
例如Logging.Console.LogLevel.Default将会覆盖Logging.LogLevel.Default,Console日志记录器将默认记录Error及其以上级别的日志。
刚才提到了,Windows EventLog比较特殊,它不会继承Logging.LogLevel的配置。EventLog默认日志级别为LogLevel.Warning,如果想要修改,则必须显式进行指定,如:
{
"Logging": {
"EventLog": {
"LogLevel": {
"Default": "Information"
}
}
}
}
配置的筛选原理
当创建ILogger
- 查找匹配该日志记录提供程序的配置。如果找不到,则使用通用配置。
- 然后匹配拥有最长前缀的配置类别。如果找不到,则使用Default配置。
- 如果匹配到了多条配置,则采用最后一条。
- 如果没有匹配到任何配置,则使用MinimumLevel,这是个配置项,默认是LogLevel.Information。
通过程序配置
除了通过配置文件对日志配置,也可以通过程序配置,允许你书写复杂的逻辑
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging
// 针对所有 LoggerProvider 设置 Microsoft 最小日志级别,建议通过配置文件进行配置
.AddFilter("Microsoft", LogLevel.Trace)
// 针对 ConsoleLoggerProvider 设置 Microsoft 最小日志级别,建议通过配置文件进行配置
.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Debug)
// 针对所有 LoggerProvider 进行过滤配置
.AddFilter((provider, category, logLevel) =>
{
// 由于下面单独针对 ConsoleLoggerProvider 添加了过滤配置,所以 ConsoleLoggerProvider 不会进入该方法
if (provider == typeof(ConsoleLoggerProvider).FullName
&& category == typeof(ValuesController).FullName
&& logLevel <= LogLevel.Warning)
{
// false:不记录日志
return false;
}
// true:记录日志
return true;
})
// 针对 ConsoleLoggerProvider 进行过滤配置
.AddFilter<ConsoleLoggerProvider>((category, logLevel) =>
{
if (category == typeof(ValuesController).FullName
&& logLevel <= LogLevel.Warning)
{
// false:不记录日志
return false;
}
// true:记录日志
return true;
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
控制台日志格式配置
在.NET 5中,对控制台日志记录提供程序进行了扩展,预置了三种日志输出格式:Json、Simple、Systemd。
通过扩展方法AddSimpleConsole()
可以添加支持Simple
格式的控制台日志记录提供程序,默认行为与AddConsole()
一致。
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSimpleConsole();
}
你可以通过SimpleConsoleFormatterOptions进行一些自定义配置:
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSimpleConsole(options =>
{
// 一条日志消息展示在同一行
options.SingleLine = true;
options.IncludeScopes = true;
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss ";
options.UseUtcTimestamp = false;
});
}
通过扩展方法AddSystemdConsole()
可以添加支持Systemd
格式的控制台日志记录提供程序。如果你熟悉Linux,那你对它也一定不陌生。
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSystemdConsole();
}
通过扩展方法AddJsonConsole()
可以添加支持Json格式的控制台日志记录提供程序。
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddJsonConsole(options =>
{
options.JsonWriterOptions = new JsonWriterOptions
{
// 启用缩进,看起来更舒服
Indented = true
};
});
}
参考:
https://www.cnblogs.com/xiaoxiaotank/p/15525052.html
https://www.cnblogs.com/RainingNight/tag/Logging/