一、 什么是 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>
主要參數含義如下:
三、源碼測試
我們可以添加一個日志類,專門用於輸出日志打印,具體代碼如下(注意: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("\r\n", " ").Replace("\n", " "); 53 } 54 private static string WrapException(string msg, Exception e) 55 { 56 var builder = new StringBuilder(msg); 57 builder.Append("\t[").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 }
測試代碼如下:

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 }
運行程序后,實際輸出效果如下:
四、引用地址
- http://logging.apache.org/log4net/release/manual/configuration.html
- https://www.sohu.com/a/254335960_696685
- https://blog.csdn.net/hr541659660/article/details/45575473