您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關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; } }
我們的設計圖
而后我們在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的建議,改了部分代碼。
以上就是C#開發高性能Log Help類設計開發的示例分析,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。