一、log4net
log4net是一个可以帮助程序员把日志信息输出到各种 不同目标的.net类库。它可以容易的加载到开发项目中,实现程序调试和运行的时候的日志信息输出,提供了比.net自己提供的debug类和trace 类的功能更多。log4net是从java下有卓越表现的log4j移植过来的。它是apache基金资助的项目的一部分。
二、创建项目
先看下结构,所用的NuGet包log4net 2.0.8,当前选中的是启动项目,LogManager是log4net帮助类,实际应用中直接Copy项目即可。
代码相对简单,先上代码,主要在配置,
1 /// <summary> 2 /// 写日志类 3 /// </summary> 4 public class LogEvent 5 { 6 /// <summary> 7 /// 默认日志对象 8 /// </summary> 9 public static ILog Loger 10 { 11 get 12 { 13 return GetLoger("Default"); 14 } 15 } 16 17 /// <summary> 18 /// 通知日志 19 /// </summary> 20 public static ILog LogInfo 21 { 22 get 23 { 24 return GetLoger("LogInfo"); 25 } 26 } 27 28 /// <summary> 29 /// 获取日志对象 30 /// </summary> 31 /// <param name="logerName">日志名称</param> 32 /// <returns></returns> 33 public static ILog GetLoger(string logerName) 34 { 35 return log4net.LogManager.GetLogger(logerName); 36 } 37 38 }
log4net.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 7 <log4net> 8 9 <!--<root> 10 <level value="ALL" /> 11 <appender-ref ref="InfoLog" /> 12 <appender-ref ref="ErrorLog"/> 13 </root>--> 14 15 <logger name="Default"> 16 <level value="ALL" /> 17 <appender-ref ref="InfoLog" /> 18 <appender-ref ref="ErrorLog"/> 19 </logger> 20 <appender name="ErrorLog" type="log4net.Appender.RollingFileAppender,log4net" > 21 <param name="File" value="log\DefaultError.log" /> 22 <param name="AppendToFile" value="true" /> 23 <param name="MaxSizeRollBackups" value="10" /> 24 <param name="MaximumFileSize" value="10MB" /> 25 <param name="RollingStyle" value="Size" /> 26 <param name="StaticLogFileName" value="true" /> 27 <layout type="log4net.Layout.PatternLayout,log4net"> 28 <param name="ConversionPattern" value="
Time:[%d]--Thread:[%t]--Class:[%C]--Method:[%M]--File:[%F]--Line:[%L]
%m%n" /> 29 <param name="Header" value="
----------------------Default Program Start--------------------------
" /> 30 <param name="Footer" value="
----------------------Default Program Stop--------------------------
" /> 31 </layout> 32 <filter type="log4net.Filter.LevelRangeFilter"> 33 <param name="LevelMin" value="ERROR" /> 34 <param name="LevelMax" value="OFF" /> 35 </filter> 36 </appender> 37 <appender name="InfoLog" type="log4net.Appender.RollingFileAppender,log4net" > 38 <param name="File" value="log\DefaultInfo.log" /> 39 <param name="AppendToFile" value="true" /> 40 <param name="MaxSizeRollBackups" value="10" /> 41 <param name="MaximumFileSize" value="10MB" /> 42 <param name="RollingStyle" value="Size" /> 43 <param name="StaticLogFileName" value="true" /> 44 <layout type="log4net.Layout.PatternLayout,log4net"> 45 <param name="ConversionPattern" value="
Time:[%d]--Thread:[%t]--Class:[%C]--Method:[%M]
%m%n" /> 46 <param name="Header" value="
----------------------Default Program Start--------------------------
" /> 47 <param name="Footer" value="
----------------------Default Program Stop--------------------------
" /> 48 </layout> 49 <filter type="log4net.Filter.LevelRangeFilter"> 50 <param name="LevelMin" value="ALL" /> 51 <param name="LevelMax" value="WARN" /> 52 </filter> 53 </appender> 54 55 56 <logger name="LogInfo"> 57 <level value="ALL" /> 58 <appender-ref ref="LogInfoAppender" /> 59 </logger> 60 <appender name="LogInfoAppender" type="log4net.Appender.RollingFileAppender,log4net" > 61 <param name="File" value="log\Log.log" /> 62 <param name="AppendToFile" value="true" /> 63 <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 64 <param name="MaxSizeRollBackups" value="10" /> 65 <param name="MaximumFileSize" value="5MB" /> 66 <param name="RollingStyle" value="Size" /> 67 <param name="StaticLogFileName" value="true" /> 68 <layout type="log4net.Layout.PatternLayout,log4net"> 69 <param name="ConversionPattern" value="
Time:[%d]--Thread:[%t]--Class:[%C]--Method:[%M]--File:[%F]--Line:[%L]
%m%n" /> 70 <param name="Header" value="
----------------------Notification Program Start--------------------------
" /> 71 <param name="Footer" value="
----------------------Notification Program Stop--------------------------
" /> 72 </layout> 73 <filter type="log4net.Filter.LevelRangeFilter"> 74 <param name="LevelMin" value="ALL" /> 75 <param name="LevelMax" value="OFF" /> 76 </filter> 77 </appender> 78 </log4net> 79 80 </configuration>
执行写日志代码,
1 for(int i = 0; i < 100; i++) 2 { 3 LogEvent.Loger.Debug("Debug..................Debug............................Debug.........................."); 4 LogEvent.Loger.DebugFormat("Debug..................Debug............................Debug..........................{0}", i); 5 LogEvent.Loger.Info("Info.....................Info............................Info..........................."); 6 LogEvent.Loger.InfoFormat("Info.....................Info............................Info...........................{0}", i); 7 LogEvent.Loger.Error("Error....................Error.............................Error......................."); 8 LogEvent.Loger.ErrorFormat("Error....................Error.............................Error.......................{0}", i); 9 LogEvent.Loger.Fatal("Fatal....................Fatal.............................Fatal......................."); 10 LogEvent.Loger.FatalFormat("Fatal....................Fatal.............................Fatal.......................{0}", i); 11 12 13 LogEvent.LogInfo.Debug("Debug..................Debug............................Debug.........................."); 14 LogEvent.LogInfo.DebugFormat("Debug..................Debug............................Debug..........................{0}", i); 15 LogEvent.LogInfo.Info("Info.....................Info............................Info..........................."); 16 LogEvent.LogInfo.InfoFormat("Info.....................Info............................Info...........................{0}", i); 17 LogEvent.LogInfo.Error("Error....................Error.............................Error......................."); 18 LogEvent.LogInfo.ErrorFormat("Error....................Error.............................Error.......................{0}", i); 19 LogEvent.LogInfo.Fatal("Fatal....................Fatal.............................Fatal......................."); 20 LogEvent.LogInfo.FatalFormat("Fatal....................Fatal.............................Fatal.......................{0}", i); 21 } 22 23 Console.ReadKey();
如果现在执行,在程序的输出文件中是看不到任何日志文件的,
需要在启动项目的AssemblyInfo.cs中添加如下,
//日志
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
这是为项目注册log4net.config配置文件,否则的话你的配置是不能加载的,
之后再执行写日志,发现还是没有输出日志的文件,这是log4net.config没有设置复制到输出目录,右键属性,复制到输出目录,始终复制,
执行,会发现有输出日志文件啦,
打开日志看下里面是不是与想象的一样,接下来分析下log4net.config内容是怎么配置生成日志的规则的。
先说下刚才代码中的Debug、Info等日志等级,Format是输出格式,
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
穿插下日志吧,
在程序中写日志是一件非常重要,但是很容易被开发人员忽视的地方。写好程序的日志可以帮助我们大大减轻后期维护压力。在实际的工作中,开发人员往往迫于巨大时间压力,而写日志又是一个非常繁琐的事情,往往没有引起足够的重视。开发人员应在一开始就养成良好的日志撰写习惯,并且应在实际的开发工作中为写日志预留足够的时间。
一般程序日志出自下面几个方面的需求:
1. 记录用户操作的审计日志,甚至有的时候就是监管部门的要求。
2. 快速定位问题的根源
3. 追踪程序执行的过程。
4. 追踪数据的变化
5. 数据统计和性能分析
6. 采集运行环境数据
一般在程序上线之后,一旦发生异常,第一件事就是要弄清楚当时发生了什么。用户当时做了什么操作,环境有无影响,数据有什么变化,是不是反复发生等,然后再进一步的确定大致是哪个方面的问题。确定是程序的问题之后再交由开发人员去重现、研究、提出解决方案。这时,日志就给我们提供了第一手的资料。
日志级别 ALL<TRACE<DEBUG<INFO<WARN<ERROR<FATAL<OFF
1. TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。TRACE一般跟踪的是函数的调用,并且TRACE不应该含有变量参数,而仅能提示函数的调用关系。
2. DEBUG 一般用于细粒度级别上,对调试应用程序非常有帮助,主要用于开发过程中打印一些运行信息。
3. INFO消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
4. WARN表示会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员一些提示。该级别表示程序会自动调整到正常的状态,类似参数未传入,使用了默认的参数,仍符合程序员预期之内的情况。
5. ERROR指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。一般在WARN之后的级别在打印错误时,应该同时打印错误码。
6. FATAL指出每个严重的错误事件将会导致应用程序的退出,这个级别比较高,重大错误,程序无法恢复,必须通过重启程序来解决。
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
首先,把config文件内容压缩起来,如下图,这两个名称就是我们在LogEvent.cs文件中的定义的两个方法的名称,相当于你调用方法的进行了switch case操作,找到相应的写配置内容,其中appender后是在这个基础上延伸出来的多个文件夹,比如,你按照日志等级可以写多文件呀,DEBUG写debug文件,INFO写info文件等等。
展开其中一个logger和appender,logger里面显示的就是你之后追加了几种写日志的方式,解释各个param的作用:
File是日志存储路径,输出到什么目录,
AppendToFile是否覆写文件,意思就是启动的时候如果当前文件夹存在同名文件,若此值为true,则继续写到同名文件中,若为false,就是先备份此文件,再新建同名文件进行写入,
MaxSizeRollBackups,当前文件夹中,同名的文件最大个数,比如DefaultError.log,当前文件写到10M,则重命名为DefaultError.log.1,又新建一个DefaultError.log,直到到DefaultError.log.10,之后9的就会把10的覆盖,一次这样,文件夹中就会只有10个存在,保证磁盘空间,
MaximumFileSize,每个文件的大小,每到10M就会新生成一个文件,
RollingStyle,默认滚动样式,在这里是Size,就是大小,也就是10M,新生成一个文件,而不是通过日期进行滚动,
StaticLogFileName,是否采用静态文件名,就是文件的名称是否是静态的,不变的,若RollingStyle为Date,就可以设置StaticLogFileName为false,根据日期来生成,这样子你的文件名就是动态的,
layout是布局,即写日志的文件格式,内容的格式信息,可参考官方文档,
filter是过滤生成文件的条件,当前是范围输出,即满足当前范围条件,才到此文件中,这个范围也就是日志等级,