Log4Net在.NET Fromework和.NET Core中的使用
本文讨论的是在都需要使用Log4Net的前提下,因为.NET Core已经内置了日志服务,不使用Log4Net也是可以看到日志的.
一、区别
相同:
1,都需要引用log4net.dll。
不同:
1,需要格式化日志输出方式的,它们中的Log4Net.config配置文件格式是不同的。
2,.NET Core还需要引用Microsoft.Extensions.Logging.Log4Net.AspNetCore.dll。
3,使用方式不同,.NET Framework一般是需要借助帮助类库的,.NET Core是可以直接使用依赖注入,也可以使用帮助类库。
二、使用方式
1,.NET Framework
1 using log4net; 2 using System; 3 using System.Collections.Concurrent; 4 using System.IO; 5 using System.Reflection; 6 using System.Xml; 7 8 namespace MS.Quality.Component.Utility 9 { 10 /// <summary> 11 /// 日志帮助类 12 /// </summary> 13 public class Log4NetUtility 14 { 15 private static readonly ConcurrentDictionary<Type, ILog> _loggers = new ConcurrentDictionary<Type, ILog>(); 16 /// <summary> 17 /// 获取记录器 18 /// </summary> 19 /// <param name="source"></param> 20 /// <returns></returns> 21 private static ILog GetLogger(Type source) 22 { 23 if (_loggers.ContainsKey(source)) 24 { 25 return _loggers[source]; 26 } 27 else 28 { 29 ILog logger = LogManager.GetLogger(source); 30 SetLog4NetConfiguration(); 31 _loggers.TryAdd(source, logger); 32 return logger; 33 } 34 } 35 36 /// <summary> 37 /// 调试信息 38 /// </summary> 39 /// <param name="source"></param> 40 /// <param name="message"></param> 41 public static void Debug(object source, string message) 42 { 43 Debug(source.GetType(), message); 44 } 45 46 /// <summary> 47 /// 调试信息 48 /// </summary> 49 /// <param name="source"></param> 50 /// <param name="message"></param> 51 /// <param name="ps"></param> 52 public static void Debug(object source, string message, params object[] ps) 53 { 54 Debug(source.GetType(), string.Format(message, ps)); 55 } 56 57 /// <summary> 58 /// 调试信息 59 /// </summary> 60 /// <param name="source"></param> 61 /// <param name="message"></param> 62 public static void Debug(Type source, string message) 63 { 64 ILog logger = GetLogger(source); 65 if (logger.IsDebugEnabled) 66 logger.Debug(message); 67 } 68 /// <summary> 69 /// 关键信息 70 /// </summary> 71 /// <param name="source"></param> 72 /// <param name="message"></param> 73 public static void Info(object source, object message) 74 { 75 Info(source.GetType(), message); 76 } 77 78 /// <summary> 79 /// 关键信息 80 /// </summary> 81 /// <param name="source"></param> 82 /// <param name="message"></param> 83 public static void Info(Type source, object message) 84 { 85 ILog logger = GetLogger(source); 86 if (logger.IsInfoEnabled) 87 logger.Info(message); 88 } 89 90 /// <summary> 91 /// 警告信息 92 /// </summary> 93 /// <param name="source"></param> 94 /// <param name="message"></param> 95 public static void Warn(object source, object message) 96 { 97 Warn(source.GetType(), message); 98 } 99 100 /// <summary> 101 /// 警告信息 102 /// </summary> 103 /// <param name="source"></param> 104 /// <param name="message"></param> 105 public static void Warn(Type source, object message) 106 { 107 ILog logger = GetLogger(source); 108 if (logger.IsWarnEnabled) 109 logger.Warn(message); 110 } 111 112 /// <summary> 113 /// 错误信息 114 /// </summary> 115 /// <param name="source"></param> 116 /// <param name="message"></param> 117 public static void Error(object source, object message) 118 { 119 Error(source.GetType(), message); 120 } 121 122 /// <summary> 123 /// 错误信息 124 /// </summary> 125 /// <param name="source"></param> 126 /// <param name="message"></param> 127 public static void Error(Type source, object message) 128 { 129 ILog logger = GetLogger(source); 130 if (logger.IsErrorEnabled) 131 logger.Error(message); 132 } 133 134 /// <summary> 135 /// 失败信息 136 /// </summary> 137 /// <param name="source"></param> 138 /// <param name="message"></param> 139 public static void Fatal(object source, object message) 140 { 141 Fatal(source.GetType(), message); 142 } 143 144 /// <summary> 145 /// 失败信息 146 /// </summary> 147 /// <param name="source"></param> 148 /// <param name="message"></param> 149 public static void Fatal(Type source, object message) 150 { 151 ILog logger = GetLogger(source); 152 if (logger.IsFatalEnabled) 153 logger.Fatal(message); 154 } 155 156 /* Log a message object and exception */ 157 158 /// <summary> 159 /// 调试信息 160 /// </summary> 161 /// <param name="source"></param> 162 /// <param name="message"></param> 163 /// <param name="exception"></param> 164 public static void Debug(object source, object message, Exception exception) 165 { 166 Debug(source.GetType(), message, exception); 167 } 168 169 /// <summary> 170 /// 调试信息 171 /// </summary> 172 /// <param name="source"></param> 173 /// <param name="message"></param> 174 /// <param name="exception"></param> 175 public static void Debug(Type source, object message, Exception exception) 176 { 177 GetLogger(source).Debug(message, exception); 178 } 179 180 /// <summary> 181 /// 关键信息 182 /// </summary> 183 /// <param name="source"></param> 184 /// <param name="message"></param> 185 /// <param name="exception"></param> 186 public static void Info(object source, object message, Exception exception) 187 { 188 Info(source.GetType(), message, exception); 189 } 190 191 /// <summary> 192 /// 关键信息 193 /// </summary> 194 /// <param name="source"></param> 195 /// <param name="message"></param> 196 /// <param name="exception"></param> 197 public static void Info(Type source, object message, Exception exception) 198 { 199 GetLogger(source).Info(message, exception); 200 } 201 202 /// <summary> 203 /// 警告信息 204 /// </summary> 205 /// <param name="source"></param> 206 /// <param name="message"></param> 207 /// <param name="exception"></param> 208 public static void Warn(object source, object message, Exception exception) 209 { 210 Warn(source.GetType(), message, exception); 211 } 212 213 /// <summary> 214 /// 警告信息 215 /// </summary> 216 /// <param name="source"></param> 217 /// <param name="message"></param> 218 /// <param name="exception"></param> 219 public static void Warn(Type source, object message, Exception exception) 220 { 221 GetLogger(source).Warn(message, exception); 222 } 223 224 /// <summary> 225 /// 错误信息 226 /// </summary> 227 /// <param name="source"></param> 228 /// <param name="message"></param> 229 /// <param name="exception"></param> 230 public static void Error(object source, object message, Exception exception) 231 { 232 Error(source.GetType(), message, exception); 233 } 234 235 /// <summary> 236 /// 错误信息 237 /// </summary> 238 /// <param name="source"></param> 239 /// <param name="message"></param> 240 /// <param name="exception"></param> 241 public static void Error(Type source, object message, Exception exception) 242 { 243 GetLogger(source).Error(message, exception); 244 } 245 246 /// <summary> 247 /// 失败信息 248 /// </summary> 249 /// <param name="source"></param> 250 /// <param name="message"></param> 251 /// <param name="exception"></param> 252 public static void Fatal(object source, object message, Exception exception) 253 { 254 Fatal(source.GetType(), message, exception); 255 } 256 257 /// <summary> 258 /// 失败信息 259 /// </summary> 260 /// <param name="source"></param> 261 /// <param name="message"></param> 262 /// <param name="exception"></param> 263 public static void Fatal(Type source, object message, Exception exception) 264 { 265 GetLogger(source).Fatal(message, exception); 266 } 267 private static void SetLog4NetConfiguration() 268 { 269 var repo = LogManager.CreateRepository( 270 Assembly.GetEntryAssembly(), typeof(log4net.Repository.Hierarchy.Hierarchy)); 271 log4net.Config.XmlConfigurator.Configure(repo, new FileInfo("Log4Net.config")); 272 } 273 } 274 }
1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <configSections> 4 <!--添加自定义节点:log4net type:解析类名,程序集名(log4net.dll)--> 5 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> 6 </configSections> 7 8 <log4net> 9 <!--定义输出到文件中--> 10 <appender name="Log4Net_INFO" type="log4net.Appender.RollingFileAppender"> 11 <!--定义文件存放位置--> 12 <file value="Log/Info/"/> 13 <!--是否追加到文件,默认为true,通常无需设置--> 14 <appendToFile value="true"/> 15 <RollingStyle value="Date"/> 16 <!--日期的格式,每月一个文件夹,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置--> 17 <DatePattern value="yyyy-MM/yyyy-MM-dd".log"" /> 18 <!--日志文件名是否为静态--> 19 <StaticLogFileName value="false"/> 20 <!--多线程时采用最小锁定--> 21 <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 22 <!--布局(向用户显示最后经过格式化的输出信息)--> 23 <layout type="log4net.Layout.PatternLayout"> 24 <!-- 25 %m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息 26 %n(new line):换行 27 %d(datetime):输出当前语句运行的时刻 28 %r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数 29 %t(thread id):当前语句所在的线程ID 30 %p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等 31 %c(class):当前日志对象的名称,例如: 32 %L:输出语句所在的行号 33 %F:输出语句所在的文件名 34 %-数字:表示该项的最小长度,如果不够,则用空格填充 35 --> 36 <Header value="[Header] "/> 37 <Footer value="[Footer] "/> 38 <!--正文--> 39 <ConversionPattern value="%date ThreadID:[%thread] Level:%-5level Logger:%logger property:[%property{NDC}] %nMessage:%message%newline" /> 40 </layout> 41 <filter type="log4net.Filter.LevelRangeFilter"> 42 <levelMin value="Debug" /> 43 <levelMax value="Warn" /> 44 </filter> 45 </appender> 46 47 <appender name="Log4Net_ERROR" type="log4net.Appender.RollingFileAppender"> 48 <file value="Log/Error/"/> 49 <appendToFile value="true"/> 50 <RollingStyle value="Date"/> 51 <DatePattern value="yyyy-MM/yyyy-MM-dd".log"" /> 52 <StaticLogFileName value="false"/> 53 <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 54 <layout type="log4net.Layout.PatternLayout"> 55 <Header value="[Header] "/> 56 <Footer value="[Footer] "/> 57 <!--正文--> 58 <ConversionPattern value="%date ThreadID:[%thread] Level:%-5level Logger:%logger property:[%property{NDC}] %nMessage:%message%newline" /> 59 </layout> 60 <filter type="log4net.Filter.LevelRangeFilter"> 61 <levelMin value="ERROR" /> 62 <levelMax value="FATAL" /> 63 </filter> 64 </appender> 65 66 <root> 67 <level value="ALL"/> 68 <appender-ref ref="Log4Net_INFO" /> 69 <appender-ref ref="Log4Net_ERROR" /> 70 </root> 71 72 </log4net> 73 74 </configuration>
Log4NetUtility.Info(this, "guid:" + guid);
2,.NET Core
a,使用Log4NetUtility.cs帮助类库,使用方式同.NET Framework,Log4Net.config同上
b,使用依赖注入方式
<?xml version="1.0" encoding="utf-8"?> <log4net> <!--定义输出到文件中--> <appender name="Log4Net_INFO" type="log4net.Appender.RollingFileAppender"> <!--定义文件存放位置--> <file value="Log/Info/"/> <!--是否追加到文件,默认为true,通常无需设置--> <appendToFile value="true"/> <!--可以为:Once|Size|Date|Composite--> <!--Composite为Size和Date的组合--> <!--<RollingStyle value="Date"/>--> <RollingStyle value="Composite"/> <!--日期的格式,每月一个文件夹,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置--> <DatePattern value="yyyy-MM/yyyy-MM-dd".log"" /> <!--日志最大个数,都是最新的--> <!--rollingStyle节点为Size时,只能有value个日志--> <!--rollingStyle节点为Composite时,每天有value个日志--> <maxSizeRollBackups value="20" /> <!--可用的单位:KB|MB|GB--> <maximumFileSize value="3MB"/> <!--日志文件名是否为静态--> <!--置为true,当前最新日志文件名永远为file节点中的名字--> <StaticLogFileName value="false"/> <!--<StaticLogFileName value="true"/>--> <!--多线程时采用最小锁定,防止多线程时不能写Log,官方说线程非安全--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--布局(向用户显示最后经过格式化的输出信息)--> <layout type="log4net.Layout.PatternLayout"> <!-- %m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息 %n(new line):换行 %d(datetime):输出当前语句运行的时刻 %r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数 %t(thread id):当前语句所在的线程ID %p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等 %c(class):当前日志对象的名称,例如: %L:输出语句所在的行号 %F:输出语句所在的文件名 %-数字:表示该项的最小长度,如果不够,则用空格填充 --> <Header value="[Header]"/> <Footer value="[Footer]"/> <!--正文--> <ConversionPattern value="%date ThreadID:[%thread] Level:%-5levelLogger:%logger property:[%property{NDC}] %nMessage:%message%newline" /> </layout> <!--输出级别在ALL和WARN之间--> <filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="INFO" /> <levelMax value="WARN" /> </filter> </appender> <appender name="Log4Net_ERROR" type="log4net.Appender.RollingFileAppender"> <file value="Log/Error/"/> <appendToFile value="true"/> <RollingStyle value="Date"/> <DatePattern value="yyyy-MM/yyyy-MM-dd".log"" /> <StaticLogFileName value="false"/> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <layout type="log4net.Layout.PatternLayout"> <Header value="[Header]"/> <Footer value="[Footer]"/> <!--正文--> <ConversionPattern value="%date ThreadID:[%thread] Level:%-5levelLogger:%logger property:[%property{NDC}] %nMessage:%message%newline" /> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="ERROR" /> <levelMax value="FATAL" /> </filter> </appender> <!--SqlServer形式--> <!--log4net日志配置:http://logging.apache.org/log4net/release/config-examples.html --> <appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender"> <!--日志缓存写入条数 设置为0时只要有一条就立刻写到数据库--> <bufferSize value="0" /> <connectionType value="System.Data.SqlClient.SqlConnection,System.Data.SqlClient, Version=4.6.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <connectionString value="Data Source=DESKTOP-KUQBMBC;Initial Catalog=LogManager;Persist Security Info=True;User ID=sa;Password=sa123" /> <commandText value="INSERT INTO Log4Net ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" /> <parameter> <parameterName value="@log_date" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout" /> </parameter> <parameter> <parameterName value="@thread" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%thread" /> </layout> </parameter> <parameter> <parameterName value="@log_level" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%level" /> </layout> </parameter> <parameter> <parameterName value="@logger" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%logger" /> </layout> </parameter> <parameter> <parameterName value="@message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message" /> </layout> </parameter> <parameter> <parameterName value="@exception" /> <dbType value="String" /> <size value="2000" /> <layout type="log4net.Layout.ExceptionLayout" /> </parameter> </appender> <root> <!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF--> <!--OFF:0--> <!--FATAL:FATAL--> <!--ERROR: ERROR,FATAL--> <!--WARN: WARN,ERROR,FATAL--> <!--INFO: INFO,WARN,ERROR,FATAL--> <!--DEBUG: INFO,WARN,ERROR,FATAL--> <!--ALL: DEBUG,INFO,WARN,ERROR,FATAL--> <priority value="ALL"/> <level value="ALL"/> <appender-ref ref="Log4Net_INFO" /> <appender-ref ref="Log4Net_ERROR" /> <appender-ref ref="AdoNetAppender_SqlServer" /> </root> </log4net>
Programe.cs:
.ConfigureLogging(logging => { logging.AddFilter("System", LogLevel.Warning);//过滤系统日志 logging.AddFilter("Microsoft", LogLevel.Warning); logging.AddLog4Net("Log4Net.config");//Log4Net.config文件路径 })
日志Level过滤也可以在appconfigs.json中进行配置:
1 { 2 "Logging": { 3 "LogLevel": { // No provider, LogLevel applies to all the enabled providers. 4 "Default": "Information", 5 "Microsoft": "Warning", 6 "Microsoft.Hosting.Lifetime": "Warning" 7 }, 8 "Debug": { // Debug provider. 9 "LogLevel": { 10 "Default": "Information" // Overrides preceding LogLevel:Default setting. 11 } 12 }, 13 "Console": { 14 "IncludeScopes": true, 15 "LogLevel": { 16 "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning", 17 "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug", 18 "Microsoft.AspNetCore.Mvc.Razor": "Error", 19 "Default": "Information" 20 } 21 }, 22 "EventSource": { 23 "LogLevel": { 24 "Microsoft": "Information" 25 } 26 }, 27 "EventLog": { 28 "LogLevel": { 29 "Microsoft": "Information" 30 } 31 }, 32 "AzureAppServicesFile": { 33 "IncludeScopes": true, 34 "LogLevel": { 35 "Default": "Warning" 36 } 37 }, 38 "AzureAppServicesBlob": { 39 "IncludeScopes": true, 40 "LogLevel": { 41 "Microsoft": "Information" 42 } 43 }, 44 "ApplicationInsights": { 45 "LogLevel": { 46 "Default": "Information" 47 } 48 } 49 } 50 }