zoukankan      html  css  js  c++  java
  • C# 使用 log4net 日志组件

    一、 什么是 log4net 

          Apache log4net 库是帮助程序员将日志语句输出到各种输出目标的工具,它是从Java中的Log4j迁移过来的一个.Net版的开源日志框架。log4net 的一个显著特征是分层记录器的概念,使用这些记录器可以有选择地控制任意粒度输出日志语句。主要特征如下:

    • 支持多个框架
    • 输出到多个日志记录目标
    • 分层日志记录体系结构
    • XML 配置
    • 动态配置
    • 日志记录上下文
    • 久经考验的架构
    • 模块化和可扩展设计
    • 高性能和灵活性   

    二、C# 使用 log4net

           添加Nuget 包,搜索到“log4net”后 ,选择安装,具体如下图所示:

    三、添加 log4net 配置文件

     使用 log4net需要我们配置log4net的配置文件,目前,配置文件是用 XML 编写的。一般有两种方式,一种是使用og4net自动生成的 “log4net.xml”进行配置,另一种是直接嵌入到运行程序的 app.config 文件中。  

     具体内容如下:

     1 <?xml version="1.0" encoding="utf-8" ?>
     2 <configuration>
     3   <configSections>
     4     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
     5   </configSections>
     6   <startup>
     7     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
     8   </startup>
     9   <log4net>
    10     <!-- OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
    11     <!-- Set root logger level to ERROR and its appenders -->
    12     <root>
    13       <level value="ALL" />
    14       <appender-ref ref="SysAppender" />
    15     </root>
    16     <!-- Print only messages of level DEBUG or above in the packages -->
    17     <logger name="WebLogger">
    18       <level value="DEBUG" />
    19     </logger>
    20     <appender name="SysAppender" type="log4net.Appender.RollingFileAppender,log4net">
    21       <param name="File" value="log/" />
    22       <param name="AppendToFile" value="true" />
    23       <param name="RollingStyle" value="Date" />
    24       <param name="DatePattern" value="'demo_'yyyy_MM_dd-HH'.log'" />
    25       <param name="StaticLogFileName" value="false" />
    26       <param name="RollingStyle" value="Composite" />
    27       <layout type="log4net.Layout.PatternLayout,log4net">
    28         <param name="ConversionPattern" value="%date [th=%3thread] [line:%5L] [%-5level] %message%newline"/>
    29       </layout>
    30     </appender>
    31     <appender name="consoleApp" type="log4net.Appender.ConsoleAppender,log4net">
    32       <layout type="log4net.Layout.PatternLayout,log4net">
    33         <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
    34       </layout>
    35     </appender>
    36   </log4net>
    37 </configuration>
    View Code

            主要参数含义如下:

          

    三、源码测试

           我们可以添加一个日志类,专门用于输出日志打印,具体代码如下(注意:log4net目前暂时不支持通过配置文件进行文件删除,可通过配置文件设置文件个数与大小进行覆盖备份文件。因此,自动删除日志需要代码实现):

      1  public static class LogUtil
      2     {
      3         private static log4net.ILog Log { get; } = log4net.LogManager.GetLogger("log");
      4 
      5         /// <summary>
      6         /// 日志加载设置
      7         /// </summary>
      8         /// <param name="exeConfigFile">日志配置文件名称</param>
      9         /// <param name="day">保留天数,-1表示不删除</param>
     10         public static void Configure(string exeConfigFile,int day=-1)
     11         {
     12             log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(exeConfigFile));
     13             if (day == -1) return;
     14             var files = new System.IO.DirectoryInfo("log").GetFiles();
     15             foreach (var file in files)
     16             {
     17                 // 定时删除日志文件
     18                 if ((DateTime.Now - file.CreationTime).TotalDays > day)
     19                 {
     20                     file.Delete();
     21                 }
     22             }
     23         }
     24 
     25         private static string GetMethodName(int skipFrames = 2)
     26         {
     27             try
     28             {
     29                 // 这里忽略skipFrames层堆栈,也就忽略了当前方法GetMethodName,以及调用此方法的方法,这样拿到的就正好是外部调用打印日志所在函数的方法信息
     30                 var method = new StackFrame(skipFrames).GetMethod();
     31                 var properties =
     32                     method?.DeclaringType?.GetProperties(
     33                         BindingFlags.Instance |
     34                         BindingFlags.Static |
     35                         BindingFlags.Public |
     36                         BindingFlags.NonPublic);
     37                 var property = properties?.Where(p => p.GetGetMethod(true) == method || p.GetSetMethod(true) == method)
     38                     .FirstOrDefault();
     39 
     40                 var name = $"{method?.DeclaringType?.ToString().Split('.').Last()}.{method?.Name}";
     41                 return property == null
     42                     ? $"{name,-50}"
     43                     : $"{property.Name,-50}";
     44             }
     45             catch (Exception e)
     46             {
     47                 return "ERROR TO GET CALLING METHOD";
     48             }
     49         }
     50         private static string NoWarp(string msg)
     51         {
     52             return msg?.Replace("
    ", " ").Replace("
    ", " ");
     53         }
     54         private static string WrapException(string msg, Exception e)
     55         {
     56             var builder = new StringBuilder(msg);
     57             builder.Append("	[").Append(e.Message).Append("]");
     58             if (e.InnerException != null)
     59             {
     60                 builder.Append(" --> [").Append(e.InnerException.Message).Append("]");
     61             }
     62 
     63             return builder.ToString();
     64         }
     65 
     66 
     67 
     68 
     69         public static void Debug(string msg)
     70         {
     71             Log.Debug(msg);
     72         }
     73         public static void Debug(string msg, Exception e)
     74         {
     75             Log.Debug(WrapException(msg, e), e);
     76         }
     77 
     78         public static void Info(string msg)
     79         {
     80             Log.Info(msg);
     81         }
     82         public static void Info(string msg, Exception e)
     83         {
     84             Log.Info(WrapException(msg, e), e);
     85         }
     86 
     87         public static void Warn(string msg)
     88         {
     89             Log.Warn(msg);
     90         }
     91         public static void Warn(string msg, Exception e)
     92         {
     93             Log.Warn(WrapException(msg, e), e);
     94         }
     95 
     96         public static void Error(string msg)
     97         {
     98             Log.Error(msg);
     99         }
    100         public static void Error(string msg, Exception e)
    101         {
    102             Log.Error(WrapException(msg, e), e);
    103         }
    104 
    105         public static void Fatal(string msg)
    106         {
    107             Log.Fatal(msg);
    108         }
    109         public static void Fatal(string msg, Exception e)
    110         {
    111             Log.Fatal(WrapException(msg, e), e);
    112         }
    113     }
    View Code

           测试代码如下:

     1  static void Main(string[] args)
     2         {
     3             try
     4             {
     5                 string exeConfigFile = $"{AppDomain.CurrentDomain.BaseDirectory}//Log4netDemo.exe.config";
     6 
     7                 if (File.Exists(exeConfigFile) == false)
     8                 {
     9                     throw new Exception($"应用程序配置文件 [{exeConfigFile}] 不存在,无法加载日志 log4net 的配置");
    10                 }
    11 
    12                 LogUtil.Configure(exeConfigFile,1);
    13                 LogUtil.Info("====================================== Log4netDemo started, log4net setup...");
    14                 LogUtil.Warn("程序启动入参不合理");
    15                 LogUtil.Error("程序启动失败");
    16 
    17                 Console.ReadKey();
    18             }
    19             catch (Exception ex)
    20             {
    21                 Console.WriteLine(ex);
    22                 LogUtil.Error("程序加载失败",ex);
    23             }
    24         }
    View Code

           运行程序后,实际输出效果如下:

            

     四、引用地址

    1.  http://logging.apache.org/log4net/release/manual/configuration.html
    2.  https://www.sohu.com/a/254335960_696685
    3.  https://blog.csdn.net/hr541659660/article/details/45575473
  • 相关阅读:
    递归删除指定目录下的 .git 文件
    mina 字节数组编解码器的写法 I
    爬取大众点评
    使用Scrapy抓取数据
    Redis:默认配置文件redis.conf详解
    Redis:五种数据类型的简单增删改查
    使用python-docx生成Word文档
    IT部门域事件与业务分析
    因为说比做容易,所以要少说慎说
    主要问题
  • 原文地址:https://www.cnblogs.com/dongweian/p/14216610.html
Copyright © 2011-2022 走看看