NETCore 支持适用于各种内置和第三方日志记录提供程序的日志记录 API。
我们都知道,Netcore为我们提供了丰富的扩展库,涉及记录输出日志到不同的地方以及对不同的需求分别控制其日志级别。下面我们来看看如何将日志记录 API 与内置提供程序一起使用。
依赖包
Netcore提供了丰富的扩展来支持日志的不同输出需求
- Microsoft.Extensions.Logging
- Microsoft.Extensions.Logging.Abstractions
- Microsoft.Extensions.Logging.Console
- Microsoft.Extensions.Logging.Debug
- Microsoft.Extensions.Logging.TraceSource
日志级别定义
每个日志都指定了一个 LogLevel 值。 日志级别指示严重性或重要程度。
public enum LogLevel:Enum { Trace,//跟踪 = 0 Debug,//调试 = 1 Information,//信息 = 2 Warning,//警告 = 3 Error,//错误 = 4 Critical,//严重 = 5 None//禁止显示所有日志=6 }
一般的,使用日志级别控制写入到特定存储介质或显示窗口的日志输出量。
例如:
生产中:
- 如果通过 Information 级别在 Trace 处记录,则会生成大量详细的日志消息。 为控制成本且不超过数据存储限制,请通过 Information 级别消息将 Trace 记录到容量大、成本低的数据存储中。
- 如果通过 Critical 级别在 Warning 处记录,通常生成的日志消息更少且更小。 因此,成本和存储限制通常不是问题,而这使得在选择数据信息时更为灵活。
在开发过程中:
- 通过 Critical 消息将 Warning 记录到控制台。
- 在疑难解答时通过 Information 消息添加 Trace。
代码演示
若要创建日志,请使用 ILogger<TCategoryName> 对象。 在 Web 应用或托管服务中,由依赖关系注入 (DI) 获取 ILogger。 在非主机控制台应用中,使用 LoggerFactory 来创建 ILogger。
我们先来看一下使用LoggerFactory创建ILogger的方式。
{ ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider(); //创建指定名称的logger ILoggerFactory loggerFactory = serviceProvider.GetService<ILoggerFactory>(); ILogger logger = loggerFactory.CreateLogger("alogger"); logger.LogTrace("trace"); logger.LogDebug("debug"); logger.LogInformation("information"); logger.LogWarning("warning"); }
从以上代码中,我们可以看到,首先,我们需要通过服务提供者Service-Provider的GetService方法来获取一个ILoggerFactory对象,接着可通过该对象来创建指定名称的日志记录器。
我们再来看一下如何通过DI获取ILogger。
我们可以先看一下以下代码,该代码是默认的aspnetcore网站的默认控制器中的代码
private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; }
通过以上方式,即可获取到对应控制器的日志对象并进行日志操作,其实,这里就是使用的依赖注入框架来获取ILogger的。
那么同样的,在当前的控制台程序内,我们可以通过以下语句来获取日志对象。
ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider(); ILogger logger = serviceProvider.GetService<ILogger<Program>>();
是不是很简单呢?不过需要注意一下,这里是生成主机后从 DI 获取 ILogger实例,但并不直接支持在主机构造期间进行日志记录。 但是,可以使用单独的记录器。换句话说,就是可以在CreateHostBuilder函数中进行配置。
了解完日志记录的2种方式,那我们在平常使用时,一般推荐哪种方式呢?我们比较推荐第二种,即通过依赖注入框架获取的方式,毕竟asp.net core自身也是如此使用的,这方式的好处是在服务中直接定义ILogger,这样日志对象的命名是确定的,是命名空间+类名的方式,并且可在操作服务时直接操作日志。
比如,我们先来生成一个服务。
public class OrderService { ILogger<OrderService> logger; public OrderService(ILogger<OrderService> logger) { this.logger = logger; } public void PrintLog() { logger.LogDebug(" Debug: Time now:{time}",DateTime.Now.ToString()); logger.LogInformation(" info: Time now:{time}",DateTime.Now.ToString()); } }
接着,在startup的Configure方法内或Program的main方法里通过以下方式即可获取
serviceDescriptors.AddScoped<OrderService>(); ServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider(); OrderService orderService = serviceProvider.GetService<OrderService>(); orderService.PrintLog();
最后,我们再来看一种情况,就是通过配置来定义日志的输出级别,我们都知道,通过配置框架可以控制程序运行的一些特殊需求,那么针对不同的日志打印需求,我们同样可以通过日志框架来进行控制。
如我们的setting.json文件如下
{ "logging": { "loglevel": { "Default": "information" }, "Console": { "loglevel": { "Default": "None", "_11_LoggingSimpleDemo.Program": "Trace", "_11_LoggingSimpleDemo.OrderService": "Trace", "aLogger": "Trace" } } } }
那么,在使用时可以通过如下方式来进行级别配置。
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); configurationBuilder.AddJsonFile("settings.json"); IConfigurationRoot configurationRoot = configurationBuilder.Build(); IServiceCollection serviceDescriptors = new ServiceCollection(); serviceDescriptors.AddSingleton<IConfiguration>(p => configurationRoot); serviceDescriptors.AddLogging(configure => { configure.AddConfiguration(configurationRoot.GetSection("Logging")); configure.AddConsole();//这里如果要在配置文件中定义level,那么,节的名称必须是”Console“,区分大小写的,否则不生效 });
好了,到这里的话,本节就先告一段落了,我们本节主要学习了日志框架的使用方式,包括日志级别定义、日志对象获取的方式以及通过logger名称进行日志过滤的配置逻辑等。
下一节,我们将学习日志作用域以及第三方日志框架serilog的内容。
详细代码请参阅
https://github.com/IronMarmot/Samples/tree/master/CoreSamples