说实话,我并不是太想写这篇文章,因为我承诺过要完成博客园的部分功能,所以一直都在积极的利用下班时间来完善这个系统, 但是我又不想让看我源代码的朋友不知道我写的代码是什么意思,所以我还是单独写一个文章,叙述一下我对管理日志的看法, 当然主要是log4net的使用。为了写这篇文章,我查看了博客园的很多关于log4net的文章,但是结果令我很不满意,因为他们对于log4net的介绍基本上都是大同小异, 我不敢说他们写的有错,因为确实就是那么写的,但是为什么我还要写这篇博客呢,因为我想以一个学习者的心态来分析这个框架结构,而不是以一个老师来分析。 从一个学习者到老师需要很多的路要走的,他们都省略了学习者入门时的困难,所以我决定还是来写一篇博客来叙述一下。希望大家吐槽。
首先,现在系统越来越复杂,并且集成的模块也越来越多,在测试系统的时候我们可以利用单元测试(有单元测试框架支持,比如nunit等), 还可以通过认为的点击来测试系统功能的正常,在开发过程中我们可以测试出来很多的问题。但是在系统已经部署到服务器上以后,我们就不能进行单元测试了, 因为部署到服务器上的不是源码,当然也有其他的方式可以测试系统bug,但是在实际环境中会出现很多令人意想不到的问题。举个简单的例子,虽然我们会在系统中进行异常的捕获, 并且会显示特定的错误信息,但是错误信息是对用户显示的,我们开发者当然希望知道错误的详细信息,以便我们可以改正错误。这是必须的,所以最简单也最直接的方式就出现了, 就是记录系统日志,当然如果不采用log4net日志管理框架,我们也是可以通过文件操作来写入日志,但是这个不便于配置。正如我听到的一个老师说的, 如果你的系统要进行扩展,那么你会怎么办?这是当时很令我头疼的一个问题,但是我现在基本知道思路,就是采用分层开发模式,将不同的层放到对应的类库中, 另外我们也可以采用IOC(依赖注入)或者Nhibernate等框架来提高系统的灵活性。
废话太多,大家都会没有耐心看下去,但是如果这是代码,我估计大家更不会看下去。呵呵
因为园子里有很多介绍log4net的介绍,所以我就不详细的介绍了,我只说我个人认为在开发中是重点的,欢迎大家吐槽~~
我们知道log4net有一个姐妹叫log4j,他们是针对.Net和java开发的两个结构基本相同的框架结构, 看到这种说法,我一直想说,为什么好的框架都会从java移植而来,并且都是apache这个组织开发的呢?这里面也不是我能理解的,我也是吐槽一下。
log4net主要由Appender,Logger,Filter,Layout和一个Object Render组成。
其中
Appender(附着器)主要用来确定日志记录的位置,也可以这么说就是确定日志是记录到数据库还是文件或其他终端。
Logger(记录器),记录器 看字面意思就应该可以猜到他就是用来确定要发送的日志信息。比如说,有一个异常发生,我们需要记录什么数据,都是由Logger负责的。
Filter(过滤器) 可以这么理解,这个和MVC中的Filter还是有差别的,这里的Filter表示的是过滤,就像筛子 可以过滤一样,而MVC中的Filter也可以叫做过滤器,但是它更多的是完成
Aop(面向切面或面向方面) 的横向的过滤导向,也可以认为是对某个Action或Controller施加的限制。
Layout(布局) 布局很容易理解,就像装修一样,把我们要记录的数据整理成我们需要的格式。
至于后面的object render,我在官方文章看了一下,个人理解就相当于渲染输出,就像服务器发送html到浏览器以后,浏览器要渲染输出的效果应该是一样。
简单的描述了一下log4net的组成,还有很重要的就是log4net的分级,其中log4net一种氛围5级,按从高到低的顺序依次为:
off>fatal>Error>Warn>Info>Debug>All
看到这个分级,大家一定要骂我了,一共有七个值,偏偏说5个分级,这里我解释一下,off的意思就是关闭log4net的日志输出,
fatal的级别最高,表示的就是特别严重的错误,一般是在应用程序崩溃的时候,而error则是表示错误出现,一般用在出现了异常以后,
Warn表示警告,这个不会使程序出现异常,但是可能会影响程序性能,info 和debug则可以随意了。另外all表示的就是所有的分级都可以满足。
这里大家要注意一下的就是,这个分级是会影响程序日志输出的。比如说你在程序中定义了 log.Info(message) 和log.debug(message),但是你定义的日志应当输出的级别是info,很抱歉
的告诉你,log.debug(message)中的信息不会写入日志,因为debug在顺序中是小于info的。
说了log4net中最重要的两个部分,现在就需要正式的启用log4net来输出日志信息了,签于园友们都有很详细的配置信息,所以我就把主要的两个简单的描述一下,如果有需要我会在注释中
写入的。在项目中我们一般会用到输出日志到文件或者数据库中,这两种方式,我个人也非常喜欢这两种方式。一般我会把日志同时输出到文件和数据库中,虽然会有一点的性能损失,但是对于
日志的完整性还是十分值得的,当然输出的日志越少性能会越高,大家都懂得。
log4net是支持配置文件来更改其输出方式的,我们可以把配置文件放到项目配置文件web.config或winform的app.config中,也可以单独的放到固定的配置文件中,现在我们把配置文件放
到项目配置文件中。
配置文件如下
12 3 45 、 6 7 8 129 10 1113 29 3314 15 16 17 18 19 20 21 22 23 2524 26 2827 34 8235 36 37 38 39 4340 41 42 44 5145 46 47 48 5049 52 5953 54 55 56 5857 60 6761 62 63 64 6665 68 7569 70 71 72 7473 76 8177 78 79 80 83 91 9684 85 86 87 88 9089 97 10698 99 -->100 101 102 103 104 105
在配置文件创建好了以后,按道理说就可以在程序中使用log4net了,创建Log4NetController,在该控制器中进行对log4net的测试
1 public class Log4netController : Controller 2 { 3 4 private static readonly log4net.ILog log = log4net.LogManager.GetLogger("rolling"); 5 6 public ActionResult Index() 7 { 8 log4net.Config.XmlConfigurator.Configure(); 9 10 log.Info("log日志信息");11 log.Debug("debug信息");12 log.Error("error信息");13 log.Warn("warn信息");14 Exception ex = new Exception("这里显示的是异常信息");15 log.Fatal("fatal信息", ex);16 return View();17 }18 19 }
运行程序,就可以在数据库中看到日志生成的记录
说明log4net的日志记录到数据库是正确的。下面我们来分析一下,因为我是在把代码复制到博客中才加的注释,所以不是C#标准的注释方式,
下面我们来把使用log4net中要注意的地方或者我认为是会令人疑惑的地方叙述一下,
-
其实我们在配置log4net的时候最好是直接复制原来可以运行的配置文件,然后进行修改,因为如果你的配置文件有一点错误,那么log4net都不会正常工作的,
这里还有一个更严重的问题就是我们不会得到log4net引发的任何异常。我们只能是慢慢修改,有耐心,最好是复制 粘贴
-
96
97 98 99 -->100 101 102 103 104 105
这段代码中的root和logger结点我们需要注意一下,因为在root中定义的是针对所有的logger,也就是说如果你在程序中使用的不是LogManager.getLogger(Loggername)这种方式,那么你默认的会使用root结点的配置信息来记录日志,而如果你使用了这种方式,那么就会使用对应的logger结点的配置信息。
3.log4net是可配置、可修改的灵活日志输出,我们必须在程序中对log4net进行配置。
log4net.Config.XmlConfigurator.Configure(); 这个是默认的配置方式,当然我们也可以利用参数中加入配置文件路径来指定配置文件。这个是必须要配置的,切记。
还有就是这个配置应当是在程序启动时就需要配置完成,因此在application_start中是比较好的方法。
4.log4net输出日志的时候我们看到了很多的%形式,这是表示的什么意思呢?其实%thread 就是表示当前的线程名称,%level就是表示日志的级别。
5.最后我还想补充一下,任何和程序执行无关的代码都会影响程序的性能,日志的输出和程序功能的完成没有直接的关系,过多的日志输出会影响程序响应的性能,另外我们要控制删除日志的级别,以便不要任何日志信息都会输出。
6.通过 private static readonly log4net.ILog log = log4net.LogManager.GetLogger("rolling"); 可以的到一个log对象,但是我们如何确定是否需要输出到对应的级别呢?
log4net提供了
我们可以通过这几个属性来判断是否需要输出不同级别的日志。
暂时想到的就这么多,我想到别的还会加上,欢迎吐槽 补充一下:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
这个可以用来对RolingFile进行更好的控制