• 第八节: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:CoreLogOneLog" />
     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:CoreLogTwoLog" />
     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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    【CF1157F】Maximum Balanced Circle 求一个相邻元素之间绝对值为小于1的最大环
    南昌网络赛 Distance on the tree 主席树+树剖 (给一颗树,m次查询ui->vi这条链中边权小于等于ki的边数。)
    P2486 [SDOI2011]染色(树剖)区间覆盖+区间的连续段(点权) && (边权)
    树链剖分
    南昌网络赛 I. Max answer (单调栈 + 线段树)
    HDU4641 || 6194多校 (后缀自动机-最少出现K次的字串个数 || 恰好出现K次字符串的个数)
    2019年华南理工大学程序设计竞赛(春季赛) 单身狗救星 (凸包+二分)
    2019年华南理工大学程序设计竞赛(春季赛) B 修仙时在做什么?有没有空?可以来炼丹吗?(思维建图搜索)
    数据结构-----顺序表的实现
    Java数据类型及运算
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/10864412.html
Copyright © 2020-2023  润新知