拥抱.NET Core系列:Logging (1)

在之前我们简单介绍了 .NET Core 中的 DI组件,没来及了解的童鞋可以翻翻我之前的文章。

接下来会对 .NET Core 中的 Logging 进行介绍。

本文中使用了“Microsoft.Extensions.Logging.Console”做为输出目标,后续文章会详解。

Logging 中的三剑客

可以看到 Logging 的核心抽象就是三个接口,分别是:

ILogger:负责具体的日志写入逻辑,如:FileLogger,ConsoleLogger,SQLLogger,ElasticsearchLogger 等。

ILoggerProvider:用来创建记录器,一般和Logger配套使用,相当于单个Logger类型的工厂接口。

ILoggerFactory:记录器工厂,直接面向使用者的,使用者可以通过记录器工厂添加记录器提供程序和创建记录器。

这几个核心抽象位于 NuGet包:“Microsoft.Extensions.Logging.Abstractions”中。

日志等级

在.NET Core提供的日志抽象中提供了7个日志等级(比一般的日志组件多提供了一个Trace和None),分别是:

Trace

包含最详细消息的日志。 这些消息可能包含敏感的应用程序数据。 默认情况下禁用这些消息,并且不应在生产环境中启用这些消息。

Debug

在开发过程中用于交互式调查的日志。 这些日志应主要包含对调试有用的信息,不具有长期价值。

Information

跟踪应用程序的一般流程的日志。 这些日志应具有长期价值。

Warning

突出显示应用程序流中异常或意外事件的日志,但是否则不会导致应用程序执行停止。

Error

当当前执行流程由于失败而停止时,会突出显示的日志。这些应该指示当前活动中的故障,而不是应用程序范围的故障。

Critical

描述不可恢复的应用程序或系统崩溃或灾难性的日志失败需要立即关注。

None

不用于写日志消息。 指定记录类别不应写任何消息。

简单的使用

CreateLogger 方法

CreateLogger 方法的签名为

它提供了两个扩展方法,可以通过类型作为分类名称,如下:

如何根据类型确定分类名称?

在扩展方法内部使用了“GetTypeDisplayName(Type type)”来根据类型获取名称(里面有一些逻辑处理,但一般是采用“{命名空间}.{类型名称}”作为分类名称)。

实现传送门:https://github.com/aspnet/Logging/blob/patch/1.1.3/src/Microsoft.Extensions.Logging.Abstractions/Internal/TypeNameHelper.cs

Log方法

logLevel

日志等级,详情见上文。

eventId(结构体,必填,可以传入 0 或 default(EventId)来充当默认值)

事件ID。

这边的事件ID是用来追踪的,类似 ErrorCode、StatusCode。这样在日志检索的时候可以通过code很方便的找到。

是一个结构体,默认为:“0”。

state(可为null)

状态。

需要记录的对象,这边可以传入任何类型,这就有点奇怪了日志不都是字符吗?

如果我传一个自建类 UserModel 进去会记录出什么信息呢?请接下来看 formatter 参数。

exception(可为null)

异常。

不多说了,如果当前上下文有异常,你丢进去就好了。

formatter(不可为null)

格式化器。

这个参数是一个委托可以看到定义“Func<TState,Exception,string>”,这个就可以解释state是非字符的情况下如何记录日志了。

这边可以通过你自己的逻辑来重建消息的内容(异常信息都会进行输出)。

如果传入null,日志组件会使用默认的格式化器替换,默认的格式化器逻辑是调用“state.ToString()”

扩展方法

当然Logging组件为我们提供了大量扩展方法以简化我们的编码。

以下是方法存根,参数说明可以对照上文。

EventId效果

日志域

日志域可以聚合一类的消息,非常适合同一种类型不同维度的日志记录。

日志过滤器

Logging提供了一个包装实现用来实现日志过滤,我们先来看看使用。

可以看到可以通过制定 CategoryName 及最小日志等级来控制日志是否输出,这边有个有趣的事情。

就是 CategoryName 可以模糊匹配。

在 Logging 组件内部挡识别到 CategoryName 为:“ConsoleApp.MyClass”时会把这个分类名称分割为:

“ConsoleApp.MyClass”

“ConsoleApp”

ps:如果你的命名空间中存在多个“.”符号则还会被分割。

分割完成之后会将这些 Key 拿去与“FilterLoggerSettings”中的字典表进行匹配,优先最大匹配,也就是说如果我们配置了“ConsoleApp.MyClass”这条项目,则优先使用这条,否则继续寻找“ConsoleApp”这条项目,如果都没匹配到则使用默认的规则。

实现传送门:https://github.com/aspnet/Logging/blob/patch/1.1.3/src/Microsoft.Extensions.Logging.Filter/Internal/FilterLogger.cs

在 NLog、log4jnet 等组件中模糊匹配是采用“.*”的方式,例如:”ConsoleApp.*”,在 .NET Core 中的 Logging 中是不被支持的(把“.*”去掉实现相同的效果),这点需要注意。

注意

“.WithFilter”是使用包装的方式进行集成,所以内部会单独维护一个 FilterLogger,也就意味着所有的 LoggerProvider 必须在 FilterFactory 中进行注册,不然过滤器是不会生效的哦。以下是错误的示例:

红色框框部分的两句应该对调,“.WithFilter”应该优先调用。

特殊的Logger => NullLogger

这个我觉得 .NET Core 是从 Orchard“偷”过来的,Orchard 满地的 NullLogger.Instance。

为什么需要 NullLogger?

在业务系统中,Logger 其实并不影响逻辑,换句话说,Logger如果失败不应该影响业务。

在单元测试时 Logger 也可以忽略。

这句话肯定是对的,但在遍地DI的项目中 Logger 很有可能被开发者传入null,这时候就会影响业务的执行,那么这时候 NullLogger 非常适合做那个最糟糕的实现者。

用来替换日志记录或防止“NullReferenceException”这类异常的发生。

非常可惜的是,1.1.3版本中没有提供 NullLogger<T> 这样的实现。好消息是在 .NET Standard2.0 中已经提供了 NullLogger<T> 的实现。

我们下面来看看可使用的场景:

可以看到在没有添加 Logging 组件的时候日志记录也不会抛出异常。

ps:NullLogger<T> 摘抄至.NET Standard2.0中的 NullLoggerOfT.cs。

地址:https://github.com/aspnet/Logging/blob/dev/src/Microsoft.Extensions.Logging.Abstractions/NullLoggerOfT.cs

Logger in DependencyInjection

不使用 Filter

使用 Filter

写在最后

不得不感叹微软在 .NET Core 中统一了非常多的常用组件,为开发者统一环境提供了极大的方便。

后续的文章会分享如何集成第三方 Logging 组件,比如:NLog、log4jnet、Exceptionless 等。

.NET技术栈QQ群:384413261(点击加入 .NET Group

时间: 2024-08-11 10:15:25

拥抱.NET Core系列:Logging (1)的相关文章

拥抱.NET Core系列:MemoryCache 缓存域

在上一篇“<拥抱.NET Core系列:MemoryCache 缓存选项>”我们介绍了一些 MSCache 的机制,今天我们来介绍一下 MSCache 中的缓存域. MSCache项目 MSCache 目前最新的正式版是 2.0.0,预览版是2.1.0,会与 .NETCore 2.1 一起发布.本篇用了2.0.0版本 开源在 GitHub 上,仓库地址是:https://github.com/aspnet/Caching NuGet地址为:https://www.nuget.org/packa

拥抱.NET Core系列:依赖注入(1)

依赖注入时编程手段中解耦和封装的一个非常重要的手段,我本人已经到了没有DI无法编写项目的程度了,在.NET Framework中微软并没有在FCL中引入DI,虽然推出了"Unity".而在.NET Core中DI几乎是所有组件的标配可见DI有多么的重要,本节主要简单介绍下微软在.NET Core中加入的DI组件. 前言 DIP.IoC.DI 说起DI不得不提IoC这个模式,很多人会把DI和IoC混为一谈,但其实这两者是概念和实现的关系. 依赖倒置原则(DIP):软件设计原则,要依赖于抽

.NET Core系列 :4 测试

2016.6.27 微软已经正式发布了.NET Core 1.0 RTM,但是工具链还是预览版,同样的大量的开源测试库也都是至少发布了Alpha测试版支持.NET Core, 这篇文章 The State of .Net Core Testing Today 就将各个开源测试库的目前进展进行了汇总.本文我们的目的是在我们构建我们应用程序的时候能够进行测试,如何使用XUnit结合你可以通过为你的项目添加不同的测试用例NSubstitute进行单元测试,同时对整个项目进行集成测试.这次我们使用Vis

.NET Core系列 : 1、.NET Core 环境搭建和命令行CLI入门

2016年6月27日.NET Core & ASP.NET Core 1.0在Redhat峰会上正式发布,社区里涌现了很多文章,我也计划写个系列文章,原因是.NET Core的入门门槛相当高,很有必要写个深入浅出的系列文章,本节内容帮助你入门.我将可能用Windows做开发环境,也可能用Linux/Mac,但是所有的dotnet CLI命令都是跨平台的,我们在windows/Linux/mac平台上开发跨平台的应用. 安装.NET Core .NET Core 包括.NET Core Runti

.NET Core 系列5 :使用 Nuget打包类库

NuGet是个开源项目,项目包括 NuGet VS插件/NuGet Explorer/NuGetServer/NuGet命令行等项目,.NET Core项目完全使用Nuget 管理组件之间的依赖关系,Nuget已经成为.NET 生态系统中不可或缺的一个组件,从项目角度,将项目中各种组件的引用统统交给NuGet,添加组件/删除组件/以及更新组件即可一键完成,大大提升工作效率,减少不必要的引用报错.从运维角度,可在不影响老版本的情况下发布新版本,可统一管理公司各个项目中组件版本不一和各个版本组件的使

.NET Core系列 : 2 、project.json 这葫芦里卖的什么药

.NET Core系列 : 1..NET Core 环境搭建和命令行CLI入门 介绍了.NET Core环境,本文介绍.NET Core中最重要的一个配置文件project.json的相关内容.我们可以使用.NET Core 的dotnet 命令行接口(CLI)dotnet new命令创建一个应用,也可以用Visual Studio 2015 update 3创建一个应用,他们都有一个project.json ,它是项目的配置文件,类似之前的*.csrpoj文件.Project.json 是一个

ASP.NET CORE系列【一】搭建ASP.NET CORE项目

原文:ASP.NET CORE系列[一]搭建ASP.NET CORE项目 为什么要使用 ASP.NET Core? NET Core 刚发布的时候根据介绍就有点心里痒痒,微软的尿性都懂的,新东西bug太多,现在2.0也发布很久了,决定研究一下. ASP.NET Core官方文档https://docs.microsoft.com/en-us/aspnet/core/getting-started ASP.NET Core 具有如下优点: 生成 Web UI 和 Web API 的统一场景. 集成

asp.net core 系列 16 Web主机 IWebHostBuilder

原文:asp.net core 系列 16 Web主机 IWebHostBuilder 一.概述 在asp.net core中,Host主机负责应用程序启动和生存期管理.host主机包括Web 主机(IWebHostBuilder)和通用主机(IHostBuilder).Web 主机是适用于托管 Web 应用:通用主机(ASP.NET Core 2.1 或更高版本)是适用于托管非 Web 应用:在未来的版本中,通用主机将适用于托管任何类型的应用,包括 Web 应用. 通用主机最终将取代 Web

Core 开发-Logging 使用NLog

ASP.NET Core 开发-Logging 使用NLog 写日志文件 ASP.NET Core 开发-Logging 使用NLog 写日志文件. NLog 可以适用于 .NET Core 和 ASP.NET Core . ASP.NET Core已经内置了日志支持,可以轻松输出到控制台. 学习Logging 组件的相关使用,使用NLog 将日志写入到文件记录. Logging 使用 新建一个 ASP.NET Core 项目,为了方便,我选择Web 应用程序,改身份验证 改为 不进行身份验证.