• 系统日志


    轻松背后的N+疲惫——系统日志

    2014-04-16 00:41 by 螺丝钉想要螺丝帽, 324 阅读, 1 评论, 收藏编辑

    相信很多coder都有这样的癖好:“自恋”!!对自己编写的code总是那么的自信,自豪,Always believe it to be so perfect!!

    不喜欢做单元测试(总觉得它就那样了能出什么错?),不喜欢做日志(总觉得他没有什么用!),不做日志也就算了还把异常给“吃”了(只是为了让别人看不到那又黄又红的像坨屎一样的页面),最终只能独自一人默默的抓狂,累的像那什么一样,自作孽不可活!!

    其实......饿......我就是这样的啦(ˉ▽ˉ;)...

    为了让生活的幸福美满,为了工作的轻松快乐,我决定虔诚的忏悔,痛定思痛,写一个简单日志!(◎﹏◎)...

    基于TraceSource的系统日志

    TraceSource官方给出的描述是这样的:“提供一组方法和属性,利用这些方法和属性,应用程序可以跟踪代码的执行并将跟踪消息和它们的源关联起来”。总觉得这描述跟系统日志挂不上勾额,但事实它是用来做系统日志的一个不错的东西;

    首先为了迎合当今编程思想,先来建2个接口:

    1.ILogger:用于实现日志的写入源

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    /// <summary>
      /// 系统日志接口
      /// </summary>
      public interface ILogger
      {
          /// <summary>
          /// 系统崩溃错误日志
          /// </summary>
          /// <param name="message">错误信息</param>
          /// <param name="args">设置格式的对象的数组</param>
          void Fatal(string message, params object[] args);
     
          /// <summary>
          /// 系统崩溃错误日志
          /// </summary>
          /// <param name="message">错误信息</param>
          /// <param name="exception">异常对象</param>
          /// <param name="args">设置格式的对象的数组</param>
          void Fatal(string message, Exception exception, params object[] args);
     
          /// <summary>
          /// 系统消息日志
          /// </summary>
          /// <param name="message">要记录的信息</param>
          /// <param name="args">设置格式的对象的数组</param>
          void Infomation(string message, params object[] args);
     
          /// <summary>
          /// 系统警告日志
          /// </summary>
          /// <param name="message">警告信息</param>
          /// <param name="args">设置格式的对象的数组</param>
          void Warning(string message, params object[] args);
     
          /// <summary>
          /// 系统错误日志
          /// </summary>
          /// <param name="message">错误信息</param>
          /// <param name="args">设置格式的对象的数组</param>
          void Error(string message, params object[] args);
     
          /// <summary>
          /// 系统错误日志
          /// </summary>
          /// <param name="message">错误信息</param>
          /// <param name="exception">异常对象</param>
          /// <param name="args">设置格式的对象的数组</param>
          void Error(string message, Exception exception, params object[] args);
      }

    2.ILoggerFactory:用于生产指定的日志写入源

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /// <summary>
      /// 系统日志工厂
      /// </summary>
      public interface ILoggerFactory
      {
          /// <summary>
          /// 创建一个系统日志
          /// </summary>
          ILogger Create();
      }

    为了方便编码和保持日志的统一性,我们再建一个日志上下文

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    /// <summary>
      /// 系统日志上下文.
      /// </summary>
      public static class LoggerContext
      {
          static ILoggerFactory _currentLogFactory = null;
     
          /// <summary>
          /// 设置当然上下文使用的日志工厂
          /// <remarks>
          /// 该上下文始终使用一个日志工厂进行创建日志,建议在系统启动时进行设置,设置后将无法再进行设置
          /// </remarks>
          /// </summary>
          /// <param name="factory">日志工厂</param>
          public static void SetCurrent(ILoggerFactory factory)
          {
              if (_currentLogFactory != null)
                  throw new ArgumentException("该日志上下文已经设置使用的日志工厂,无法进行再次设置,如需使用其他日志工厂,请直接实例日志工厂进行操作。", "factory");
               
              _currentLogFactory = factory;
          }
     
          /// <summary>
          /// 创建一个日志
          /// </summary>
          public static ILogger CreateLog()
          {
              if (_currentLogFactory == null)
                  throw new NullReferenceException("该日志上下文尚未设置日志工厂,请使用SetCurrent方法进行设置。");
     
              return _currentLogFactory.Create();
          }
      }

    好的,现在我们进入正题,使用TraceSource进行日志记录,不要介意哈,进入正题前总要有些前奏, 目的你懂得o(^▽^)o.....

    TraceSource 位于命名空间System.Diagnostics下,该命名空间在System.dll中,所以无需添加引用,比较方便。

    下面是基于TraceSource的ILogger实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    public sealed class TraceSourceLogger
        :ILogger
    {
        private const string EXCEPTION_FORMAT = "{0} 捕获异常信息:{1}";
     
        TraceSource _source;
     
        public TraceSourceLogger()
        {
            _source = new TraceSource("Bulrush");
        }
     
        public void Fatal(string message, params object[] args)
        {
            if (String.IsNullOrWhiteSpace(message))
                return;
     
            string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
            Trace(TraceEventType.Critical, messageToTrace);
        }
     
        public void Fatal(string message, Exception exception, params object[] args)
        {
            if (String.IsNullOrWhiteSpace(message) || exception == null)
                return;
     
            string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
            string exceptionString = exception.ToString();
            Trace(TraceEventType.Critical, String.Format(CultureInfo.InvariantCulture, EXCEPTION_FORMAT, messageToTrace, exceptionString));
        }
     
        public void Infomation(string message, params object[] args)
        {
            if (String.IsNullOrWhiteSpace(message))
                return;
     
            string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
            Trace(TraceEventType.Information, messageToTrace);
        }
     
        public void Warning(string message, params object[] args)
        {
            if (String.IsNullOrWhiteSpace(message))
                return;
     
            string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
            Trace(TraceEventType.Warning, messageToTrace);
        }
     
        public void Error(string message, params object[] args)
        {
            if (String.IsNullOrWhiteSpace(message))
                return;
     
            string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
            Trace(TraceEventType.Error, messageToTrace);
        }
     
        public void Error(string message, Exception exception, params object[] args)
        {
            if (String.IsNullOrWhiteSpace(message) || exception == null)
                return;
     
            string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
            string exceptionString = exception.ToString();
            Trace(TraceEventType.Error, String.Format(CultureInfo.InvariantCulture, EXCEPTION_FORMAT, messageToTrace, exceptionString));
        }
     
        void Trace(TraceEventType eventType, string message)
        {
            if (_source != null)
            {
                try
                {
                    _source.TraceEvent(eventType, (int)eventType, message);
                }
                catch (SecurityException)
                {
                    //这里处理写入是出现的安全问题,如文件没有写入权限。
                }
            }
        }
    }

    这个实现比较简单,但是这里有一个很好的哦,那是什么呢?嘻嘻就TraceSource里的Listeners倾听器,微软给我们提供了几个常用的倾听器,我觉得基本已经够用了,

    1.DefaultTraceListener:默认使用这个,这个倾听器会输出在调试器的输出窗口。

    2.EventLogTraceListener: 这个是操作系统日志的倾听器,会把日志记录在操作系统的事件里,我还是比较喜欢这个,毕竟比较完善,安全性也比较好。

    3.TextWriterTraceListener:这个是文本编辑器的倾听器,简单点就是以文件流的形式进行记录,当然了文件路径是自己定义的,这个也比较常用。

    4.XmlWriterTraceListener:这个Xml文件的倾听器,用法和TextWriterTraceListener差不多,只是使用Xml流格式进行记录。

    等等,当然还有几个倾听器,这里就不一一列出了,有兴趣的可以查看MSDN的System.Diagnostics

    如果你想拓展也可以,如记录在数据库,或者使用Log4net等等,只要继承TraceListener基类进行重写就可以了。

    下面是一个最简单的自定义倾听器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class CustomeTraceListener
        : TraceListener
    {
        public override void Write(string message)
        {
            File.AppendAllText(@"d:log.txt", message);
        }
     
        public override void WriteLine(string message)
        {
            File.AppendAllText(@"d:log.txt", message+ Environment.NewLine);
        }
    }

    下面我们在写一个TraceSourceLogger工厂就可以了,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class TraceSourceLoggerFactory
        : ILoggerFactory
    {
        public ILogger Create()
        {
            var logger = new TraceSourceLogger();
            return logger;
        }
    }

    OK,代码已经写好了,那又的同学就要问了倾听器在哪里设置呢?

    这个问题很简单,当然是在配置文件里配置了;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <configuration>
      <system.diagnostics>
        <sources>
          <source name="Bulrush" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch">
            <listeners>
              <clear/>
              <add name="eventLog"></add>
            </listeners>
          </source>
        </sources>
        <switches>
          <!--这里设置TraceSource的写入开关,默认为Off关闭,不进行写入,具体值可以查看SourceLevels枚举-->
          <add name="SourceSwitch" value="All"/>
        </switches>
        <sharedListeners>
          <!--
            这里使用操作系统的事件倾听器,initializeData属性是事件源,false为默认。
            不同的倾听器initalizeData有不同的意义,如TextWriterTraceListnener倾听器,可以设置为“d:log.txt”,意思就是保存的路径。
          -->
          <add name="eventLog"
            type="System.Diagnostics.EventLogTraceListener"
            initializeData="false"/>
        </sharedListeners>
      </system.diagnostics>
    </configuration>

    到这里就结束了,下面做个简单的测试,是使用EventLogTraceListener倾听器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    [ClassInitialize()]
    public static void ClassInitialze(TestContext context)
    {
        LoggerContext.SetCurrent(new TraceSourceLoggerFactory());
    }
     
    [TestMethod]
    public void TestTraceSourceLogger()
    {
        //LoggerContext.CreateLog().Error("错误日志");
     
        var logger = LoggerContext.CreateLog();
     
        try
        {
            logger.Error("错误日志");
            logger.Fatal("系统崩溃日志");
            logger.Infomation("普通消息日志");
            logger.Warning("非关键性,警告日志");
        }
        catch
        {
            Assert.Fail();
        }
    }   

    结果为:

    太晚了,该睡觉了哦!!

     
     
  • 相关阅读:
    Luogu P2016 战略游戏(树形DP)
    Luogu P2486 染色(树链剖分+线段树)
    Luogu P3178 树上操作(树链剖分+线段树)
    Luogu P2590 树的统计(树链剖分+线段树)
    Luogu P2146 软件包管理器(树链剖分+线段树)
    获得spring
    网卡绑定多个ip
    描述01-配置文件咋整
    进程查看
    端口查看,进程杀死
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3667884.html
Copyright © 2020-2023  润新知