.NET Core开发实战前文传送门:
- 第1课:课程介绍
- 第2课:内容综述
- 第3课:.NET Core的现状、未来以及环境搭建
- 第4课:Startup:掌握ASP.NET Core的启动过程
- 第5课:依赖注入:良好架构的起点(上)
- 第5课:依赖注入:良好架构的起点(中)
- 第5课:依赖注入:良好架构的起点(下)
- 第6课:作用域与对象释放行为(上)
- 第6课:作用域与对象释放行为(下)
- 第7课:用Autofac增强容器能力(上)
- 第7课:用Autofac增强容器能力(下)
- 第8课:配置框架:让服务无缝适应各种环境
- 第9课:命令行配置提供程序
- 第10课:环境变量配置提供程序
- 第11课:文件配置提供程序
- 第12课:配置变更监听
- 第13课:配置绑定:使用强类型对象承载配置数据
- 第14课:自定义配置数据源:低成本实现定制化配置方案
- 第15课:选项框架:服务组件集成配置的最佳实践
- 第16课:选项数据热更新:让服务感知配置的变化
- 第17课:为选项数据添加验证:避免错误配置的应用接收用户流量
18 | 日志框架:聊聊记日志的最佳姿势
源码链接:
https://github.com/witskeeper/geektime/tree/master/samples/LoggingSimpleDemo
日志框架必要的包:
1、Microsoft.Extensions.Logging
2、Microsoft.Extensions.Logging.Console
3、Microsoft.Extensions.Logging.Debug
4、Microsoft.Extensions.Logging.TraceSource
代码通过一个控制台程序,展示从读取配置到整个日志的记录器的构造和日志记录的过程
首先从文件读取配置
IConfigurationBuilder configBuilder = new ConfigurationBuilder(); configBuilder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); var config = configBuilder.Build();
接着构造容器,注入对象
IServiceCollection serviceCollection = new ServiceCollection();// 构造容器 // 用工厂模式将配置对象注册到容器管理 // 注入的时候使用了一个委托,意味着容器可以帮我们管理这个对象的生命周期 serviceCollection.AddSingleton<IConfiguration>(p => config); // 如果将实例直接注入,容器不会帮我们管理 //serviceCollection.AddSingleton<IConfiguration>(config); // AddLogging 往容器里面注册了几个关键对象: // ILoggerFactory,泛型模板 typeof (ILogger<>),Logger 的过滤配置 IConfigureOptions<LoggerFilterOptions> // 最后一行,configure((ILoggingBuilder) new LoggingBuilder(services)); 就是整个注入我们的委托 serviceCollection.AddLogging(builder => { builder.AddConfiguration(config.GetSection("Logging"));// 注册 Logging 配置的 Section builder.AddConsole();// 先使用一个 Console 的日志输出提供程序 });
AddLogging 源码
public static IServiceCollection AddLogging( this IServiceCollection services, Action<ILoggingBuilder> configure) { if (services == null) throw new ArgumentNullException(nameof (services)); services.AddOptions(); services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>()); services.TryAdd(ServiceDescriptor.Singleton(typeof (ILogger<>), typeof (Logger<>))); services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<LoggerFilterOptions>>((IConfigureOptions<LoggerFilterOptions>) new DefaultLoggerLevelConfigureOptions(LogLevel.Information))); configure((ILoggingBuilder) new LoggingBuilder(services)); return services; }
配置文件,appsettings.json
{ "Logging": { "LogLevel": { "Default": "Debug", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" }, "Console": { "LogLevel": { "Default": "Information", "Program": "Trace", "alogger": "Trace", "LoggingSimpleDemo.OrderService": "None" } } } }
Logging 里面定义了 Log 的级别,Key 代表 Log 的名称,Value 代表 Logger 的级别
Console 是指针对 Console 的输出提供程序配置的日志级别
下面看一下日志级别的定义,按照严重程度从低到高
namespace Microsoft.Extensions.Logging { public enum LogLevel { Trace, Debug, Information, Warning, Error, Critical, None, } }
也就是说我们可以指定日志输出的最低级别
接着 BuildServiceProvider,从容器里面获取 ILoggerFactory
IServiceProvider service = serviceCollection.BuildServiceProvider(); ILoggerFactory loggerFactory = service.GetService<ILoggerFactory>();
ILoggerFactory 的定义
namespace Microsoft.Extensions.Logging { public interface ILoggerFactory : IDisposable { // 输入的名称是 Logger 的名称,输出的结果是一个 ILogger 的对象,代表日志记录器 ILogger CreateLogger(string categoryName); // 这个方法通常不会用到它,因为通常情况下注册容器提供程序会在 AddLogging 委托里面去注册,而不会用 AddProvider 方法 void AddProvider(ILoggerProvider provider); } }
获取到 ILoggerFactory 之后就可以创建日志记录器
ILogger alogger = loggerFactory.CreateLogger("alogger"); alogger.LogDebug(2001, "aiya"); alogger.LogInformation("hello"); var ex = new Exception("出错了"); alogger.LogError(ex, "出错了");
因为配置文件中 alogger 的级别是 Trace
"alogger": "Trace",
所以这三行都会被打印出来
启动程序,输出如下:
dbug: alogger[2001] aiya info: alogger[0] hello fail: alogger[0] 出错了 System.Exception: 出错了
方括号的内容是 EventID,也就是针对每一个记录的位置事件,可以为它分配一个事件 ID,代码中在 LogDebug 的时候定义了一个事件 ID 是2001
假如说把 alogger 的日志级别调整成 Information
"alogger": "Information",
那么 Debug 级别的信息没有输出的
info: alogger[0] hello fail: alogger[0] 出错了 System.Exception: 出错了

原文出处:微信公众号【 郑子铭 DotNet NB】
原文链接:https://mp.weixin.qq.com/s/Duz9n4zmaSHrgUVnOi2XtA
本文观点不代表Dotnet9立场,转载请联系原作者。