在日志类里开启一个刷盘的线程,在闲时是不运行,也不会占用很多的系统资源,因为WaitOne()水阀状态是关闭着的。一旦别的线程往缓冲队列里写日志数据,就用Set()信号量通知打开水阀,日志刷盘完毕后,用Reset()信号量通知把水阀关起来。
这样就用信号量的原理实现了即时刷盘的机制。
六:RollingFile日志
在特别的场景下,比如即时消息系统,WEB应用系统,日志量都很大,一天可以达到G级别量的日志,一般情况下,记录本文件超过10M,打开速度就比较慢,而且不便于定位和查看。这时就需要对日志文件进行分割,分割日志文件常用的手法一般从两个维度进行,一个是按时间维度,一个是按日志的体积。NLogger采用了时间维度和日志维度叠加的方法来进行日志的分割。
分割日志是一件很容易的事情,难的是对新的日志文件的命名,比如现在的日志文件名是test_20170212(7).log,怎么能计算出下一个日志文件应该是test_20170212(8).log呢?用正则表达式的方式,先匹配出文件名的数字,再计算出下一个文件的名字。这儿的正则式就有含量了,抗干扰性要强,容错性要高,才能匹配出更精准的数字。
七:支持日志存储位置,日志文件前缀的个性化定义
并不是每个程序的日志信息都存储在自身程序目录里,有可能定义到其它盘符,或者其它服务器上的共享目录,支持日志存储位置自定义是有必要的。
不同的应用场景,为了区分日志的分类,有必要在日志文件名前加一个前缀,很幸运NLoger支持了这一功能。
八:与标杆日志组件log4net一试高低
Log4net的普及度是很高的,这儿不做详细介绍如何配置使用了。把测试的代码贴出来,熟手一看就明白了。
这儿做一个Log4net的标配文件:
为了测试的公平性,测试代码的逻辑与测试数据和NLogger都是相同的:
for (int count = 0; count < 10; count++) { Thread writeThread = new Thread(new ParameterizedThreadStart((para) => { log4net.ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); Console.WriteLine(, para)); Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 100000; i++) { log.Info(, i.ToString())); } sw.Stop(); Console.WriteLine(, para, sw.ElapsedMilliseconds)); })); writeThread.IsBackground = true; writeThread.Start(count); }
log4net写日志,测试开启10个线程,共写100W条数据到硬盘,吃了个午饭回来还没有执行结束。NLogger 10秒刷100W条数据到缓存,50秒刷100W条数据到硬盘,这样的对比,意义已经不大了。
测试源码下载(包括NLogger .net2.0版源码)
想了解更多,请翻阅以前的博客,在网页右下角点击推荐。
下篇将NLogger .net4.0版贴出来,性能是优于.net2.0版的。