编程博客
002、修改Nuget包位置
001、C#常用的单词
003、收藏的书签
回家准备
004、ASP.NET Core 3.0 gRPC
001、ASP.NET Core 3.0 使用gRPC
002、ASP.NET Core 3.0 gRPC 双向流
003、ASP.NET Core 3.0 gRPC 身份认证和授权
005、飞牛NAS
001、 FnOS飞牛系统实用配置1-应用远程访问(迅雷)
006、DeepSeek
001、DeepSeek 使用指南
007、并发编程
01、并发编程 - 死锁的产生、排查与解决方案
02、并发编程 - 初识线程
03、并发编程 - 线程浅试
04、并发编程 - 线程同步(一)
05、并发编程 - 线程同步(二)
06、并发编程 - 线程同步(三)之原子操作 Interlocked 简介
07、并发编程 - 线程同步(四)之原子操作 Interlocked 详解一
08、并发编程 - 线程同步(五)之原子操作 Interlocked 详解二
09、并发编程 - 线程同步(六)之锁 lock
008、启动项
03、应用--Program 中的 WebApplication
02、主机--Host
01、Program 文件的作用
04、控制反转 IOC 与依赖注入 DI
05、中间件
06、Logger 原理及配置 Log4Net
07、ElasticSearch
本文档使用 MrDoc 发布
-
+
首页
06、Logger 原理及配置 Log4Net
# 日志服务 日志服务可以分为 2 种,一种是 NetCore 内置的日志 `ILogger`,一种是第三方日志服务组件,如 Log4Net 需要掌握: * [ ] netcore 中日志组件是什么类?他的特点是什么?如何使用? * [ ] log4net 如何集成在项目中?log4net 的配置文件如何编写,如何写入日志? ## 内置日志组件[#](https://www.cnblogs.com/boise/p/18002739#%E5%86%85%E7%BD%AE%E6%97%A5%E5%BF%97%E7%BB%84%E4%BB%B6) ### 注意:[#](https://www.cnblogs.com/boise/p/18002739#%E6%B3%A8%E6%84%8F) * **NetCore 不提供将日志写入文件的程序,如果要记录日志文件,请用第三方** * 日志记录应该会很快,不值得牺牲性能来使用异步代码。 如果日志记录数据存储很慢,请不要直接写入它。 考虑先将日志消息写入快速存储,然后再将其移至慢速存储。 ### 分析:[#](https://www.cnblogs.com/boise/p/18002739#%E5%88%86%E6%9E%90) 使用最小托管模型创建应用,在 `Program.cs文件` 中 `WebApplication.CreateBuilder()` 方法会添加以下日志服务。 即 WebApplication 对象中的 Logging 属性 *添加的一组默认的日志记录提供程序* ```C# var builder = WebApplication.CreateBuilder(args); // 提供程序将输出记录到控制台 builder.Logging.AddConsole(); // 提供程序使用 System.Diagnostics.Debug 类写入日志输出 builder.Logging.AddDebug(); // EventLog 提供程序将日志输出发送到 Windows 事件日志。 builder.Logging.AddEventLog(); // 提供程序写入名称为Microsoft-Extensions-Logging 的跨平台事件源 在Windows上,提供程序使用的是 ETW builder.Logging.AddEventSourceLogger(); ``` 同样会在 `appsettings.{ENVIRONMENT}.json` 文件的 `Logging` 部分提供文件生成一个日志相关的配置节点(不是 6.0 也会创建的) ```json { "Logging": { "LogLevel": { // 低于Information级别的日志不会被输出 "Default": "Information", "Microsoft.AspNetCore": "Warning" } } } ``` * **默认等级:**如果需要更改输出的级别日志下限等级,可以修改 `appsettings.json` 配置文件的 "Default"节点,比如修改为"Default"节点的内容为“Debug”,这意味着低于 Debug 等级的日志不会被记录 * **单个类设置等级:**如果需要指定具体的类输出默认输出的下限的等级,可以增加以下节点 ```json "LogLevel": { "完整命名空间.类名": "Warning" } ``` ## 日志等级[#](https://www.cnblogs.com/boise/p/18002739#%E6%97%A5%E5%BF%97%E7%AD%89%E7%BA%A7) net 内部组件日志一共分为 7 个等级,从低到高,可以从枚举 LogLevel 中看出来: ```fsharp public enum LogLevel { // 跟踪日志:包含最详细消息的日志,不应该在生产环境启用 Trace = 0, // 调试日志:在开发过程中用于交互式调查的日志 Debug = 1, // 信息日志:跟踪应用程序常规流的日志 Information = 2, // 警告日志:指的应用程序流中异常或意外事件的日志,但是不会导致应用程序停止 Warning = 3, // 报错日志:指的在应用程序运行失败而停止的日志 Error = 4, // 紧急日志:描述不可恢复的应用程序或系统崩溃或灾难性事件的日志 Critical = 5, // 不写入日志:不用于写入日志消息 None = 6 } ``` ## 如何创建日志-netcore 内部组件[#](https://www.cnblogs.com/boise/p/18002739#%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E6%97%A5%E5%BF%97-netcore%E5%86%85%E9%83%A8%E7%BB%84%E4%BB%B6) > 微软:在 6.0 开始,日志服务不再使用 ILogger 类型。而是使用 ILogger 或将 ILogger 注册为依赖注入 ### ILoggingBuilder 接口[#](https://www.cnblogs.com/boise/p/18002739#iloggingbuilder%E6%8E%A5%E5%8F%A3) 首先,我们来了解一下 `ILoggingBuilder` 这个东西,微软官方说是用于配置日志记录提供程序的接口,但是实际上,这个接口只提供了一个获取从 DI 容器中配置的日志服务的方法,我们更多的是使用他的拓展方法 `AddConfiguration()` 来配置我们自己的日志服务。 *demo* ```c# // 用于配置日志记录提供程序的接口。 public interface ILoggingBuilder { // 获取从DI容器中配置的日志服务 IServiceCollection Services { get; } } // ILoggingBuilder的拓展类 public static class LoggingBuilderExtensions { // 拓展我们自己的日志服务 public static ILoggingBuilder AddConfiguration(this ILoggingBuilder builder, IConfiguration configuration) { // 注入关于日志等级过滤的服务,默认是拿appsetting.json里面“Logging”节点的 "LogLevel"设置 builder.Services.AddSingleton<IConfigureOptions<LoggerFilterOptions>>(new LoggerFilterConfigureOptions(configuration)); builder.Services.AddSingleton<IOptionsChangeTokenSource<LoggerFilterOptions>>( new ConfigurationChangeTokenSource<LoggerFilterOptions>(configuration) ); return builder; } } ``` ### 使用 ILoggerFactory 工厂创建日志[#](https://www.cnblogs.com/boise/p/18002739#%E4%BD%BF%E7%94%A8iloggerfactory%E5%B7%A5%E5%8E%82%E5%88%9B%E5%BB%BA%E6%97%A5%E5%BF%97) 一般在应用程序中,我们创建日志需要一个 ILogger 对象,而 ILogger 对象是由 LoggerFactory 工厂提供的,所以我们首先得需要一个 ILoggerFactory 工厂 ## 日志过滤[#](https://www.cnblogs.com/boise/p/18002739#%E6%97%A5%E5%BF%97%E8%BF%87%E6%BB%A4) ## 集成 Log4net 组件[#](https://www.cnblogs.com/boise/p/18002739#%E9%9B%86%E6%88%90log4net%E7%BB%84%E4%BB%B6) 由于 netcore 的日志组件,不能提供写入文件的服务,所以我们集成 Log4net 组件来为我们提供服务 ### 安装和配置服务[#](https://www.cnblogs.com/boise/p/18002739#%E5%AE%89%E8%A3%85%E5%92%8C%E9%85%8D%E7%BD%AE%E6%9C%8D%E5%8A%A1) 1. 安装 Nuget 包:**log4net** 和对应的 apsnet.core 包 2. 在 `Program.cs文件` 中,注入服务,启用自定义配置文件 ```c# builder.Logging.AddLog4Net("xxxx.config"); ``` 3. 编写配置文件 `log4net.config`,如果不使用自定义配置文件,则可以写在 `web.config` 中 ### 日志等级[#](https://www.cnblogs.com/boise/p/18002739#%E6%97%A5%E5%BF%97%E7%AD%89%E7%BA%A7-1) 7 个等级由低到高: 1. ALL:所有 2. DEBUG:调试 3. INFO:信息 4. WARN:警告 5. ERROR:报错 6. FATAL:重大事故 7. OFF :不输出 ### 编写 log4net.config[#](https://www.cnblogs.com/boise/p/18002739#%E7%BC%96%E5%86%99log4netconfig) 编写配置文件的原因是需要设置日志的一些基本参数,文件格式为 xml。 **注意:** 1. **appenders、logger、root 这几个节点需要小写!!!否则读取不到** **以下有些配置信息不太全面,具体百度官网查看,我这里只写了我们比较常用的几个** **log4net 有 3 个节点** #### Appenders 节点:[#](https://www.cnblogs.com/boise/p/18002739#appenders%E8%8A%82%E7%82%B9) **作用:** 定义日志的输出方式,可以存在多个,可以理解为日志的输出模板。 **必须属性:** type:Appender 对象的输出类型,设置为 log4net.Appender.RollingFileAppender 则是 日志以回滚文件的形式写到文件中,AdoNetAppender 则是写入数据库,有许多种选择,请自行百度。 name:Appender 对象的名称,这个地方设置的值会在 root 标签用到 **子节点:必须属性 value,如果还有子节点 param 或者其他的时候则为 type** :生成的日志文件存放在哪里。value 用于设置文件路径;文件夹不存在则会新建 :文件命名规则。value 用于设置规则,如 yyyy-MM-dd-.'txt',将会以时间为命名格式输出,文件类型需要加上英文单引号包裹起来; :文件名称是否为静态,当设置了命名规则的时候,value 要设置为 false,如果设置为 true,那么 log 的文件名称永远为 file 节点里面的名称 :按照什么方式生成日志文件。value 有 3 个选择 Size、Date、Composite(Size+Date 组合) :日志能分割最大个数,超过设置的值,会删掉最旧的,value 必须好好设置,设置为-1 的时候,代表无线增加,如果 rollingStyle 节点的 value 设置为 Size,则设置的数字代表只能由有 N 个日志;当设置为 Composite 则代表只能每天最多有 N 个日志 :单个日志文件大小,value 用于设置文件大小;只有 rollingStyle 节点设置为 Size 或者 Composite 的时候才使用。比如设置 value = ”500KB“,文件大小单位要大写(KB、MB、GB),必须是正整数。 :编码格式。value 设置 utf-8 等格式 :是否追加到文件末尾,value 设置为 true 的时候,代表追加,false 代表不追加 :value 设置为 log4net.Appender.FileAppender+MinimalLock,目的是防止多线程无法写入 log :过滤器,比如输出级别在 INFO 和 ERROR 之间的日志,有一个属性,type,设置为 log4net.Filter.LevelRangeFilter 的时候,会以日志等级来过滤是否写入文件。必须下方就是最低输出 all,最高到 FATAL ```xml <!--过滤器 输出级别在INFO和ERROR之间的日志 --> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="ALL" /> <param name="LevelMax" value="FATAL" /> </filter> ``` :布局器,意思是每条记录的文案,type 一般设置为 log4net.Layout.PatternLayout,代表自定义类型 节点的作用在于规范输出行为,value 设置输出格式 这里的 %class 的数据来源是,当我们调用 LogManager.GetLogger(typeof(类型)),会传入一个类的 type,这就是他的数据来源,当前日志对象的名称。 **格式参数,可以简写可以完整写:** %m(message):数据来源是,当我们得到的 ILog 对象,调用如 Error 或者 Debug 之类的方法,传入的 message 就是这个数据来源。 %d(datetime){yyy-MM-dd HH:mm:ss }:当前时间,{}里面是格式化内容 %r(runtime):运行时间 %p(priority):日志的等级 %c(class):类名 %t(thread):线程 id %l(line):行号 %f(file):文件名称 有一些会自动填充,有一些则来自于我们调用的方法的参数。 ```xml <!--布局器 就是输出的错误文案是由什么组成的 这里用的是自定义类型--> <layout type="log4net.Layout.PatternLayout"> <!--布局器 输出在什么时间 那个类 哪个行 调用的哪个方法 输出详细报错信息--> <conversionPattern value="%d{yyy-MM-dd HH:mm:ss } :%c %n %m %n"/> </layout> ``` #### logger 节点:[#](https://www.cnblogs.com/boise/p/18002739#logger%E8%8A%82%E7%82%B9) **作用:** 默认继承 root 节点,设置的目的是来单独处理一种日志,可以多个,比如定义一个错误日志的 appender 和一个错误日志的 logger,然后请求日志一样配套 appender 和 logger,这样做可以方便我们定义输出不同的日志类型,如果不定义,默认采用 root 节点。 **怎么使用?:** 在使用 `LogManager.GetLogger("logger节点设置的name属性的值")`,可以获取 logger 对象 **必须属性:** name:用于设置 logger 的名称,这个名称在使用 `LogManager.GetLogger("name属性值")`,可以获取 logger 对象。 additivity:用于设置是否继承 root 节点。如果同时设置了 root 和 logger,则 logger 里面的 appender 会写一份,root 里面的 appender 也会写一份,设置为 false 可以避免出现这种情况 ```xml <logger name = "testLog"> <!--默认输出的等级,低于此等级的不会被输出--> <level value="ALL"/> <!--引用我们自定义的appender--> <appender-ref ref="rollingAppender" /> </logger> ``` #### root 节点:[#](https://www.cnblogs.com/boise/p/18002739#root%E8%8A%82%E7%82%B9) **作用:** 只能有一个,是所有 logger 对象的父节点,必须设置,当我们在方法中,调用 `LogManager.GetLogger()` 不使用 logger 节点的 name 属性获取 logger 的时候,默认就是拿的这个里面的输出配置。 ```xml <root> <priority value="ALL"/> <!--控制级别,由低到高:ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF 比如定义级别为INFO,则INFO级别向下的级别,比如DEBUG日志将不会被记录--> <level value="ALL"/> <appender-ref ref="rollingAppender" /> </root> ``` ### 使用 log4net 记录日志[#](https://www.cnblogs.com/boise/p/18002739#%E4%BD%BF%E7%94%A8log4net%E8%AE%B0%E5%BD%95%E6%97%A5%E5%BF%97) 在我们在 `Program.cs` 注入服务后,编写完配置文件就可以开始使用了, 所有的日志对象都是由 `LogManager类` 来获取管理的,该类有一个 `GetLogger()` 静态的方法,通过这个方法来获取 logger 对象,这个方法有好几个重载 如果框架里不存在该 Logger 对象,它也会为我们创建一个 Logger 对象,默认的输出方式采用 root 节点里面的 appender。 *使用方法* * `LogManager.GetLogger("log4net.config配置文件中logger节点的name属性值")` * `LogManager.GetLogger(typeof(类型))` 得到 logger 对象后我们就可以用来输出了,比如 debug、Info、Warn、Error、FatalFormat 在不同的情况下使用不同的方法 * `log.Error(Exception ex);` * `log.Error(object message);` #### 完整 demo[#](https://www.cnblogs.com/boise/p/18002739#%E5%AE%8C%E6%95%B4demo) ```C# /// <summary> /// log4net 日志工具类 /// </summary> public class LogHelper { private static readonly ILog log = LogManager.GetLogger("ErrorLog"); public static void Error(Exception ex) { log.Error(ex); } } ``` 注意:我这里的 ErrorLog 的 logger 对象属性 additivity 没有设置为 false,所以会写 2 次日志记录,一份到报错日志,一份默认请求日志。 ```xml <?xml version="1.0" encoding="utf-8"?> <log4net> <!--debug日志输出模板--> <appender name="ErrorLogByRollingAppender" type="log4net.Appender.RollingFileAppender"> <file value="OtherFiles/ErrorLog/" /> <datePattern value="yyyy-MM-dd-'.txt'"/> <rollingStyle value="Composite" /> <encoding value="utf-8" /> <maxSizeRollBackups value="20" /> <maximumFileSize value="5MB" /> <appendToFile value="true" /> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <staticLogFileName value="false" /> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="ALL" /> <param name="LevelMax" value="FATAL" /> </filter> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="报错日志:%n 时间:%d{yyy-MM-dd HH:mm:ss } %n 类名:%c %n 报错信息:%m %n "/> </layout> </appender> <!--debug日志对象--> <logger name ="ErrorLog"> <level value="Error"/> <appender-ref ref="ErrorLogByRollingAppender" /> </logger> <!--默认请求日志输出模板--> <appender name ="DefaultLogByRollingAppender" type="log4net.Appender.RollingFileAppender"> <!--配置生成的日志文件放在哪里--> <file value="OtherFiles/DefaultLog/" /> <datePattern value="yyyy-MM-dd-'.txt'"/> <rollingStyle value="Composite" /> <encoding value="utf-8" /> <maxSizeRollBackups value="20" /> <maximumFileSize value="5MB" /> <appendToFile value="true" /> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <staticLogFileName value="false" /> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="ALL" /> <param name="LevelMax" value="DEBUG" /> </filter> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value=" 默认请求日志:%n 时间:%d{yyy-MM-dd HH:mm:ss } %n 运行时间:%r %n "/> </layout> </appender> <!--父节点--> <root> <level value="ALL"/> <appender-ref ref="DefaultLogByRollingAppender" /> </root> </log4net> ```
个人天使
2025年2月10日 14:00
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码