概述
项目中要在操作数据库的异常处理中加入写Log日志,对于商业上有要求,写log时对其它操作尽可能影响小,不能因为加入log导致耗时太多。
设计思想
在写入日志时利用Queue来管理,写日志有一个专门的backgroud线程来处理,如果没有日志要写,这个线程处于wait状态,这就有了线程的异步处理。
简单的实现方式
- //
- //Write Log
- //
- 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 线程。
代码设计
- ///
- /// Author: spring yang
- /// Create time:2012/3/30
- /// Log Help class
- ///
- ///
High performance log class - public class Log : IDisposable
- {
- //Log Message queue
- private static Queue
_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;
- ///
- /// Wait enqueue wirte log message semaphore will release
- ///
- private Semaphore _semaphore;
- ///
- /// Single instance
- ///
- private static Log _log;
- ///
- /// Gets a single instance
- ///
- public static Log LogInstance
- {
- get { return _log ?? (_log = new Log()); }
- }
- private object _lockObjeck;
- ///
- /// Initialize Log instance
- ///
- 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
(); - var thread = new Thread(Work) {IsBackground = true};
- thread.Start();
- }
- }
- ///
- /// Create a log instance
- ///
- private Log()
- {
- Initialize();
- }
- ///
- /// Log save name type,default is daily
- ///
- public LogType LogType
- {
- get { return _logType; }
- set { _logType = value; }
- }
- ///
- /// Write Log file work method
- ///
- private void Work()
- {
- while (true)
- {
- //Determine log queue have record need wirte
- if (_logMessages.Count > 0)
- {
- FileWriteMessage();
- }
- else
- if (WaitLogMessage()) break;
- }
- }
- ///
- /// Write message to log file
- ///
- private void FileWriteMessage()
- {
- LogMessage logMessage=null;
- lock (_lockObjeck)
- {
- if(_logMessages.Count>0)
- logMessage = _logMessages.Dequeue();
- }
- if (logMessage != null)
- {
- FileWrite(logMessage);
- }
- }
- ///
- /// The thread wait a log message
- ///
- ///
is close or not - 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;
- }
- ///
- /// Gets file name by log type
- ///
- ///
log file name - 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);
- }
- ///
- /// Write log file message
- ///
- ///
- 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);
- }
- }
- ///
- /// Open log file write log message
- ///
- private void FileOpen()
- {
- _writer = new StreamWriter(Path.Combine(_logDirectory, GetFilename()), true, Encoding.UTF8);
- }
- ///
- /// Close log file
- ///
- private void FileClose()
- {
- if (_writer != null)
- {
- _writer.Flush();
- _writer.Close();
- _writer.Dispose();
- _writer = null;
- }
- }
- ///
- /// Enqueue a new log message and release a semaphore
- ///
- /// Log message
- public void Write(LogMessage msg)
- {
- if (msg != null)
- {
- lock (_lockObjeck)
- {
- _logMessages.Enqueue(msg);
- _semaphore.Release();
- }
- }
- }
- ///
- /// Write message by message content and type
- ///
- /// log message
- /// message type
- public void Write(string text, MessageType type)
- {
- Write(new LogMessage(text, type));
- }
- ///
- /// Write Message by datetime and message content and type
- ///
- /// datetime
- /// message content
- /// message type
- public void Write(DateTime dateTime, string text, MessageType type)
- {
- Write(new LogMessage(dateTime, text, type));
- }
- ///
- /// Write message ty exception and message type
- ///
- /// exception
- /// message type
- public void Write(Exception e, MessageType type)
- {
- Write(new LogMessage(e.Message, type));
- }
- #region IDisposable member
- ///
- /// Dispose log
- ///
- public void Dispose()
- {
- _state = false;
- }
- #endregion
- }
- ///
- /// Log Type
- ///
- ///
Create log by daily or weekly or monthly or annually - public enum LogType
- {
- ///
- /// Create log by daily
- ///
- Daily,
- ///
- /// Create log by weekly
- ///
- Weekly,
- ///
- /// Create log by monthly
- ///
- Monthly,
- ///
- /// Create log by annually
- ///
- Annually
- }
- ///
- /// Log Message Class
- ///
- public class LogMessage
- {
- ///
- /// Create Log message instance
- ///
- public LogMessage()
- : this("", MessageType.Unknown)
- {
- }
- ///
- /// Crete log message by message content and message type
- ///
- /// message content
- /// message type
- public LogMessage(string text, MessageType messageType)
- : this(DateTime.Now, text, messageType)
- {
- }
- ///
- /// Create log message by datetime and message content and message type
- ///
- /// date time
- /// message content
- /// message type
- public LogMessage(DateTime dateTime, string text, MessageType messageType)
- {
- Datetime = dateTime;
- Type = messageType;
- Text = text;
- }
- ///
- /// Gets or sets datetime
- ///
- public DateTime Datetime { get; set; }
- ///
- /// Gets or sets message content
- ///
- public string Text { get; set; }
- ///
- /// Gets or sets message type
- ///
- public MessageType Type { get; set; }
- ///
- /// Get Message to string
- ///
- ///
- public new string ToString()
- {
- return Datetime.ToString(CultureInfo.InvariantCulture) + "\t" + Text + "\n";
- }
- }
- ///
- /// Log Message Type enum
- ///
- public enum MessageType
- {
- ///
- /// unknown type
- ///
- Unknown,
- ///
- /// information type
- ///
- Information,
- ///
- /// warning type
- ///
- Warning,
- ///
- /// error type
- ///
- Error,
- ///
- /// success type
- ///
- 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/
当前名称:C#开发高性能LogHelp类设计开发
URL标题:http://www.shufengxianlan.com/qtweb/news49/433849.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联