Logger原理及配置Log4Net
日志服务
日志服务可以分为2种,一种是NetCore内置的日志ILogger
,一种是第三方日志服务组件,如Log4Net
需要掌握:
内置日志组件#
注意:#
- NetCore不提供将日志写入文件的程序,如果要记录日志文件,请用第三方
- 日志记录应该会很快,不值得牺牲性能来使用异步代码。 如果日志记录数据存储很慢,请不要直接写入它。 考虑先将日志消息写入快速存储,然后再将其移至慢速存储。
分析:#
使用最小托管模型创建应用,在Program.cs文件
中WebApplication.CreateBuilder()
方法会添加以下日志服务。
即WebApplication对象中的Logging属性
添加的一组默认的日志记录提供程序
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也会创建的)
{
"Logging": {
"LogLevel": {
// 低于Information级别的日志不会被输出
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
-
默认等级:如果需要更改输出的级别日志下限等级,可以修改
appsettings.json
配置文件的 "Default"节点,比如修改为"Default"节点的内容为“Debug”,这意味着低于Debug等级的日志不会被记录 -
单个类设置等级:如果需要指定具体的类输出默认输出的下限的等级,可以增加以下节点
"LogLevel": { "完整命名空间.类名": "Warning" }
日志等级#
net内部组件日志一共分为7个等级,从低到高,可以从枚举LogLevel中看出来:
public enum LogLevel
{
// 跟踪日志:包含最详细消息的日志,不应该在生产环境启用
Trace = 0,
// 调试日志:在开发过程中用于交互式调查的日志
Debug = 1,
// 信息日志:跟踪应用程序常规流的日志
Information = 2,
// 警告日志:指的应用程序流中异常或意外事件的日志,但是不会导致应用程序停止
Warning = 3,
// 报错日志:指的在应用程序运行失败而停止的日志
Error = 4,
// 紧急日志:描述不可恢复的应用程序或系统崩溃或灾难性事件的日志
Critical = 5,
// 不写入日志:不用于写入日志消息
None = 6
}
如何创建日志-netcore内部组件#
微软:在6.0开始,日志服务不再使用ILogger类型。而是使用ILogger
或将 ILogger 注册为依赖注入
ILoggingBuilder接口#
首先,我们来了解一下ILoggingBuilder
这个东西,微软官方说是用于配置日志记录提供程序的接口,但是实际上,这个接口只提供了一个获取从DI容器中配置的日志服务的方法,我们更多的是使用他的拓展方法AddConfiguration()
来配置我们自己的日志服务。
demo
// 用于配置日志记录提供程序的接口。
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工厂创建日志#
一般在应用程序中,我们创建日志需要一个ILogger对象,而ILogger对象是由LoggerFactory工厂提供的,所以我们首先得需要一个ILoggerFactory工厂
日志过滤#
集成Log4net组件#
由于netcore的日志组件,不能提供写入文件的服务,所以我们集成Log4net组件来为我们提供服务
安装和配置服务#
-
安装Nuget包:log4net和对应的apsnet.core包
-
在
Program.cs文件
中,注入服务,启用自定义配置文件builder.Logging.AddLog4Net("xxxx.config");
-
编写配置文件
log4net.config
,如果不使用自定义配置文件,则可以写在web.config
中
日志等级#
7个等级由低到高:
- ALL:所有
- DEBUG:调试
- INFO:信息
- WARN:警告
- ERROR:报错
- FATAL:重大事故
- OFF :不输出
编写log4net.config#
编写配置文件的原因是需要设置日志的一些基本参数,文件格式为xml。
注意:
- appenders、logger、root这几个节点需要小写!!!否则读取不到
以下有些配置信息不太全面,具体百度官网查看,我这里只写了我们比较常用的几个
log4net有3个节点
Appenders节点:#
作用:
定义日志的输出方式,可以存在多个,可以理解为日志的输出模板。
必须属性:
type:Appender对象的输出类型,设置为log4net.Appender.RollingFileAppender则是 日志以回滚文件的形式写到文件中,AdoNetAppender则是写入数据库,有许多种选择,请自行百度。
name:Appender对象的名称,这个地方设置的值会在root标签用到
子节点:必须属性value,如果还有子节点param或者其他的时候则为type
<!--过滤器 输出级别在INFO和ERROR之间的日志 -->
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="ALL" />
<param name="LevelMax" value="FATAL" />
</filter>
这里的%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):文件名称
有一些会自动填充,有一些则来自于我们调用的方法的参数。
<!--布局器 就是输出的错误文案是由什么组成的 这里用的是自定义类型-->
<layout type="log4net.Layout.PatternLayout">
<!--布局器 输出在什么时间 那个类 哪个行 调用的哪个方法 输出详细报错信息-->
<conversionPattern value="%d{yyy-MM-dd HH:mm:ss } :%c %n %m %n"/>
</layout>
logger节点:#
作用:
默认继承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可以避免出现这种情况
<logger name = "testLog">
<!--默认输出的等级,低于此等级的不会被输出-->
<level value="ALL"/>
<!--引用我们自定义的appender-->
<appender-ref ref="rollingAppender" />
</logger>
root节点:#
作用:
只能有一个,是所有logger对象的父节点,必须设置,当我们在方法中,调用LogManager.GetLogger()
不使用logger节点的name属性获取logger的时候,默认就是拿的这个里面的输出配置。
<root>
<priority value="ALL"/>
<!--控制级别,由低到高:ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF
比如定义级别为INFO,则INFO级别向下的级别,比如DEBUG日志将不会被记录-->
<level value="ALL"/>
<appender-ref ref="rollingAppender" />
</root>
使用log4net记录日志#
在我们在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#
/// <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 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>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)