• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

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

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

项目中要在操作数据库的异常处理中加入写Log日志,对于商业上有要求,写log时对其它操作尽可能影响小,不能因为加入log导致耗时太多。在写入日志时利用Queue来管理,写日志有一个专门的backgroud线程来处理,如果没有日志要写,这个线程处于wait状态,这就有了线程的异步处理。
 




    概述


    项目中要在操作数据库的异常处理中加入写Log日志,对于商业上有要求,写log时对其它操作尽可能影响小,不能因为加入log导致耗时太多。


    设计思想


    在写入日志时利用Queue来管理,写日志有一个专门的backgroud线程来处理,如果没有日志要写,这个线程处于wait状态,这就有了线程的异步处理。


    简单的实现方式

    1. //<summary>
    2. //Write Log
    3. //<summary>
    4. public static void WriteLog(string logFile, string msg)
    5. {
    6. try
    7. {
    8. System.IO.StreamWriter sw = System.IO.File.AppendText(
    9. logPath + LogFilePrefix +" "+ logFile + " " +
    10. DateTime.Now.ToString("yyyyMMdd") + ".Log"
    11. );
    12. sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss: ") + msg);
    13. sw.Close();
    14. }
    15. catch (Exception)
    16. {
    17. throw;
    18. }
    19. }

    我们的设计图



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


    代码设计

    1. /// <summary>
    2. /// Author: spring yang
    3. /// Create time:2012/3/30
    4. /// Log Help class
    5. /// </summary>
    6. /// <remarks>High performance log class</remarks>
    7. public class Log : IDisposable
    8. {
    9. //Log Message queue
    10. private static Queue<LogMessage> _logMessages;
    11. //log save directory
    12. private static string _logDirectory;
    13. //log write file state
    14. private static bool _state;
    15. //log type
    16. private static LogType _logType;
    17. //log life time sign
    18. private static DateTime _timeSign;
    19. //log file stream writer
    20. private static StreamWriter _writer;
    21. /// <summary>
    22. /// Wait enqueue wirte log message semaphore will release
    23. /// </summary>
    24. private Semaphore _semaphore;
    25. /// <summary>
    26. /// Single instance
    27. /// </summary>
    28. private static Log _log;
    29. /// <summary>
    30. /// Gets a single instance
    31. /// </summary>
    32. public static Log LogInstance
    33. {
    34. get { return _log ?? (_log = new Log()); }
    35. }
    36. private object _lockObjeck;
    37. /// <summary>
    38. /// Initialize Log instance
    39. /// </summary>
    40. private void Initialize()
    41. {
    42. if (_logMessages == null)
    43. { _state = true;
    44. string logPath = System.Configuration.ConfigurationManager.AppSettings["LogDirectory"];
    45. _logDirectory = string.IsNullOrEmpty(logPath) ? ".\\log\\" : logPath;
    46. if (!Directory.Exists(_logDirectory)) Directory.CreateDirectory(_logDirectory);
    47. _logType = LogType.Daily;
    48. _lockObjeck=new object();
    49. _semaphore = new Semaphore(0, int.MaxValue, Constants.LogSemaphoreName);
    50. _logMessages = new Queue<LogMessage>();
    51. var thread = new Thread(Work) {IsBackground = true};
    52. thread.Start();
    53. }
    54. }
    55. /// <summary>
    56. /// Create a log instance
    57. /// </summary>
    58. private Log()
    59. {
    60. Initialize();
    61. }
    62. /// <summary>
    63. /// Log save name type,default is daily
    64. /// </summary>
    65. public LogType LogType
    66. {
    67. get { return _logType; }
    68. set { _logType = value; }
    69. }
    70. /// <summary>
    71. /// Write Log file work method
    72. /// </summary>
    73. private void Work()
    74. {
    75. while (true)
    76. {
    77. //Determine log queue have record need wirte
    78. if (_logMessages.Count > 0)
    79. {
    80. FileWriteMessage();
    81. }
    82. else
    83. if (WaitLogMessage()) break;
    84. }
    85. }
    86. /// <summary>
    87. /// Write message to log file
    88. /// </summary>
    89. private void FileWriteMessage()
    90. {
    91. LogMessage logMessage=null;
    92. lock (_lockObjeck)
    93. {
    94. if(_logMessages.Count>0)
    95. logMessage = _logMessages.Dequeue();
    96. }
    97. if (logMessage != null)
    98. {
    99. FileWrite(logMessage);
    100. }
    101. }
    102. /// <summary>
    103. /// The thread wait a log message
    104. /// </summary>
    105. /// <returns>is close or not</returns>
    106. private bool WaitLogMessage()
    107. {
    108. //determine log life time is true or false
    109. if (_state)
    110. {
    111. WaitHandle.WaitAny(new WaitHandle[] { _semaphore }, -1, false);
    112. return false;
    113. }
    114. FileClose();
    115. return true;
    116. }
    117. /// <summary>
    118. /// Gets file name by log type
    119. /// </summary>
    120. /// <returns>log file name</returns>
    121. private string GetFilename()
    122. {
    123. DateTime now = DateTime.Now;
    124. string format = "";
    125. switch (_logType)
    126. {
    127. case LogType.Daily:
    128. _timeSign = new DateTime(now.Year, now.Month, now.Day);
    129. _timeSign = _timeSign.AddDays(1);
    130. format = "yyyyMMdd'.log'";
    131. break;
    132. case LogType.Weekly:
    133. _timeSign = new DateTime(now.Year, now.Month, now.Day);
    134. _timeSign = _timeSign.AddDays(7);
    135. format = "yyyyMMdd'.log'";
    136. break;
    137. case LogType.Monthly:
    138. _timeSign = new DateTime(now.Year, now.Month, 1);
    139. _timeSign = _timeSign.AddMonths(1);
    140. format = "yyyyMM'.log'";
    141. break;
    142. case LogType.Annually:
    143. _timeSign = new DateTime(now.Year, 1, 1);
    144. _timeSign = _timeSign.AddYears(1);
    145. format = "yyyy'.log'";
    146. break;
    147. }
    148. return now.ToString(format);
    149. }
    150. /// <summary>
    151. /// Write log file message
    152. /// </summary>
    153. /// <param name="msg"></param>
    154. private void FileWrite(LogMessage msg)
    155. {
    156. try
    157. {
    158. if (_writer == null)
    159. {
    160. FileOpen();
    161. }
    162. else
    163. {
    164. //determine the log file is time sign
    165. if (DateTime.Now >= _timeSign)
    166. {
    167. FileClose();
    168. FileOpen();
    169. }
    170. _writer.WriteLine(Constants.LogMessageTime+msg.Datetime);
    171. _writer.WriteLine(Constants.LogMessageType+msg.Type);
    172. _writer.WriteLine(Constants.LogMessageContent+msg.Text);
    173. _writer.Flush();
    174. }
    175. }
    176. catch (Exception e)
    177. {
    178. Console.Out.Write(e);
    179. }
    180. }
    181. /// <summary>
    182. /// Open log file write log message
    183. /// </summary>
    184. private void FileOpen()
    185. {
    186. _writer = new StreamWriter(Path.Combine(_logDirectory, GetFilename()), true, Encoding.UTF8);
    187. }
    188. /// <summary>
    189. /// Close log file
    190. /// </summary>
    191. private void FileClose()
    192. {
    193. if (_writer != null)
    194. {
    195. _writer.Flush();
    196. _writer.Close();
    197. _writer.Dispose();
    198. _writer = null;
    199. }
    200. }
    201. /// <summary>
    202. /// Enqueue a new log message and release a semaphore
    203. /// </summary>
    204. /// <param name="msg">Log message</param>
    205. public void Write(LogMessage msg)
    206. {
    207. if (msg != null)
    208. {
    209. lock (_lockObjeck)
    210. {
    211. _logMessages.Enqueue(msg);
    212. _semaphore.Release();
    213. }
    214. }
    215. }
    216. /// <summary>
    217. /// Write message by message content and type
    218. /// </summary>
    219. /// <param name="text">log message</param>
    220. /// <param name="type">message type</param>
    221. public void Write(string text, MessageType type)
    222. {
    223. Write(new LogMessage(text, type));
    224. }
    225. /// <summary>
    226. /// Write Message by datetime and message content and type
    227. /// </summary>
    228. /// <param name="dateTime">datetime</param>
    229. /// <param name="text">message content</param>
    230. /// <param name="type">message type</param>
    231. public void Write(DateTime dateTime, string text, MessageType type)
    232. {
    233. Write(new LogMessage(dateTime, text, type));
    234. }
    235. /// <summary>
    236. /// Write message ty exception and message type
    237. /// </summary>
    238. /// <param name="e">exception</param>
    239. /// <param name="type">message type</param>
    240. public void Write(Exception e, MessageType type)
    241. {
    242. Write(new LogMessage(e.Message, type));
    243. }
    244. #region IDisposable member
    245. /// <summary>
    246. /// Dispose log
    247. /// </summary>
    248. public void Dispose()
    249. {
    250. _state = false;
    251. }
    252. #endregion
    253. }
    254. /// <summary>
    255. /// Log Type
    256. /// </summary>
    257. /// <remarks>Create log by daily or weekly or monthly or annually</remarks>
    258. public enum LogType
    259. {
    260. /// <summary>
    261. /// Create log by daily
    262. /// </summary>
    263. Daily,
    264. /// <summary>
    265. /// Create log by weekly
    266. /// </summary>
    267. Weekly,
    268. /// <summary>
    269. /// Create log by monthly
    270. /// </summary>
    271. Monthly,
    272. /// <summary>
    273. /// Create log by annually
    274. /// </summary>
    275. Annually
    276. }
    277. /// <summary>
    278. /// Log Message Class
    279. /// </summary>
    280. public class LogMessage
    281. {
    282. /// <summary>
    283. /// Create Log message instance
    284. /// </summary>
    285. public LogMessage()
    286. : this("", MessageType.Unknown)
    287. {
    288. }
    289. /// <summary>
    290. /// Crete log message by message content and message type
    291. /// </summary>
    292. /// <param name="text">message content</param>
    293. /// <param name="messageType">message type</param>
    294. public LogMessage(string text, MessageType messageType)
    295. : this(DateTime.Now, text, messageType)
    296. {
    297. }
    298. /// <summary>
    299. /// Create log message by datetime and message content and message type
    300. /// </summary>
    301. /// <param name="dateTime">date time </param>
    302. /// <param name="text">message content</param>
    303. /// <param name="messageType">message type</param>
    304. public LogMessage(DateTime dateTime, string text, MessageType messageType)
    305. {
    306. Datetime = dateTime;
    307. Type = messageType;
    308. Text = text;
    309. }
    310. /// <summary>
    311. /// Gets or sets datetime
    312. /// </summary>
    313. public DateTime Datetime { get; set; }
    314. /// <summary>
    315. /// Gets or sets message content
    316. /// </summary>
    317. public string Text { get; set; }
    318. /// <summary>
    319. /// Gets or sets message type
    320. /// </summary>
    321. public MessageType Type { get; set; }
    322. /// <summary>
    323. /// Get Message to string
    324. /// </summary>
    325. /// <returns></returns>
    326. public new string ToString()
    327. {
    328. return Datetime.ToString(CultureInfo.InvariantCulture) + "\t" + Text + "\n";
    329. }
    330. }
    331. /// <summary>
    332. /// Log Message Type enum
    333. /// </summary>
    334. public enum MessageType
    335. {
    336. /// <summary>
    337. /// unknown type
    338. /// </summary>
    339. Unknown,
    340. /// <summary>
    341. /// information type
    342. /// </summary>
    343. Information,
    344. /// <summary>
    345. /// warning type
    346. /// </summary>
    347. Warning,
    348. /// <summary>
    349. /// error type
    350. /// </summary>
    351. Error,
    352. /// <summary>
    353. /// success type
    354. /// </summary>
    355. Success
    356. }

    Test Case:

    1. public static void TestLog()
    2. {
    3. Log.LogInstance.Write( "Test Message",MessageType.Information);
    4. Log.LogInstance.Write("one",MessageType.Error);
    5. Log.LogInstance.Write("two", MessageType.Success);
    6. Log.LogInstance.Write("three", MessageType.Warning);
    7. }

    运行结果:



    接受Mainz的建议,改了部分代码。


    鲜花

    握手

    雷人

    路过

    鸡蛋
    该文章已有0人参与评论

    请发表评论

    全部评论

    专题导读
    上一篇:
    C#与JAVA的不定参用法发布时间:2022-07-10
    下一篇:
    什么是.NET平台、什么是c#、什么是ASP.NET。发布时间:2022-07-10
    热门推荐
    阅读排行榜

    扫描微信二维码

    查看手机版网站

    随时了解更新最新资讯

    139-2527-9053

    在线客服(服务时间 9:00~18:00)

    在线QQ客服
    地址:深圳市南山区西丽大学城创智工业园
    电邮:jeky_zhao#qq.com
    移动电话:139-2527-9053

    Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap