C#開發高效能Log Help 類設計開發

來源:互聯網
上載者:User

概述

項目中要在操作資料庫的異常處理中加入寫Log日誌,對於商業上有要求,寫log時對其它操作儘可能影響小,不能因為加入log導致耗時太多.

設計思想

在寫入日誌時利用Queue來管理,寫日誌有一個專門的backgroud線程來處理,如果沒有日誌要寫,這個線程處於wait狀態,這就有了線程的非同步處理.

 

簡單的實現方式

        //<summary>        //Write Log        //<summary>        public static void WriteLog(string logFile, string msg)        {            try            {                System.IO.StreamWriter sw = System.IO.File.AppendText(                        logPath + LogFilePrefix +" "+ logFile + " " +                        DateTime.Now.ToString("yyyyMMdd") + ".Log"                    );                sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:  ") + msg);                sw.Close();            }            catch (Exception)            {                                throw;            }        }

我們的設計圖

而後我們在AddLogMessage時semaphore.Release()就能喚醒wait中的log 線程.

代碼設計

    /// <summary>    /// Author: spring yang    /// Create time:2012/3/30     /// Log Help class    /// </summary>    /// <remarks>High performance log class</remarks>    public class Log : IDisposable    {        //Log Message queue        private static Queue<LogMessage> _logMessages;        //log save directory        private static string _logDirectory;        //log write file state        private static bool _state;        //log type        private static LogType _logType;        //log life time sign        private static DateTime _timeSign;        //log file stream writer        private static StreamWriter _writer;        /// <summary>        /// Wait enqueue wirte log message semaphore will release        /// </summary>        private Semaphore _semaphore;        /// <summary>        /// Single instance        /// </summary>        private static Log _log;        /// <summary>        /// Gets a single instance        /// </summary>        public static Log LogInstance        {            get { return _log ?? (_log = new Log()); }        }        private object _lockObjeck;        /// <summary>        /// Initialize Log instance        /// </summary>        private void Initialize()        {            if (_logMessages == null)            {   _state = true;                string logPath = System.Configuration.ConfigurationManager.AppSettings["LogDirectory"];                _logDirectory = string.IsNullOrEmpty(logPath) ? ".\\log\\" : logPath;                if (!Directory.Exists(_logDirectory)) Directory.CreateDirectory(_logDirectory);                _logType = LogType.Daily;                _lockObjeck=new object();                _semaphore = new Semaphore(0, int.MaxValue, Constants.LogSemaphoreName);                _logMessages = new Queue<LogMessage>();                var thread = new Thread(Work) {IsBackground = true};                thread.Start();            }        }         /// <summary>        /// Create a log instance        /// </summary>        private Log()        {            Initialize();        }        /// <summary>        /// Log save name type,default is daily        /// </summary>        public LogType LogType        {            get { return _logType; }            set { _logType = value; }        }        /// <summary>        /// Write Log file  work method        /// </summary>        private void Work()        {            while (true)            {                //Determine log queue have record need wirte                if (_logMessages.Count > 0)                {                    FileWriteMessage();                }                else                    if (WaitLogMessage()) break;            }        }        /// <summary>        /// Write message to log file        /// </summary>        private void FileWriteMessage()        {            LogMessage logMessage=null;            lock (_lockObjeck)            {                if(_logMessages.Count>0)                logMessage = _logMessages.Dequeue();            }            if (logMessage != null)            {                FileWrite(logMessage);            }        }        /// <summary>        /// The thread wait a log message        /// </summary>        /// <returns>is close or not</returns>        private bool WaitLogMessage()        {            //determine log life time is true or false            if (_state)            {                WaitHandle.WaitAny(new WaitHandle[] { _semaphore }, -1, false);                return false;            }            FileClose();            return true;        }        /// <summary>        /// Gets file name by log type        /// </summary>        /// <returns>log file name</returns>        private string GetFilename()        {            DateTime now = DateTime.Now;            string format = "";            switch (_logType)            {                case LogType.Daily:                    _timeSign = new DateTime(now.Year, now.Month, now.Day);                    _timeSign = _timeSign.AddDays(1);                    format = "yyyyMMdd'.log'";                    break;                case LogType.Weekly:                    _timeSign = new DateTime(now.Year, now.Month, now.Day);                    _timeSign = _timeSign.AddDays(7);                    format = "yyyyMMdd'.log'";                    break;                case LogType.Monthly:                    _timeSign = new DateTime(now.Year, now.Month, 1);                    _timeSign = _timeSign.AddMonths(1);                    format = "yyyyMM'.log'";                    break;                case LogType.Annually:                    _timeSign = new DateTime(now.Year, 1, 1);                    _timeSign = _timeSign.AddYears(1);                    format = "yyyy'.log'";                    break;            }            return now.ToString(format);        }        /// <summary>        /// Write log file message        /// </summary>        /// <param name="msg"></param>        private void FileWrite(LogMessage msg)        {            try            {                if (_writer == null)                {                    FileOpen();                }                else                {                    //determine the log file is time sign                    if (DateTime.Now >= _timeSign)                    {                        FileClose();                        FileOpen();                    }                    _writer.WriteLine(Constants.LogMessageTime+msg.Datetime);                    _writer.WriteLine(Constants.LogMessageType+msg.Type);                    _writer.WriteLine(Constants.LogMessageContent+msg.Text);                    _writer.Flush();                }            }            catch (Exception e)            {                Console.Out.Write(e);            }        }        /// <summary>        /// Open log file write log message        /// </summary>        private void FileOpen()        {            _writer = new StreamWriter(Path.Combine(_logDirectory, GetFilename()), true, Encoding.UTF8);        }        /// <summary>        /// Close log file         /// </summary>        private void FileClose()        {            if (_writer != null)            {                _writer.Flush();                _writer.Close();                _writer.Dispose();                _writer = null;            }        }        /// <summary>        /// Enqueue a new log message and release a semaphore        /// </summary>        /// <param name="msg">Log message</param>        public void Write(LogMessage msg)        {            if (msg != null)            {                lock (_lockObjeck)                {                    _logMessages.Enqueue(msg);                    _semaphore.Release();                }            }        }        /// <summary>        /// Write message by message content and type        /// </summary>        /// <param name="text">log message</param>        /// <param name="type">message type</param>        public void Write(string text, MessageType type)        {            Write(new LogMessage(text, type));        }        /// <summary>        /// Write Message by datetime and message content and type        /// </summary>        /// <param name="dateTime">datetime</param>        /// <param name="text">message content</param>        /// <param name="type">message type</param>        public void Write(DateTime dateTime, string text, MessageType type)        {            Write(new LogMessage(dateTime, text, type));        }        /// <summary>        /// Write message ty exception and message type         /// </summary>        /// <param name="e">exception</param>        /// <param name="type">message type</param>        public void Write(Exception e, MessageType type)        {            Write(new LogMessage(e.Message, type));        }        #region IDisposable member        /// <summary>        /// Dispose log        /// </summary>        public void Dispose()        {            _state = false;        }        #endregion    }    /// <summary>    /// Log Type    /// </summary>    /// <remarks>Create log by daily or weekly or monthly or annually</remarks>    public enum LogType    {        /// <summary>        /// Create log by daily        /// </summary>        Daily,        /// <summary>        /// Create log by weekly        /// </summary>        Weekly,        /// <summary>        /// Create log by monthly        /// </summary>        Monthly,        /// <summary>        /// Create log by annually        /// </summary>        Annually    }    /// <summary>    /// Log Message Class    /// </summary>    public class LogMessage    {        /// <summary>        /// Create Log message instance        /// </summary>        public LogMessage()            : this("", MessageType.Unknown)        {        }        /// <summary>        /// Crete log message by message content and message type        /// </summary>        /// <param name="text">message content</param>        /// <param name="messageType">message type</param>        public LogMessage(string text, MessageType messageType)            : this(DateTime.Now, text, messageType)        {        }        /// <summary>        /// Create log message by datetime and message content and message type        /// </summary>        /// <param name="dateTime">date time </param>        /// <param name="text">message content</param>        /// <param name="messageType">message type</param>        public LogMessage(DateTime dateTime, string text, MessageType messageType)        {            Datetime = dateTime;            Type = messageType;            Text = text;        }        /// <summary>        /// Gets or sets datetime        /// </summary>        public DateTime Datetime { get; set; }        /// <summary>        /// Gets or sets message content        /// </summary>        public string Text { get; set; }        /// <summary>        /// Gets or sets message type        /// </summary>        public MessageType Type { get; set; }        /// <summary>        /// Get Message to string        /// </summary>        /// <returns></returns>        public new string ToString()        {            return Datetime.ToString(CultureInfo.InvariantCulture) + "\t" + Text + "\n";        }    }    /// <summary>    /// Log Message Type enum    /// </summary>    public enum MessageType    {        /// <summary>        /// unknown type         /// </summary>        Unknown,        /// <summary>        /// information type        /// </summary>        Information,        /// <summary>        /// warning type        /// </summary>        Warning,        /// <summary>        /// error type        /// </summary>        Error,        /// <summary>        /// success type        /// </summary>        Success    }

 

 

Test Case:

        public static void TestLog()        {            Log.LogInstance.Write(  "Test Message",MessageType.Information);            Log.LogInstance.Write("one",MessageType.Error);            Log.LogInstance.Write("two", MessageType.Success);            Log.LogInstance.Write("three", MessageType.Warning);        }

 

 

運行結果:

 

接受Mainz的建議,改了部分代碼,

Mainz:http://www.cnblogs.com/Mainz/

 

歡迎各位參與討論,如果覺得對你有協助,請點擊    推薦下,萬分謝謝.

作者:spring yang

出處:http://www.cnblogs.com/springyangwc/

本文著作權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則保留追究法律責任的權利。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.