• 转载——利用C#自带组件强壮程序日志


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

     

    在项目正式上线后,如果出现错误,异常,崩溃等情况

    我们往往第一想到的事就是查看日志

    所以日志对于一个系统的维护是非常重要的

    声明

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

    具体实现可以自由发挥~~~~

    贯穿所有的日志系统

    日志系统,往往是贯穿一个程序的所有代码的;

    试想一下,如果你的日志完全是由第三方组件提供的;

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

    也许你会说自己可以2次封装,那么依然需要所有项目都引用你的这个封装后的log项目

    另一方面

    一些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文件的位置

     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系统了啊 ,是不是就想写数据库就写数据库 想写文件就写文件, 写干啥就干啥了啊~~~~~~

    兄弟们啊~~~~~~~

    我写的文章,除了纯代码,其他的都是想表达一种思想,一种解决方案.希望各位看官不要局限于文章中的现成的代码,要多关注整个文章的主题思路,谢谢!
    我发布的代码,没有任何版权,遵守WTFPL协议(如有引用,请遵守被引用代码的协议)
     
  • 相关阅读:
    案例53-crm练习修改客户功能实现
    测开之路一百二十五:flask之urlencode参数传递和解析
    测开之路一百二十四:flask之MVC响应过程
    测开之路一百二十三:快速搭建python虚拟环境
    测开之路一百二十二:高级组件之警告框
    测开之路一百二十一:常用组件之助手类
    测开之路一百一二十:常用组件之进度条
    测开之路一百一十九:常用组件之标签和徽章
    测开之路一百一十八:常用组件之面包屑导航和分页导航
    测开之路一百一十七:常用组件之导航栏
  • 原文地址:https://www.cnblogs.com/ShaYeBlog/p/3642736.html
Copyright © 2020-2023  润新知