第八节:Asp.Net Core整合Log4net(官方的、微软的两种)

一. 整合Log4net

1. 简单说明

  对于log4net 官方的程序集而言,从2.0.7开始就支持.Net Core了,这里我们采用的是2.0.8,虽然好久没更新了,但不影响使用。Core版本与普通的.Net版本下的使用方法非常类似,仅仅多了一步【创建日志仓储对象】CreateRepository而已,在实际框架封装中,建议把ILoggerRepository和ILog对象设置成单例的。

  .Net 版本的Log4Net参考:https://www.cnblogs.com/yaopengfei/p/9428206.html

2. 使用步骤

声明:【使用的是log4net官方程序集,MyLog02项目直接Nuget Log4net 程序集即可,使用的是该层中的Xml文件下的log4net.xml配置文件】

(1).通过Nuget安装【log4net 2.0.8】,并将log4net.xml配置文件拷贝到Xml文件夹下,将其生成操作改为“嵌入的资源”. 

PS:log4net.xml文件与.Net版本下使用的一致,直接拷贝过来的,代码如下:

  1 <?xml version="1.0" encoding="utf-8" ?>
  2 <configuration>
  3   <!-- 一. 添加log4net的自定义配置节点-->
  4   <configSections>
  5     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  6   </configSections>
  7   <!--二. log4net的核心配置代码-->
  8   <log4net>
  9     <!--1. 输出途径(一) 将日志以回滚文件的形式写到文件中-->
 10     
 11     <!--模式一:全部存放到一个文件夹里-->
 12     <appender name="log0" type="log4net.Appender.RollingFileAppender">
 13       <!--1.1 文件夹的位置(也可以写相对路径)-->
 14       <param name="File"  value="D:\CoreLog\" />
 15       <!--相对路径-->
 16       <!--<param name="File"  value="Logs/" />-->
 17       <!--1.2 是否追加到文件-->
 18       <param name="AppendToFile" value="true" />
 19       <!--1.3 使用最小锁定模型(minimal locking model),以允许多个进程可以写入同一个文件 -->
 20       <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
 21       <!--1.4 配置Unicode编码-->
 22       <Encoding value="UTF-8" />
 23       <!--1.5 是否只写到一个文件里-->
 24       <param name="StaticLogFileName" value="false" />
 25       <!--1.6 配置按照何种方式产生多个日志文件 (Date:日期、Size:文件大小、Composite:日期和文件大小的混合方式)-->
 26       <param name="RollingStyle" value="Composite" />
 27       <!--1.7 介绍多种日志的的命名和存放在磁盘的形式-->
 28       <!--1.7.1 在根目录下直接以日期命名txt文件 注意&quot;的位置,去空格 -->
 29       <param name="DatePattern" value="yyyy-MM-dd&quot;.log&quot;" />
 30       <!--1.7.2 在根目录下按日期产生文件夹,文件名固定 test.log  -->
 31       <!--<param name="DatePattern" value="yyyy-MM-dd/&quot;test.log&quot;"  />-->
 32       <!--1.7.3 在根目录下按日期产生文件夹,这是按日期产生文件夹,并在文件名前也加上日期  -->
 33       <!--<param name="DatePattern" value="yyyyMMdd/yyyyMMdd&quot;-test.log&quot;"  />-->
 34       <!--1.7.4 在根目录下按日期产生文件夹,这再形成下一级固定的文件夹  -->
 35       <!--<param name="DatePattern" value="yyyyMMdd/&quot;OrderInfor/test.log&quot;"  />-->
 36       <!--1.8 配置每个日志的大小。【只在1.6 RollingStyle 选择混合方式与文件大小方式下才起作用!!!】可用的单位:KB|MB|GB。不要使用小数,否则会一直写入当前日志,
 37       超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入。-->
 38       <param name="maximumFileSize" value="10MB" />
 39       <!--1.9 最多产生的日志文件个数,超过则保留最新的n个 将value的值设置-1,则不限文件个数 【只在1.6 RollingStyle 选择混合方式与文件大小方式下才起作用!!!】
 40         与1.8中maximumFileSize文件大小是配合使用的-->
 41       <param name="MaxSizeRollBackups" value="5" />
 42       <!--1.10 配置文件文件的布局格式,使用PatternLayout,自定义布局-->
 43       <layout type="log4net.Layout.PatternLayout">
 44         <conversionPattern value="记录时间:%date %n线程ID:[%thread] %n日志级别:%-5level %n出错类:%logger property: [%property{NDC}] - %n错误描述:%message%newline %n%newline"/>
 45       </layout>
 46     </appender>
 47 
 48     <!--模式二:分文件夹存放-->
 49     <!--文件夹1-->
 50     <appender name="log1" type="log4net.Appender.RollingFileAppender">
 51       <param name="File"  value="D:\CoreLog\OneLog\" />
 52       <param name="AppendToFile" value="true" />
 53       <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
 54       <Encoding value="UTF-8" />
 55       <param name="StaticLogFileName" value="false" />
 56       <param name="RollingStyle" value="Composite" />
 57       <param name="DatePattern" value="yyyy-MM-dd&quot;.log&quot;" />
 58       <param name="maximumFileSize" value="10MB" />
 59       <param name="MaxSizeRollBackups" value="5" />
 60       <layout type="log4net.Layout.PatternLayout">
 61         <conversionPattern value="记录时间:%date %n错误描述:%message%newline %n%newline"/>
 62       </layout>
 63       <!--下面是利用过滤器进行分文件夹存放,两种过滤器进行配合-->
 64       <!--与Logger名称(OneLog)匹配,才记录,-->
 65       <filter type="log4net.Filter.LoggerMatchFilter">
 66         <loggerToMatch value="OneLog" />
 67       </filter>
 68       <!--阻止所有的日志事件被记录-->
 69       <filter type="log4net.Filter.DenyAllFilter" />
 70     </appender>
 71     <!--文件夹2-->
 72     <appender name="log2" type="log4net.Appender.RollingFileAppender">
 73       <param name="File"  value="D:\CoreLog\TwoLog\" />
 74       <param name="AppendToFile" value="true" />
 75       <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
 76       <Encoding value="UTF-8" />
 77       <param name="StaticLogFileName" value="false" />
 78       <param name="RollingStyle" value="Composite" />
 79       <param name="DatePattern" value="yyyy-MM-dd&quot;.log&quot;" />
 80       <param name="maximumFileSize" value="10MB" />
 81       <param name="MaxSizeRollBackups" value="5" />
 82       <layout type="log4net.Layout.PatternLayout">
 83         <conversionPattern value="记录时间:%date %n错误描述:%message%newline %n%newline"/>
 84       </layout>
 85       <!--下面是利用过滤器进行分文件夹存放,两种过滤器进行配合-->
 86       <!--与Logger名称(TwoLog)匹配,才记录,-->
 87       <filter type="log4net.Filter.LoggerMatchFilter">
 88         <loggerToMatch value="TwoLog" />
 89       </filter>
 90       <!--阻止所有的日志事件被记录-->
 91       <filter type="log4net.Filter.DenyAllFilter" />
 92     </appender>
 93 
 94 
 95     <!--2. 输出途径(二) 记录日志到数据库-->
 96     <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
 97       <!--2.1 设置缓冲区大小,只有日志记录超设定值才会一块写入到数据库-->
 98       <param name="BufferSize" value="1" />
 99       <!--2.2 引用-->
100       <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
101       <!--2.3 数据库连接字符串-->
102       <connectionString value="data source=localhost;initial catalog=LogDB;integrated security=false;persist security info=True;User ID=sa;Password=123456" />
103       <!--2.4 SQL语句插入到指定表-->
104       <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)" />
105       <!--2.5 数据库字段匹配-->
106       <!-- 线程号-->
107       <parameter>
108         <parameterName value="@threadId" />
109         <dbType value="String" />
110         <size value="100" />
111         <layout type="log4net.Layout.PatternLayout">
112           <conversionPattern value="%thread" />
113         </layout>
114       </parameter>
115       <!--日志级别-->
116       <parameter>
117         <parameterName value="@log_level" />
118         <dbType value="String" />
119         <size value="100" />
120         <layout type="log4net.Layout.PatternLayout">
121           <conversionPattern value="%level" />
122         </layout>
123       </parameter>
124       <!--日志记录类名称-->
125       <parameter>
126         <parameterName value="@log_name" />
127         <dbType value="String" />
128         <size value="100" />
129         <layout type="log4net.Layout.PatternLayout">
130           <conversionPattern value="%logger" />
131         </layout>
132       </parameter>
133       <!--日志信息-->
134       <parameter>
135         <parameterName value="@log_msg" />
136         <dbType value="String" />
137         <size value="5000" />
138         <layout type="log4net.Layout.PatternLayout">
139           <conversionPattern value="%message" />
140         </layout>
141       </parameter>
142       <!--异常信息  指的是如Infor 方法的第二个参数的值-->
143       <parameter>
144         <parameterName value="@log_exception" />
145         <dbType value="String" />
146         <size value="2000" />
147         <layout type="log4net.Layout.ExceptionLayout" />
148       </parameter>
149       <!-- 日志记录时间-->
150       <parameter>
151         <parameterName value="@log_time" />
152         <dbType value="DateTime" />
153         <layout type="log4net.Layout.RawTimeStampLayout" />
154       </parameter>
155     </appender>
156 
157 
158     <!--(二). 配置日志的的输出级别和加载日志的输出途径-->
159     <root>
160       <!--1. level中的value值表示该值及其以上的日志级别才会输出-->
161       <!--OFF > FATAL(致命错误) > ERROR(一般错误) > WARN(警告) > INFO(一般信息) > DEBUG(调试信息)  > ALL  -->
162       <!--OFF表示所有信息都不写入,ALL表示所有信息都写入-->
163       <level value="ALL"></level>
164       <!--2. append-ref标签表示要加载前面的日志输出途径代码  通过ref和appender标签的中name属性相关联-->
165       
166       <!--<appender-ref ref="AdoNetAppender"></appender-ref>-->
167       <appender-ref ref="log0"></appender-ref>
168       <appender-ref ref="log1"></appender-ref>
169       <appender-ref ref="log2"></appender-ref>
170     </root>
171   </log4net>
172 
173 </configuration>
View Code

(2).创建日志仓储对象, 在框架封装的时候,建议把该对象封装成单例的。

ILoggerRepository repository = LogManager.CreateRepository("myRespository");

(3).加载XML文件,前提要先把xml属性改为“嵌入的资源”,这里主要有两种方式,一种是反射的方式加载,需要加上“程序集名称”,如下面代码中的“MyLog”;另外一种是文件的方式,直接定位到文件路径即可。

A:反射

1 Assembly assembly = Assembly.GetExecutingAssembly();
2 var xml = assembly.GetManifestResourceStream("MyLog.Xml.log4net.xml");
3 XmlConfigurator.Configure(repository, xml);

B:文件加载

var file = new FileInfo(Directory.GetCurrentDirectory() + "/Xml/log4net.xml");
XmlConfigurator.Configure(repository, file);

(4).创建日志对象,

如: ILog log = LogManager.GetLogger(repository.Name, "all");

  特别注意:这里和.Net平台有区别,第一个参数必须是仓储对象的名称,建议直接这么写:repository.Name,第二个参数就是以前.Net 平台下类似的,可以随意起名,如果要分文件存储的话,要配合xml文件中的过滤器,<filter type="log4net.Filter.LoggerMatchFilter"><loggerToMatch value = "OneLog" /></ filter >,实现分文件夹存储。

(5). 开开心心的使用Info、Debug等方法写入日志即可。

 完整代码如下:

 1   //1.创建日志仓储对象
 2   ILoggerRepository repository = LogManager.CreateRepository("myRespository");
 3 
 4   //2.加载xml文件
 5   //2.1 反射的方式加载
 6   //Assembly assembly = Assembly.GetExecutingAssembly();
 7   //var xml = assembly.GetManifestResourceStream("MyLog.Xml.log4net.xml");
 8   //XmlConfigurator.Configure(repository, xml);
 9 
10   //2.2 文件的方式加载
11   var file = new FileInfo(Directory.GetCurrentDirectory() + "/Xml/log4net.xml");
12   XmlConfigurator.Configure(repository, file);
13 
14   //3. 创建日志对象
15   ILog log = LogManager.GetLogger(repository.Name, "all");
16   ILog OneLog = LogManager.GetLogger(repository.Name, "OneLog");
17 
18   //4. 写入日志
19   log.Info("alllog");
20   OneLog.Info("oneLog");

 

二. 分层封装使用

1.声明:

  MyLog02层仅仅需要添加对Utils层的引用,不需要再引入任何程序集。

2.目的:

  在Utils层中封装Log4net,然后可以在其它层中通过引用,直接调用。

3. 步骤:

(1). 给Utils层通过Nuget安装【log4net 2.0.8】,并将log4net.xml配置文件拷贝到Xml文件夹下,将其生成操作改为“嵌入的资源”。

(2). 新建LogUtils类,对log4net进行封装,其中日志仓储对象利用静态变量做成单例的

代码如下:

  1  public class LogUtils
  2     {
  3         //日志仓储(单例模式,静态变量,程序在第一次使用的时候被调用,由clr保证)
  4         private static ILoggerRepository loggerRepository;
  5         //1. 适用于全部文件夹
  6         public static ILog log;
  7         //2. OneLog文件夹
  8         public static ILog log1;
  9         //3. TwoLog文件夹
 10         public static ILog log2;
 11 
 12         //声明文件夹名称(这里分两个文件夹)
 13         static string log1Name = "OneLog";
 14         static string log2Name = "TwoLog";
 15 
 16         /// <summary>
 17         /// 初始化Log4net的配置
 18         /// xml文件一定要改为嵌入的资源
 19         /// </summary>
 20         public static void InitLog4Net()
 21         {
 22             //1. 创建日志仓储(单例)
 23             loggerRepository = loggerRepository ?? LogManager.CreateRepository("myLog4net");
 24             //2. 加载xml文件
 25             Assembly assembly = Assembly.GetExecutingAssembly();
 26             var xml = assembly.GetManifestResourceStream("Utils.Xml.log4net.xml");
 27             log4net.Config.XmlConfigurator.Configure(loggerRepository, xml);
 28             //3. 创建日志对象
 29             log = LogManager.GetLogger(loggerRepository.Name,"all");
 30             log1 = LogManager.GetLogger(loggerRepository.Name, log1Name);
 31             log2 = LogManager.GetLogger(loggerRepository.Name, log2Name);
 32 
 33         }
 34 
 35 
 36         /************************* 五种不同日志级别 *******************************/
 37         //FATAL(致命错误) > ERROR(一般错误) > WARN(警告) > INFO(一般信息) > DEBUG(调试信息)
 38 
 39         #region 00-将调试的信息输出,可以定位到具体的位置(解决高层封装带来的问题)
 40         /// <summary>
 41         /// 将调试的信息输出,可以定位到具体的位置(解决高层封装带来的问题)
 42         /// </summary>
 43         /// <returns></returns>
 44         private static string getDebugInfo()
 45         {
 46             StackTrace trace = new StackTrace(true);
 47             return trace.ToString();
 48         }
 49         #endregion
 50 
 51         #region 01-DEBUG(调试信息)
 52         /// <summary>
 53         /// DEBUG(调试信息)
 54         /// </summary>
 55         /// <param name="msg">日志信息</param>
 56         ///  <param name="logName">文件夹名称</param>
 57         public static void Debug(string msg, string logName = "")
 58         {
 59             if (logName == "")
 60             {
 61                 log.Debug(getDebugInfo() + msg);
 62             }
 63             else if (logName == log1Name)
 64             {
 65                 log1.Debug(msg);
 66             }
 67             else if (logName == log2Name)
 68             {
 69                 log2.Debug(msg);
 70             }
 71         }
 72         /// <summary>
 73         /// Debug
 74         /// </summary>
 75         /// <param name="msg">日志信息</param>
 76         /// <param name="exception">错误信息</param>
 77         public static void Debug(string msg, Exception exception)
 78         {
 79             log.Debug(getDebugInfo() + msg, exception);
 80         }
 81 
 82         #endregion
 83 
 84         #region 02-INFO(一般信息)
 85         /// <summary>
 86         /// INFO(一般信息)
 87         /// </summary>
 88         /// <param name="msg">日志信息</param>
 89         /// <param name="logName">文件夹名称</param>
 90         public static void Info(string msg, string logName = "")
 91         {
 92             if (logName == "")
 93             {
 94                 log.Info(getDebugInfo() + msg);
 95             }
 96             else if (logName == log1Name)
 97             {
 98                 log1.Info(msg);
 99             }
100             else if (logName == log2Name)
101             {
102                 log2.Info(msg);
103             }
104         }
105         /// <summary>
106         /// Info
107         /// </summary>
108         /// <param name="msg">日志信息</param>
109         /// <param name="exception">错误信息</param>
110         public static void Info(string msg, Exception exception)
111         {
112             log.Info(getDebugInfo() + msg, exception);
113         }
114         #endregion
115 
116         #region 03-WARN(警告)
117         /// <summary>
118         ///WARN(警告)
119         /// </summary>
120         /// <param name="msg">日志信息</param>
121         /// <param name="logName">文件夹名称</param>
122         public static void Warn(string msg, string logName = "")
123         {
124             if (logName == "")
125             {
126                 log.Warn(getDebugInfo() + msg);
127             }
128             else if (logName == log1Name)
129             {
130                 log1.Warn(msg);
131             }
132             else if (logName == log2Name)
133             {
134                 log2.Warn(msg);
135             }
136         }
137         /// <summary>
138         /// Warn
139         /// </summary>
140         /// <param name="msg">日志信息</param>
141         /// <param name="exception">错误信息</param>
142         public static void Warn(string msg, Exception exception)
143         {
144             log.Warn(getDebugInfo() + msg, exception);
145         }
146         #endregion
147 
148         #region 04-ERROR(一般错误)
149         /// <summary>
150         /// ERROR(一般错误)
151         /// </summary>
152         /// <param name="msg">日志信息</param>
153         /// <param name="logName">文件夹名称</param>
154         public static void Error(string msg, string logName = "")
155         {
156             if (logName == "")
157             {
158                 log.Error(getDebugInfo() + msg);
159             }
160             else if (logName == log1Name)
161             {
162                 log1.Error(msg);
163             }
164             else if (logName == log2Name)
165             {
166                 log2.Error(msg);
167             }
168         }
169         /// <summary>
170         /// Error
171         /// </summary>
172         /// <param name="msg">日志信息</param>
173         /// <param name="exception">错误信息</param>
174         public static void Error(string msg, Exception exception)
175         {
176             log.Error(getDebugInfo() + msg, exception);
177         }
178         #endregion
179 
180         #region 05-FATAL(致命错误)
181         /// <summary>
182         /// FATAL(致命错误)
183         /// </summary>
184         /// <param name="msg">日志信息</param>
185         /// <param name="logName">文件夹名称</param>
186         public static void Fatal(string msg, string logName = "")
187         {
188             if (logName == "")
189             {
190                 log.Fatal(getDebugInfo() + msg);
191             }
192             else if (logName == log1Name)
193             {
194                 log1.Fatal(msg);
195             }
196             else if (logName == log2Name)
197             {
198                 log2.Fatal(msg);
199             }
200         }
201         /// <summary>
202         /// Fatal
203         /// </summary>
204         /// <param name="msg">日志信息</param>
205         /// <param name="exception">错误信息</param>
206         public static void Fatal(string msg, Exception exception)
207         {
208             log.Fatal(getDebugInfo() + msg, exception);
209         }
210 
211         #endregion
212 
213 
214     }
View Code

(3). 对“MyLog”项目添加对“Utils”的引用,然后在Startup类中ConfigureServices方法中进行初始化Log4net,如下:

1 LogUtils.InitLog4Net();

(4).根据情况进行调用。

  如:LogUtils.Info("我是二哈"); LogUtils.Info("我是二哈1", "OneLog");

 

三. 微软出品的日志程序

1. 声明:

   微软的日志扩展库中新增了对Log4Net的支持,仅仅需要在MyLog2项目中引入微软自己的 【Microsoft.Extensions.Logging.Log4Net.AspNetCore】 2.2.11即可,不需要再重复引入log4net官方程序集。

2. 使用步骤:

(1). 通过Nuget安装程序集【Microsoft.Extensions.Logging.Log4Net.AspNetCore】,版本号:2.2.11

(2). 在Xml文件夹中新建一个log4net2.xml的配置文件,并将其改为 “始终复制!!!【这里和前面处理配置文件的方式不同哦】

(3). 在Startup类中的Configure方法中先注入ILoggerFactory对象,然后初始化log4net,代码如下:

1 loggerFactory.AddLog4Net("Xml/log4net2.xml");

  解释:这里加载的是bin最终目录下的文件,所以步骤②中要将其改为“始终复制”(即复制到bin的最终目录下),如果这里不写参数,默认加载的是bin最终目录下的log4net.config文件。

(4). 在控制器里通过构造函数注入ILogger对象,注入的时候一定要注意<out TCategoryName> ,需要传入一个值。

(5). 进行调用,这里有两种方式区分日志级别:Log(LogLevel.Warning, "LogLevel.Warning"); 或者LogWarning("LogLevel.Warning");

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2019-05-14 20:31  Yaopengfei  阅读(1203)  评论(1编辑  收藏  举报