Log4Net日志详解

2020-12-23 22:27

阅读:732

一. Log4Net简介

  Log4net是从Java中的Log4j迁移过来的一个.Net版的开源日志框架,它的功能很强大,可以将日志分为不同的等级,以不同的格式输出到不同的存储介质中,比如:数据库、txt文件、内存缓冲区、邮件、控制台、ANSI终端、远程接收端等等,我们这里主要介绍最常用的两种:txt文件和数据库。

(PS:其它的存储介质详见 http://logging.apache.org/log4net/release/config-examples.html)

  Log4net将日志分为五个级别,分别是: FATAL(致命错误) > ERROR(一般错误) > WARN(警告) > INFO(一般信息) > DEBUG(调试信息),每个级别都对应着一组重载方法进行调用。

  官网地址:http://logging.apache.org/log4net/index.html

  Nuget地址:https://www.nuget.org/packages/log4net/

  Nuget安装:Install-Package log4net

  最新版本:2.0.8 (2018-08-09)

   本节主要围绕两个主要的存储介质:【txt文件】和【SQLServer数据库】展开,涵盖的知识点有:

    ①. 基本的使用步骤。

    ②. 初始化关联配置文件的几种形式。

    ③. 代码调用详解。

    ④. 配置文件详解。

    ⑤. 简单的封装和在MVC框架中的调用。 

二. 基本使用步骤

   我们先以控制台程序为例,简单介绍Log4net存储日志到txt文本文档中,后面在做代码的详解。

1. 新建01-SimpleDemo控制台程序,通过指令 【Install-Package log4net】安装相应程序集。

技术图片

2.  在默认配置文件中App.config(B/S程序则为web.config)中进行配置,主要分两块:

  A. 在节点下新增节点下新增(要在其最顶部):

    
      


    
  B. 在根节点下,配置log4net的核心配置代码, 主要节点如下:
    

详细代码如下:

技术图片技术图片
 1 xml version="1.0" encoding="utf-8" ?>
 2 configuration>
 3   
 4   configSections>
 5     section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
 6   configSections>
 7   
 8   log4net>   
 9     
10     appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
11       
12       file value="D:\MyLog1\" />
13       appendToFile value="true" />
14       
15       param name="StaticLogFileName" value="false" />
16       
17       param name="DatePattern" value="yyyyMMdd".log"" />
18       rollingStyle value="Date" />
19       
20       layout type="log4net.Layout.PatternLayout">
21         conversionPattern value="%newline %n记录时间:%date %n线程ID:[%thread] %n日志级别:  %-5level %n出错类:%logger property: [%property{NDC}] - %n错误描述:%message%newline %n"/>
22       layout>
23       
24       lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
25     appender> 
26     root>
27       level value="ALL">level>
28       appender-ref ref="RollingFileAppender">appender-ref>
29     root> 
30   log4net>
31   startup>
32     supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
33   startup>
34 configuration>
View Code

3. 代码调用

1 log4net.Config.XmlConfigurator.Configure();
2 ILog log = LogManager.GetLogger("test");
3 log.Debug("调试信息");

4. 运行结果

技术图片

截止此处,日志保存成功。

 

三. 初始化配置文件

  前面提到在默认配置文件中App.config(B/S程序则为web.config)中进行配置,可以通过代码  log4net.Config.XmlConfigurator.Configure(); 来初始化配置,或者还可以通过 [assembly: log4net.Config.XmlConfigurator()]  反射的形式进行初始化配置,二者可以达到同样的效果,代表了两种初始化配置文件的形式。

  PS: [assembly: log4net.Config.XmlConfigurator()]  可以加在 当前使用文件的 namespace上作用于当前文件,或者加在Properties/AssemblyInfo.cs中,则该项目全局都无须再初始化了。

技术图片

技术图片

 

  在实际项目中,默认的配置文件里可能包含很多框架的信息,这个时候把 log4net的配置代码再放入进去,就会显得有点杂乱,或者有些“奇葩”的人把默认配置文件改名了,这个时候使用上述默认的两种方式就不好用了,那么这种情况怎么处理呢?
  这里重点介绍 通过 log4net.Config.XmlConfigurator.Configure(); 来关联配置文件。

情况一: 使用默认配置文件的情况

  1. 代码配置:log4net.Config.XmlConfigurator.Configure();

  2. 反射配置:[assembly: log4net.Config.XmlConfigurator()] 

 

情况二:修改默认配置文件的名称为:App1.config (这里只是举例,很少有修改默认配置文件名称的)

  1. 代码配置: 首先将App1.config文件的属性中的“生成操作”改为“ 嵌入的资源”,然后通过以下代码进行配置。

1 Assembly assembly = Assembly.GetExecutingAssembly();
2 var xml = assembly.GetManifestResourceStream("_01_SimpleDemo.App1.config");
3 log4net.Config.XmlConfigurator.Configure(xml);

  注:代码中的 _01_SimpleDemo 为命名空间名。

  2. 反射配置:[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.xml")]     

  注:用这种方式属性中的:复制到输出目录需要改为:始终复制,生成操作不需要配置,使用默认:无  即可

 技术图片

情况三:新建单独xml文件,进行log4net的配置 (推荐采用这种方式,和原配置文件区分开,单独配置方便,处理方式和情况二是一致的)

  1. 代码配置:首先将log4net.xml文件的属性中的“生成操作”改为“ 嵌入的资源”,然后通过以下代码进行配置。

1 Assembly assembly = Assembly.GetExecutingAssembly();
2 var xml = assembly.GetManifestResourceStream("_01_SimpleDemo.log4net.xml");
3 log4net.Config.XmlConfigurator.Configure(xml);

  注:代码中的 _01_SimpleDemo 为命名空间名。

 

情况四:无论是修改默认配置文件的名称为 或者 新建单独的xml作为配置文件 → 可以通过绝对路径的方式进行处理 【不推荐这种方式】

  1. 直接写绝对路径 (注意这种方式【不需要】配置文件属性为 “嵌入的资源”)

1 log4net.Config.XmlConfigurator.Configure(new FileInfo(@"D:\06-我的开发之路\DotNet体系\05-DotNet框架篇\03-Log4net详解\Code\01-SimpleDemo\log4net.xml"));

  2 通过代码获取绝对路径 (注意这种方式【不需要】配置文件属性的“生成操作”改为 “嵌入的资源”,但需要改为“始终复制”,确保输出到bin文件下)

1 string assemblyFilePath = Assembly.GetExecutingAssembly().Location;
2 string assemblyDirPath = Path.GetDirectoryName(assemblyFilePath);
3 string configFilePath = assemblyDirPath + " //log4net.xml";
4 log4net.Config.XmlConfigurator.Configure(new FileInfo(configFilePath));

PS:B/S程序下通过  log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~") + @"/log4net.xml")); 来配置。

 

四. 代码调用详解

  Log4net允许多个ILog对象同时存在,通过代码:ILog log = LogManager.GetLogger("xxx"); 来创建。

  A: 日志级别由高到低分别为:FATAL(致命错误) > ERROR(一般错误) > WARN(警告) > INFO(一般信息) > DEBUG(调试信息),另外还有 OFF和 ALL 。

  几点说明:OFF表示所有信息都不写入,ALL表示所有信息都写入,我们也可以通过: level >这样配置,表示WARN级别以及高于WARN以上的级别才会被写入日志

  B: 写入日志的方法有:Debug、Error、Fatal、Info、Warn五个方法,每个方法都有两个重载,如下图:

技术图片

分享在使用配置文件为log4net.xml的情况下的调用代码:

技术图片
 1   Assembly assembly = Assembly.GetExecutingAssembly();
 2   var xml = assembly.GetManifestResourceStream("_01_SimpleDemo.log4net.xml");
 3   log4net.Config.XmlConfigurator.Configure(xml);
 4   ILog log = LogManager.GetLogger("test");
 5   log.Debug("调试信息");
 6   log.Info("一般信息");
 7   log.Warn("警告");
 8   try
 9   {
10      int.Parse("ddd");
11   }
12   catch (Exception ex)
13   {
14       log.Error("一般错误", ex);
15   }
16   log.Fatal("致命错误");
技术图片

 

五. 配置文件详解

  Log4net的配置文件主要分为两大部分:分别是 【自定义配置节点】和 【核心代码配置】,自定义配置节点代码固定,如下图,核心代码配置主要位于:节点中,里面包括节点配置日日志输出途径 和 节点,用于设置记录日志的级别和启用哪些输出途径。  

技术图片

几点说明:

1.  自定义配置节点  

代码固定,直接复制即可。

2.  节点主要用来: 配置日志的的输出级别和加载日志的输出途径。

  A: level中的value值表示该值及其以上的日志级别才会输出,日志级别包括:OFF > FATAL(致命错误) > ERROR(一般错误) > WARN(警告) > INFO(一般信息) > DEBUG(调试信息) > ALL ,比如:

     表示只有INFO及其以上的日志级别才会被保存。

  PS:OFF表示所有信息都不写入,ALL表示所有信息都写入。

  B: 标签用于加载日志的输出途径代码,通过ref和appender标签的中name属性相关联,比如:

      表示开启txt文档保存日志的方式。

3. 节点,用来配置日志的输出途径的,本节主要介绍了输出到 【txt文本文档】中 和 【数据库】。

 A:分享一下数据库的表结构,详细配置见下面的代码分享,需要注意字段类型相匹配,并且要显式指定其长度。

 技术图片

  B:关于txt文本文档的命名,可以存放到一个文件夹里,也可以按照时间来区分文件夹,并且命名可以 动态+指定命名的方式。

技术图片

  C:关于日志文件大小的说明和文件个数的说明,主要需要三个节点配合使用(实际开发中,如果一个txt特别大,打开的时候会非常的慢,卡顿,所以该步骤有必要配置一下)。

  PS:首先要配置 RollingStyle 节点为Size模式或者Composite模式,然后配置 maximumFileSize 节点设置每个文件的大小,最后配置 MaxSizeRollBackups 节点,设置日志文件的个数。超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。

  用下面的代码简单测试一下:

1 "RollingStyle" value="Composite" />
2 "maximumFileSize" value="10KB" />
3 "MaxSizeRollBackups" value="5" />
  技术图片
 
详细代码如下:
技术图片
  1 xml version="1.0" encoding="utf-8" ?>
  2 configuration>
  3   
  4   configSections>
  5     section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  6   configSections>
  7   
  8   log4net>
  9     
 10     
 11     appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
 12       
 13       param name="File"  value="D:\MyLog1\" />
 14       
 15       
 16       
 17       param name="AppendToFile" value="true" />
 18       
 19       lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
 20       
 21       Encoding value="UTF-8" />
 22       
 23       param name="StaticLogFileName" value="false" />
 24       
 25       param name="RollingStyle" value="Composite" />
 26       
 27       
 28       param name="DatePattern" value="yyyy-MM-dd".log"" />
 29       
 30       
 31       
 32       
 33       
 34       
 35       
 37       param name="maximumFileSize" value="10MB" />
 38       
 40       param name="MaxSizeRollBackups" value="5" />
 41       
 42       layout type="log4net.Layout.PatternLayout">
 43         conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property: [%property{NDC}] - %n错误描述:%message%newline %n%newline"/>
 44       layout>
 45     appender>
 46 
 47     
 48     appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
 49       
 50       param name="BufferSize" value="1" />
 51       
 52       connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
 53       
 54       connectionString value="data source=localhost;initial catalog=LogDB;integrated security=false;persist security info=True;User ID=sa;Password=123456" />
 55       
 56       commandText value="INSERT INTO LogInfor ([threadId],[log_level],[log_name],[log_msg],[log_exception],[log_time]) VALUES (@threadId, @log_level, @log_name, @log_msg, @log_exception,@log_time)" />
 57       
 58       
 59       parameter>
 60         parameterName value="@threadId" />
 61         dbType value="String" />
 62         size value="100" />
 63         layout type="log4net.Layout.PatternLayout">
 64           conversionPattern value="%thread" />
 65         layout>
 66       parameter>
 67       
 68       parameter>
 69         parameterName value="@log_level" />
 70         dbType value="String" />
 71         size value="100" />
 72         layout type="log4net.Layout.PatternLayout">
 73           conversionPattern value="%level" />
 74         layout>
 75       parameter>
 76       
 77       parameter>
 78         parameterName value="@log_name" />
 79         dbType value="String" />
 80         size value="100" />
 81         layout type="log4net.Layout.PatternLayout">
 82           conversionPattern value="%logger" />
 83         layout>
 84       parameter>
 85       
 86       parameter>
 87         parameterName value="@log_msg" />
 88         dbType value="String" />
 89         size value="5000" />
 90         layout type="log4net.Layout.PatternLayout">
 91           conversionPattern value="%message" />
 92         layout>
 93       parameter>
 94       
 95       parameter>
 96         parameterName value="@log_exception" />
 97         dbType value="String" />
 98         size value="2000" />
 99         layout type="log4net.Layout.ExceptionLayout" />
100       parameter>
101       
102       parameter>
103         parameterName value="@log_time" />
104         dbType value="DateTime" />
105         layout type="log4net.Layout.RawTimeStampLayout" />
106       parameter>
107     appender>
108     
109     root>
110       
111       
112       
113       level value="ALL">level>
114       
115       appender-ref ref="RollingFileAppender">appender-ref>
116       appender-ref ref="AdoNetAppender">appender-ref>
117     root>
118   log4net>
119 
120 configuration>
技术图片

 

六. 简单的封装及完整代码分享

   这里模拟在系统框架中对Log4net进行简单的封装,然后在MVC框架中调用,并分享全部代码。

  步骤一:新建Ypf.Utils类库,作为工具类库,引入log4net程序集,并将前面用到的log4net.xml 复制进来,改属性为嵌入资源,然后新建LogUtils类(不要起名为LogHelp),对Log4net的方法进行简单的封装,主要包括:初始化代码、ILog实例创建、五类日志级别的封装。

技术图片

  特别注意:这种封装会带来一个问题,会导致输出的文件中出错类永远显示的为LogUtils这个封装类,这里采用StackTrace类进行迂回处理一下,就可以定位到具体的出错位置了,如下图:

技术图片

 log4net.xml文件代码如下:

技术图片技术图片
技术图片
  1 xml version="1.0" encoding="utf-8" ?>
  2 configuration>
  3   
  4   configSections>
  5     section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  6   configSections>
  7   
  8   log4net>
  9     
 10     
 11     appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
 12       
 13       param name="File"  value="D:\MyLog1\" />
 14       
 15       
 16       
 17       param name="AppendToFile" value="true" />
 18       
 19       lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
 20       
 21       Encoding value="UTF-8" />
 22       
 23       param name="StaticLogFileName" value="false" />
 24       
 25       param name="RollingStyle" value="Composite" />
 26       
 27       
 28       param name="DatePattern" value="yyyy-MM-dd".log"" />
 29       
 30       
 31       
 32       
 33       
 34       
 35       
 37       param name="maximumFileSize" value="10MB" />
 38       
 40       param name="MaxSizeRollBackups" value="5" />
 41       
 42       layout type="log4net.Layout.PatternLayout">
 43         conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property: [%property{NDC}] - %n错误描述:%message%newline %n%newline"/>
 44       layout>
 45     appender>
 46 
 47     
 48     appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
 49       
 50       param name="BufferSize" value="1" />
 51       
 52       connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
 53       
 54       connectionString value="data source=localhost;initial catalog=LogDB;integrated security=false;persist security info=True;User ID=sa;Password=123456" />
 55       
 56       commandText value="INSERT INTO LogInfor ([threadId],[log_level],[log_name],[log_msg],[log_exception],[log_time]) VALUES (@threadId, @log_level, @log_name, @log_msg, @log_exception,@log_time)" />
 57       
 58       
 59       parameter>
 60         parameterName value="@threadId" />
 61         dbType value="String"


评论


亲,登录后才可以留言!