輕鬆背後的N+疲憊——系統日誌

相信不少coder都有這樣的癖好:「自戀」!!對本身編寫的code老是那麼的自信,自豪,Always believe it to be so perfect!!數據庫

不喜歡作單元測試(總以爲它就那樣了能出什麼錯?),不喜歡作日誌(總以爲他沒有什麼用!),不作日誌也就算了還把異常給「吃」了(只是爲了讓別人看不到那又黃又紅的像坨屎同樣的頁面),最終只能獨自一人默默的抓狂,累的像那什麼同樣,自做孽不可活!!編程

其實......餓......我就是這樣的啦(ˉ▽ˉ;)...數組

爲了讓生活的幸福美滿,爲了工做的輕鬆快樂,我決定虔誠的懺悔,痛定思痛,寫一個簡單日誌!(◎﹏◎)...安全

基於TraceSource的系統日誌編輯器

TraceSource官方給出的描述是這樣的:「提供一組方法和屬性,利用這些方法和屬性,應用程序能夠跟蹤代碼的執行並將跟蹤消息和它們的源關聯起來」。總以爲這描述跟系統日誌掛不上勾額,但事實它是用來作系統日誌的一個不錯的東西;ide

首先爲了迎合當今編程思想,先來建2個接口:單元測試

1.ILogger:用於實現日誌的寫入源測試

  /// <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:用於生產指定的日誌寫入源編碼

  /// <summary>
    /// 系統日誌工廠
    /// </summary>
    public interface ILoggerFactory
    {
        /// <summary>
        /// 建立一個系統日誌
        /// </summary>
        ILogger Create();
    }

爲了方便編碼和保持日誌的統一性,咱們再建一個日誌上下文spa

  /// <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實現:

    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基類進行重寫就能夠了。

下面是一個最簡單的自定義傾聽器:

    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工廠就能夠了,代碼以下:

    public class TraceSourceLoggerFactory
        : ILoggerFactory
    {
        public ILogger Create()
        {
            var logger = new TraceSourceLogger();
            return logger;
        }
    }

OK,代碼已經寫好了,那又的同窗就要問了傾聽器在哪裏設置呢?

這個問題很簡單,固然是在配置文件裏配置了;

<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傾聽器:

        [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();
            }
        }    

結果爲:

 

太晚了,該睡覺了哦!!

相關文章
相關標籤/搜索