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组件来为我们提供服务

安装和配置服务#

  1. 安装Nuget包:log4net和对应的apsnet.core包

  2. Program.cs文件中,注入服务,启用自定义配置文件

    builder.Logging.AddLog4Net("xxxx.config");
    
  3. 编写配置文件log4net.config,如果不使用自定义配置文件,则可以写在web.config

日志等级#

7个等级由低到高:

  1. ALL:所有
  2. DEBUG:调试
  3. INFO:信息
  4. WARN:警告
  5. ERROR:报错
  6. FATAL:重大事故
  7. OFF :不输出

编写log4net.config#

编写配置文件的原因是需要设置日志的一些基本参数,文件格式为xml。

注意:

  1. appenders、logger、root这几个节点需要小写!!!否则读取不到

以下有些配置信息不太全面,具体百度官网查看,我这里只写了我们比较常用的几个

log4net有3个节点

Appenders节点:#

作用:

定义日志的输出方式,可以存在多个,可以理解为日志的输出模板。

必须属性:

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

<!--过滤器  输出级别在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):文件名称

有一些会自动填充,有一些则来自于我们调用的方法的参数。

    <!--布局器 就是输出的错误文案是由什么组成的 这里用的是自定义类型-->			
	<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>

作者:boise

出处:https://www.cnblogs.com/boise/p/18002739

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Ghetto_richh  阅读(458)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示
主题色彩