2012年3月31日星期六

C#开发高性能Log Help 类设计开发

C#开发高性能Log Help 类设计开发



概述

项目中要在操作数据库的异常处理中加入写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;            }        }

我们的设计图

image

而后我们在AddLogMessage时semaphore.Release()就能唤醒wait中的log 线程.

代码设计

    /// <summary>    /// 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()); }        }        /// <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;                _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;            lock (_logMessages)            {                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(_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 (_logMessages)                {                    _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);        }

 

 

运行结果:

image

欢迎各位参与讨论,如果觉得对你有帮助,请点击image    推荐下,万分谢谢.

作者:spring yang

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

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。



TAG: