利用C#自带组件强壮程序日志

在项目正式上线后,若是出现错误,异常,崩溃等状况html

咱们每每第一想到的事就是查看日志数据库

因此日志对于一个系统的维护是很是重要的app

声明

正文中的代码只是一个栗子,一个很是简单的栗子,只是说明这个框架是怎么工做的框架

具体实现能够自由发挥~~~~ide

贯穿全部的日志系统

日志系统,每每是贯穿一个程序的全部代码的;函数

试想一下,若是你的日志彻底是由第三方组件提供的;测试

那么就意味着,你的全部项目都必须引用这个dll;ui

也许你会说本身能够2次封装,那么依然须要全部项目都引用你的这个封装后的log项目spa

另外一方面debug

一些log组件须要实例化后才可使用,好比log4net,这又意味着你得有一个全局的静态变量,或者你本身二次封装

 

但其实微软已经为咱们提供了2个十分方便的静态类,用于日志的记录

System.Diagnostics.Trace和System.Diagnostics.Debug

关于这2个类的文档能够去看MSDN

System.Diagnostics.Trace

System.Diagnostics.Debug

他的使用真的是很是的方便,以致于你只要使用一次就会爱上他

不用引用任何dll,由于他是微软自家的东西,就在System.dll中

调用他的方法也很简单

using System.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,来实现更多的操做

必须实现的方法有

void Write(string message);
void WriteLine(string message);

不过也能够主动重写其余方法

随便写一个MyTraceListener

class MyTraceListener : TraceListener
{
    public override void Write(string message)
    {
        File.AppendAllText("d:\\1.log",message);
    }

    public override void WriteLine(string message)
    {
        File.AppendAllText("d:\\1.log", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss    ") + message + Environment.NewLine);
    }
}

如今程序入口中初始化监听器Trace.Listeners

PS下:Trace和Debug的监听器的共用的

static void Main(string[] args)
{
    Trace.Listeners.Clear();  //清除系统监听器 (就是输出到Console的那个)
    Trace.Listeners.Add(new MyTraceListener()); //添加MyTraceListener实例
}

在随便来个方法测试下

private static void Test()
{
    try
    {
        int i = 0;
        Console.WriteLine(5 / i); //出现除0异常
    }
    catch (Exception ex)
    {
        Trace.TraceError("出现异常:" + ex.Message);//记录日志
    }
}

因为大部分方法都是可重写的,因此其实最终输出什么都是能够灵活处理的

例如这样

public override void Write(object o, string category)
{
    string msg = "";
    if (string.IsNullOrWhiteSpace(category) == false) //category参数不为空
    {
        msg = category + " : ";
    }
    if (o is Exception) //若是参数o是异常类,输出异常消息+堆栈,不然输出o.ToString()
    {
        var ex = (Exception)o;
        msg += ex.Message + Environment.NewLine; 
        msg += ex.StackTrace;
    }
    else if(o != null)
    {
        msg = o.ToString();
    }
    WriteLine(msg);
}
private static void Test()
{
    try
    {
        int i = 0;
        Console.WriteLine(5 / i); //出现除0异常
    }
    catch (Exception ex)
    {
        Trace.Write(ex, "计算员工工资出现异常");
    }
}

其余的就本身触类旁通

经过配置文件初始化监听器

经过配置文件初始化监听器比直接写代码稍稍复杂一点,可是也更方便,咱们能够快速的,不从新编译系统,便可进行对日志监听器进行设定

特别是在Web项目中,这将变得更加方便

 

我把刚才的MyTraceListener独立成一个项目,编译为dll

而且为他增长一个构造函数和FilePath属性用于设置将log文件的位置

    public class MyTraceListener : TraceListener
    {
        public string FilePath { get; private set; }

        public MyTraceListener(string filepath)
        {
            FilePath = filepath;
        }

        public override void Write(string message)
        {
            File.AppendAllText(FilePath, message);
        }

        public override void WriteLine(string message)
        {
            File.AppendAllText(FilePath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss    ") + message + Environment.NewLine);
        }

        public override void Write(object o, string category)
        {
            string msg = "";

            if (string.IsNullOrWhiteSpace(category) == false) //category参数不为空
            {
                msg = category + " : ";
            }

            if (o is Exception) //若是参数o是异常类,输出异常消息+堆栈,不然输出o.ToString()
            {
                var ex = (Exception)o;
                msg += ex.Message + Environment.NewLine;
                msg += ex.StackTrace;
            }
            else if (o != null)
            {
                msg = o.ToString();
            }

            WriteLine(msg);
        }
    }
MyTraceListener
配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="false" indentsize="4">
      <listeners>
        <clear /><!--清除默认监听器-->
        <!--添加自定义监听器 initializeData 就是初始化参数-->
        <add name="MyTraceListener" type="MyLog.MyTraceListener, MyLog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" initializeData="d:\1.log" />
      </listeners>
    </trace>
    <switches>
      <!--这里能够设定监听级别,能够设置Error,Warning,Info或者留空-->
      <add name="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好用。

兄弟们啊,大家真的是来看文章的吗? 不是个人对手派来玩个人吧...............咳咳....鸡冻了.....

好吧,怪我没说清楚,我再集中这些问题,用一个栗子简单回答一下

public class MyTraceListener : TraceListener
{
    log4net _log = new log4net();

    public MyTraceListener(string filepath)
    {
        _log = new log4net();
        _log.FilePath = filepath;
    }

    public override void Write(string message)
    {
        _log.Info(message);
    }

    public override void WriteLine(string message)
    {
        _log.Info(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss    ") + message + Environment.NewLine);
    }
}

这样是否是就能够用log4net了啊,是否是就能够用其余log系统了啊 ,是否是就想写数据库就写数据库 想写文件就写文件, 写干啥就干啥了啊~~~~~~

兄弟们啊~~~~~~~

相关文章
相关标签/搜索