C#⽇志记录分级功能使⽤按照⽇期,⼤⼩,或是单⽂件存储
本⽂将使⽤⼀个Nuget的⼀个组件库来实现⼀个简单强⼤的⽇志记录功能,包采⽤线程安全实现,所有的记录在后台完成,即使您在前台调⽤100万次⽅法,耗时也不过1000ms(具体时间依照电脑性能决定),⽀持⽇志等级,并提供了⼀个控件⽤于分析所有的⽇志消息。
在visual studio 中的Nuget管理器中可以下载安装,也可以直接在Nuget控制台输⼊下⾯的指令安装:
Install-Package HslCommunication
Nuget安装教程:
联系作者及加⽅式(激活码在⾥发放):
本组件提供了⼀个⽇志功能,实现了常⽤的3中⽇志模式:
单⽇志⽂件模式,⽇志始终都向该⽂件写⼊,需要程序中⾃⾏清除或⼿动编写代码清空,不然⽂件会很⼤。
根据⽂件⼤⼩存储的多⽂件模式,⼀个⽇志⽂件写⼊达到某个数值时,创建新⽂件写⼊。
根据时间⽇期的多⽂件模式,每条⽇志将根据写⼊的时间⽇志来判断⽂件名,⽐如创建按每天存储的⽇志。
我也曾使⽤过中⼤名⿍⿍的log4net⽇志组件,⼀般使⽤起来确实⽅便,但是我在诸如实现上述的需求的时候就特别⿇烦,⽽且log4net功能众多,⼤多数功能并不是我所需要的,我就需要⼀个实现txt⽇志的存储⽅式,简单⾼效,多种模式即可。于是就⾃⾏开发了⼀个简单⾼效的⽇志组件,并集成到了该通信库中,本⽇志组件还提供了⼀个分析控件及窗⼝,可以对⼀个长长的⽇志⽂件进⾏分析统计(只对本组件⽣成的⽇志有效),快速定位需要查的⽇志信息,⽀持使⽤正则表达式来筛选,本⽇志组件也提供了分级存储。
Demo程序下载
使⽤之前先要进⾏命名控件的引⽤,如下:
using HslCommunication.LogNet;
实例化
⾸先先实例化⼀个对象,如果您⽤于整个application的⽇志存储,可以定义成静态对象。或者直接定义在form窗⼝的下⾯也可以。此处先实例化单⽂件存储的机制
private ILogNet logNet = new LogNetSingle("D:\\");
我们通常的做法是⽇志⽂件存储在exe程序⽬录下的Logs⽂件夹中,⽆论在服务器端还是客户端都是⾮常适⽤的,所以
private ILogNet logNet = new LogNetSingle(Application.StartupPath + "\\Logs\\");
写⽇志
接下来你就可以在窗⼝的其他地⽅进⾏写⼊⽇志了,本组件提供了5个等级的⽇志写⼊功能,名称参考了常规的⽇志等级,有 DEBUG , INFO, WARN , ERROR , FATAL ,根据需要进⾏存储,还提供了对exception异常的⽅法⽀持和⾃定义的描述化⽂本写⼊,该⽂本不属于⽇志范畴,在⽇志分析中会被忽略,如下代码演⽰⼏种不同的写⼊(写⼊的⽅式采⽤统⼀的接⼝实现,对于三种⽇志模式都是适⽤的):
private void userButton1_Click(object sender, EventArgs e)
{
// ⼀般⽇志写⼊
logNet.WriteDebug("调试信息");
logNet.WriteInfo("⼀般信息");
logNet.WriteWarn("警告信息");
logNet.WriteError("错误信息");
logNet.WriteFatal("致命信息");
logNet.WriteException(null, new IndexOutOfRangeException());
// 带有关键字的写⼊,关键字建议为⽅法名或是类名,⽅便分析的时候归类搜索
logNet.WriteDebug("userButton1_Click", "调试信息");
logNet.WriteInfo("TestForm", "⼀般信息");
logNet.WriteWarn("随便什么", "警告信息");
logNet.WriteError("userButton1_Click", "错误信息");
logNet.WriteFatal("userButton1_Click", "致命信息");
logNet.WriteException("userButton1_Click", new IndexOutOfRangeException());
}
写⼊异常时会被⾃动赋予 FATAL 等级。写⼊效果如下:
下⾯再说明写⼊描述⽂本的时候发⽣的事情:
logNet.WriteDescrition("这是⼀条描述⽂本");
描述性⽂本的前⾯会再新增⼀⾏作为明显的区分。描述性⽂本不列⼊到⽇志分析⼯具中,会被⾃动被过滤。
设置等级
为什么要实现⽇志分级呢?有两个巨⼤的好处。第⼀个好处是⽅便在⽇志追述的时候进⾏筛选,⽐如我需要查看⽇志中致命错误的时候就尤为重要,可以进⾏快速的筛选。第⼆个好处就是⽤于开发的时候调试使⽤,有时候我们为了快速的到程序问题的时候,会对程序运⾏中各种数据状态,系统状态进⾏输出,然后分析⽇志得出结论。当你已经写了很多很多的
logNet.WriteDebug("调试信息");
代码后,准备发布使⽤的时候不想输出这种仅⽤于调试的时候的⽇志,总不可能取消所有的调试⽇志吧?效率太低,万⼀以后需要恢复输出就⿇烦了,所以本⽇志组件⽀持写⼊⽇志的时候的等级设置,如果我们把⽇志的等级设置为INFO级别,那么所有的DEBUG级别的⽇志都不会存储,所以我们在发布软件的时候,只要设置等级就⾏。
下⾯再来说明下如何设置⽇志存储等级。使⽤⽅法:
logNet.SetMessageDegree(HslMessageDegree.DEBUG);//所有等级存储
logNet.SetMessageDegree(HslMessageDegree.INFO);//除DEBUG外,都存储
logNet.SetMessageDegree(HslMessageDegree.WARN);//除DEBUG和INFO外,都存储
logNet.SetMessageDegree(HslMessageDegree.ERROR);//只存储ERROR和FATAL
logNet.SetMessageDegree(HslMessageDegree.FATAL);//只存储FATAL
logNet.SetMessageDegree(HslMessageDegree.None);//不存储任何等级
选择上⾯的⼀⾏代码执⾏就⾏。
⾃定义事件
组件默认存储所有的等级,如果需要设置,在实例化后即可设置等级。⽇志组件⽀持⼀个事件,在所有的⽇志进⾏存储前(被⽇志等级过滤掉的不会触发)会报告事件,可以⽤于其他操作或是控制台的显⽰等等,注意:如果在事件关联⽅法中直接访问UI线程,会异常
这个事件有个⾮常⼤的好处,可以统⼀输出显⽰你的程序中所有地⽅的⽇志,⽅便统⼀的控制和处理。
logNet.BeforeSaveToFile += LogNet_BeforeSaveToFile;
private void LogNet_BeforeSaveToFile(object sender, HslEventArgs e)
{
// 如果需要UI显⽰,就要取消注释下⽅的代码
//if(InvokeRequired)
//{
/大文件发送
/    Invoke(new Action(() =>{
//        LogNet_BeforeSaveToFile(sender, e);
//    }));
//    return;
//}
string degree = e.HslMessage.Degree.ToString();//获取等级
DateTime time = e.HslMessage.Time;//获取时间
string text = e.HslMessage.Text;//⽇志⽂本
int threadId = e.HslMessage.ThreadId;//记录⽇志的线程id
}
这个事件在2019年2⽉10⽇ 16:36:41上新增了⼀个额外的功能,就是允许你⼿动取消当前⽇志的存储
private void LogNet_BeforeSaveToFile( object sender, HslEventArgs e )
{
e.HslMessage.Cancel = checkBox1.Checked;
}
假设这样设置后,所有的⽇志都不存储到⽂件中去。
private void LogNet_BeforeSaveToFile( object sender, HslEventArgs e )
{
if (e.HslMessage.Degree != HslMessageDegree.INFO)
{
e.HslMessage.Cancel = checkBox1.Checked;
}
}
如果这么写,就是只存储INFO等级的⽇志信息。
过滤指定的关键字⽇志存储
有些⽇志数据可能我们想要触发BeforeSaveToFile事件,但是不能存储到⽇志⽂件⾥,那么可以直接按照如下的配置进⾏设置,会过滤掉存储到⽂件中,如下就是过滤掉关键字的信息
logNet.FiltrateKeyword( "123" );
按⽂件⼤⼩存储的实例化
若要按照⽂件⼤⼩进⾏存储,例如⽇志存储2M后,⾃动⽣成新的⽂件,然后存满2M后⽣成新⽂件,如此重复,则需要指定⽂件的存储路径和⼤⼩,这种⽅式存储的⽂件名称不可控制,⾃动定义为 的格式,会以当前时间⾃动命名,如下举例了实例化⼀个2M⼤⼩的对象:
ILogNet logNet = new LogNetFileSize(Application.StartupPath + "\\customer1", 2 * 1024 * 1024);
只要定义了对象,就可以按照上述写⼊⽇志的代码来写了。
按时间⽇期存储的实例化
也是⼀种多⽂件的存储机制,和按照⼤⼩的存储⾮常类似,此处可以配置按照每⼩时⽣成新的⽂件,每天新的⽂件,每⽉新的⽂件,每季度新的⽂件,每年新的⽂件,⽣成的⽂件名称也是固定的,需要指定路径和存储模式:
ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2",GenerateMode.ByEveryHour);//按每⼩时
ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2", GenerateMode.ByEveryDay);//按每天
ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2", GenerateMode.ByEveryMonth);//按每⽉
ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2", GenerateMode.ByEverySeason);//按每季度
ILogNet logNet = new LogNetDateTime(Application.StartupPath + "\\customer2", GenerateMode.ByEveryYear);//按每年
单⽂件模式
单⽂件的模式在上述已经作为演⽰说明过了,但是单⽂件模式提供了两个额外的⽅法:
获取该⽂件⽇志中所有的内容
清空该⽂件的所有数据
具体的代码如下所⽰:
LogNetSingle logNetSingle = logNet as LogNetSingle;
if (logNetSingle != null)
{
string logData = logNetSingle.GetAllSavedLog();//获取所有的⽇志信息
logNetSingle.ClearLog();//清除所有的⽇志信息
}
⽇志查看器
如果只提供了⼀个⽇志的写⼊⽽没有分析⼯具,那么本组件就是没什么竞争⼒的,本⽇志组件提供了⼀个⼤杀器,⽇志分析控件!您可以集成到您⾃⼰的系统中,该控件只需要接受⼀个⽇志源字符串(就是⽇志⽂件的所有字符串数据,服务器读取⽂件发送给远程客户端就可以现实远程查看⽇志分析!棒不棒!)原先的 ClientServerProject 项⽬中已经带有了2个⽇志查看器,⼀个服务器端使⽤了本组件提供的标准form窗⼝,客户端使⽤了⽇志分析控件实现远程查看功能,具体代码可以参照 ClientServerProject 项⽬的代码。
功能概述
对⽇志⽂件中的所有等级⽇志进⾏分析,每种等级多少个
可以同时根据⽇志等级和时间区段来筛选⽇志,⽐如查看某⼀时间段的 DEBUG 等级⽇志
可以进⾏可视化分析,查看⽇志数据的时间分布情况
在可视化的界⾯,如果某个区间段的某⽇数量特别⾼,⿏标移动上去后还可以⾃动跳转
此处直接演⽰⼀个组件标准的⽇志查看窗⼝,这个窗⼝也可以在wpf项⽬中显⽰:
private void userButton13_Click(object sender, EventArgs e)
{
// ⽇志查看器
using (HslCommunication.LogNet.FormLogNetView form = new HslCommunication.LogNet.FormLogNetView())
{
form.ShowDialog();
}
}
效果上图
查看⽇志信息
上图中点击了信息按钮后,显⽰的图形发⽣了变化,只显⽰了信息等级⽇志