在项目正式上线后,如果出现错误,异常,崩溃等情况
我们往往第一想到的事就是查看日志
所以日志对于一个系统的维护是非常重要的
声明正文中的代码只是一个栗子,一个非常简单的栗子,只是说明这个框架是怎么工作的
具体实现可以自由发挥~~~~
贯穿所有的日志系统日志系统,往往是贯穿一个程序的所有代码的;
试想一下,如果你的日志完全是由第三方组件提供的;
那么就意味着,你的所有项目都必须引用这个dll;
也许你会说自己可以2次封装,那么依然需要所有项目都引用你的这个封装后的log项目
另一方面
一些log组件需要实例化后才可以使用,比如log4net,这又意味着你得有一个全局的静态变量,或者你自己二次封装
但其实微软已经为我们提供了2个十分方便的静态类,用于日志的记录
System.Diagnostics.Trace和System.Diagnostics.Debug关于这2个类的文档可以去看MSDN
System.Diagnostics.Trace
System.Diagnostics.Debug
他的使用真的是非常的方便,以至于你只要使用一次就会爱上他
不用引用任何dll,因为他是微软自家的东西,就在System.dll中
调用他的方法也很简单usingSystem.Diagnostics;
...
...Trace.TraceError("这是一个Error级别的日志");Trace.TraceWarning("这是一个Warning级别的日志");Trace.TraceInformation("这是一个Info级别的日志");Trace.WriteLine("这是一个普通日志");Trace.Flush();//立即输出...
...
当然方法不止只有4个,更多的可以参考MSDN
Trace,Debug的调用方式完全相同,不同的地方在于
Debug的所有方法都有
[Conditional("DEBUG")]
表明了,在Release模式下(没有定义DEBUG常量时),该方法不会被编译的(不是不执行,而是根本不会编译到程序中去)
也就是说 Debug.XXX() 方法仅在Debug模式下运行,这个又可以为我们省下很多事
重写日志实现Trace和Debug中的方法的默认行为是输出到控制台Console,和Console.Write是一样的
但是我们通过改变他的监听器TraceListener,来实现更多的操作
必须实现的方法有
voidWrite(stringmessage);voidWriteLine(stringmessage);
不过也可以主动重写其他方法
随便写一个MyTraceListener
classMyTraceListener : TraceListener
{publicoverridevoidWrite(stringmessage)
{
File.AppendAllText("d:\\1.log",message);
}publicoverridevoidWriteLine(stringmessage)
{
File.AppendAllText("d:\\1.log", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + message +Environment.NewLine);
}
}
现在程序入口中初始化监听器Trace.Listeners
PS下:Trace和Debug的监听器的共用的
staticvoidMain(string[] args)
{
Trace.Listeners.Clear();//清除系统监听器 (就是输出到Console的那个)Trace.Listeners.Add(newMyTraceListener());//添加MyTraceListener实例}
在随便来个方法测试下
PRivatestaticvoidTest()
{try{inti =0;
Console.WriteLine(5/ i);//出现除0异常}catch(Exception ex)
{
Trace.TraceError("出现异常:"+ ex.Message);//记录日志}
}
由于大部分方法都是可重写的,所以其实最终输出什么都是可以灵活处理的
例如这样
publicoverridevoidWrite(objecto,stringcategory)
{stringmsg ="";if(string.IsNullOrWhiteSpace(category) ==false)//category参数不为空{
msg= category +":";
}if(oisException)//如果参数o是异常类,输出异常消息+堆栈,否则输出o.ToString(){varex =(Exception)o;
msg += ex.Message +Environment.NewLine;
msg+=ex.StackTrace;
}elseif(o !=null)
{
msg=o.ToString();
}
WriteLine(msg);
}
privatestaticvoidTest()
{try{inti =0;
Console.WriteLine(5/ i);//出现除0异常}catch(Exception ex)
{Trace.Write(ex,"计算员工工资出现异常");}
}
其他的就自己举一反三了
通过配置文件初始化监听器通过配置文件初始化监听器比直接写代码稍稍复杂一点,但是也更方便,我们可以快速的,不重新编译系统,即可进行对日志监听器进行设定
特别是在Web项目中,这将变得更加方便
我把刚才的MyTraceListener独立成一个项目,编译为dll
并且为他增加一个构造函数和FilePath属性用于设置将log文件的位置
publicclassMyTraceListener : TraceListener
{publicstringFilePath {get;privateset; }publicMyTraceListener(stringfilepath)
{
FilePath=filepath;
}publicoverridevoidWrite(stringmessage)
{
File.AppendAllText(FilePath, message);
}publicoverridevoidWriteLine(stringmessage)
{
File.AppendAllText(FilePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + message +Environment.NewLine);
}publicoverridevoidWrite(objecto,stringcategory)
{stringmsg ="";if(string.IsNullOrWhiteSpace(category) ==false)//category参数不为空{
msg= category +":";
}if(oisException)//如果参数o是异常类,输出异常消息+堆栈,否则输出o.ToString(){varex =(Exception)o;
msg+= ex.Message +Environment.NewLine;
msg+=ex.StackTrace;
}elseif(o !=null)
{
msg=o.ToString();
}
WriteLine(msg);
}
}
MyTraceListener
配置文件
<?xmlversion="1.0" encoding="utf-8"?><configuration><system.diagnostics><traceautoflush="false"indentsize="4"><listeners><clear/><!--清除默认监听器--><!--添加自定义监听器 initializeData 就是初始化参数--><addname="MyTraceListener"type="MyLog.MyTraceListener, MyLog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"initializeData="d:\1.log"/></listeners></trace><switches><!--这里可以设定监听级别,可以设置Error,Warning,Info或者留空--><addname="MyTraceListener"value="Error"/></switches></system.diagnostics></configuration>
其中type参数可以这样获得
typeof(MyLog.MyTraceListener).AssemblyQualifiedName
Version,Culture,PublicKeyToken 也可以忽略
测试一下
没有任何问题
而且如果你用了log4net等第三方组件的话,只需要在实现TraceListener的项目中引用log4net就可以了
说完了...拜拜~~
代码下载LogDemo.rar
撸主发飙了.......#13楼 2014-04-02 09:25 永远的麦子
兄弟写得非常好。
不过我有两个问题:
1,目前是往文本文件写,如果同时也要往系统事件或数据库中写,要怎么处理?
2,像企业库这些第三方组件,可以设置按日期或限定文件大小去循环生成日志,这又要怎么处理?
#14楼 2014-04-02 09:26 潇湘吹雨
博客君,这个Trace方式,在写入操作比较频繁的时候,经常出现很多guid命名的文件,然后写入的一条内容
#23楼 2014-04-02 10:27 censhao
不错,适用简单的程序。
复杂的程序,比如轻易就能产生几G日志文件的程序里还是log4net好用。
兄弟们啊,你们真的是来看文章的吗? 不是我的对手派来玩我的吧...............咳咳....鸡冻了.....
好吧,怪我没说清楚,我再集中这些问题,用一个栗子简单回答一下
publicclassMyTraceListener : TraceListener
{
log4net _log=newlog4net();publicMyTraceListener(stringfilepath)
{
_log=newlog4net();
_log.FilePath=filepath;
}publicoverridevoidWrite(stringmessage)
{
_log.Info(message);
}publicoverridevoidWriteLine(stringmessage)
{
_log.Info(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + message +Environment.NewLine);
}
}
这样是不是就可以用log4net了啊,是不是就可以用其他log系统了啊 ,是不是就想写数据库就写数据库 想写文件就写文件, 写干啥就干啥了啊~~~~~~
兄弟们啊~~~~~~~