工作快三年,入園子差不多有三年了,每天茶余飯后,輕敲鼠標偷偷的打開博客園,肆無忌憚的品嘗着各種干貨,慢慢的從新人變成了老司機,從軟香蕉變成了硬橡膠,一篇篇優質的博客讓我陶醉其中無法自拔,俗話說三年之痛,七年之癢,在這個我認為不痛不癢的時候,是時候奉獻一下自己的積累,開始准備一個簡單框架系列主要包括----日志,基於HTTP傳輸,Windows內部消息通訊,面向對象容器包裝等,目前只總結了這么多,我們就廢話少數開始第一個框架。
首先做一下簡單的需求分析,常見的日志功能需求:
1. 按日期類型記錄(天、周、月、年)
2. 按文件大小記錄(行數或字節)
3. 按日志等級記錄(Unknow、Error、Warning、Info、Debug)
4. 定時清理日志(依據實際大小制定具體天數)
5. 為方便開發調試,針對服務類型開發,同時顯示在Console界面(繼承TraceListener)
6. 支持多線程同時日志記錄
框架准備:輕量級日志框架,我給它起了個名字,就叫做LogLight
枚舉類型:
1 public enum EnumLogType 2 { 3 Daily, 4 Weekly, 5 Monthly, 6 Annually 7 } 8 9 public enum EunmMsgType 10 { 11 Unknown, 12 Error, 13 Warning, 14 Info, 15 Debug 16 }
每行內容對象,重寫ToString方法,重載構造函數
1 public class LogMsg 2 { 3 public LogMsg(string text, string category) 4 { 5 Category = category; 6 DateTime = DateTime.Now; 7 Text = text; 8 Type = EunmMsgType.Unknown; 9 } 10 11 public LogMsg(string text, EunmMsgType type) 12 { 13 Category = ""; 14 DateTime = DateTime.Now; 15 Text = text; 16 Type = type; 17 } 18 19 public LogMsg(DateTime dt, string text, EunmMsgType type) 20 { 21 Category = ""; 22 DateTime = dt; 23 Text = text; 24 Type = type; 25 } 26 27 public string Text { get; set; } 28 29 public DateTime DateTime { get; set; } 30 31 public string Category { get; set; } 32 33 public EunmMsgType Type { get; set; } 34 35 public override string ToString() 36 { 37 var bulider = new StringBuilder(); 38 bulider.Append(DateTime.ToString("yyyy-MM-dd HH:mm:ss:ff")); 39 bulider.Append(Category); 40 bulider.Append(" "); 41 bulider.Append(Text); 42 return bulider.ToString(); 43 } 44 }
程序入口
1 public class LogLightConsole 2 { 3 public static EunmMsgType LogLevel = EunmMsgType.Debug; 4 5 public static void WriteLog(string sInfo, EunmMsgType type) 6 { 7 if (type <= LogLevel) 8 { 9 Trace.WriteLine(new LogMsg(sInfo, type)); 10 } 11 } 12 }
根據設定條件創建文件,定義文件行條數,定期刪除文件,支持多線程操作,防止同時訪問隊列造成的死鎖
1 public class Logger : IDisposable 2 { 3 private static readonly int _keepLogDayCount = 15; 4 5 private static int _lineCount; 6 7 private static readonly int _lineMaxCount = 0x3d090;//2500 8 9 private static Queue<LogMsg> _msgs; 10 11 private static string _path; 12 13 private static bool _state; 14 15 private static DateTime _timeSign; 16 17 private static EnumLogType _type; 18 19 private static StreamWriter _writer; 20 21 private readonly bool _bOutputCount = false; 22 23 private readonly string _format = "yyyy-MM-dd HH:mm:ss:fff"; 24 25 private long _count; 26 27 public Logger(string path, EnumLogType type) 28 { 29 if (_msgs == null) 30 { 31 _state = true; 32 _path = path; 33 _type = type; 34 _msgs = new Queue<LogMsg>(); 35 var thread = new Thread(Work) {IsBackground = true}; 36 thread.Start(); 37 } 38 } 39 40 public void Dispose() 41 { 42 _state = false; 43 } 44 45 private void FileClose() 46 { 47 if (_writer == null) return; 48 _writer.Flush(); 49 _writer.Close(); 50 _writer.Dispose(); 51 _writer = null; 52 } 53 54 private void FileOpen() 55 { 56 _lineCount = 0; 57 _writer = new StreamWriter(GetFileName(), true, Encoding.UTF8); 58 } 59 60 private void FileWrite(LogMsg msg) 61 { 62 try 63 { 64 if (_writer == null) 65 { 66 FileOpen(); 67 } 68 69 if (_writer != null) 70 { 71 if ((DateTime.Now >= _timeSign) || _lineCount > _lineMaxCount) 72 { 73 FileClose(); 74 try 75 { 76 var fileSn = 0; 77 for (var str = _path + GetFilenameBeforeDays(0, _keepLogDayCount); 78 File.Exists(str); 79 str = _path + GetFilenameBeforeDays(fileSn, _keepLogDayCount)) 80 { 81 File.Delete(str); 82 fileSn++; 83 } 84 } 85 catch (Exception exception) 86 { 87 Console.Out.Write(exception); 88 } 89 FileOpen(); 90 } 91 _lineCount++; 92 _writer.Write(msg.DateTime.ToString(_format)); 93 _writer.Write(' '); 94 if (msg.Type == EunmMsgType.Unknown) 95 { 96 _writer.Write(msg.Category); 97 } 98 else 99 { 100 _writer.Write(msg.Type); 101 } 102 _writer.Write(' '); 103 _writer.WriteLine(msg.Text); 104 _writer.Flush(); 105 } 106 } 107 catch (Exception exception) 108 { 109 Console.Out.Write(exception); 110 } 111 } 112 113 private string GetFileName() 114 { 115 var num = 0; 116 var now = DateTime.Now; 117 var format = ""; 118 119 Label_OO0E: 120 switch (_type) 121 { 122 case EnumLogType.Daily: 123 _timeSign = new DateTime(now.Year, now.Month, now.Day); 124 _timeSign = _timeSign.AddDays(1.0); 125 format = "yyyyMMdd"; 126 break; 127 case EnumLogType.Weekly: 128 _timeSign = new DateTime(now.Year, now.Month, now.Day); 129 _timeSign = _timeSign.AddDays(7.0); 130 format = "yyyyMMdd"; 131 break; 132 case EnumLogType.Monthly: 133 _timeSign = new DateTime(now.Year, now.Month, 1); 134 _timeSign = _timeSign.AddMonths(1); 135 format = "yyyyMM"; 136 break; 137 case EnumLogType.Annually: 138 _timeSign = new DateTime(now.Year, 1, 1); 139 _timeSign = _timeSign.AddYears(1); 140 format = "yyyy"; 141 break; 142 } 143 if (File.Exists(_path + now.ToString(format) + string.Format("-{0}.log", num))) 144 { 145 num++; 146 goto Label_OO0E; 147 } 148 return _path + now.ToString(format) + string.Format("-{0}.log", num); 149 } 150 151 private string GetFilenameBeforeDays(int fileSn, int dayCount) 152 { 153 var time = DateTime.Now - TimeSpan.FromDays(dayCount); 154 var format = ""; 155 switch (_type) 156 { 157 case EnumLogType.Daily: 158 format = "yyyyMMdd"; 159 break; 160 case EnumLogType.Weekly: 161 format = "yyyyMMdd"; 162 break; 163 case EnumLogType.Monthly: 164 format = "yyyyMM"; 165 break; 166 case EnumLogType.Annually: 167 format = "yyyy"; 168 break; 169 } 170 return time.ToString(format) + string.Format("-{0}.log", fileSn); 171 } 172 173 private void Work() 174 { 175 Label_0000: 176 while (_msgs.Count > 0) 177 { 178 LogMsg msg = null; 179 lock (_msgs) 180 { 181 if (_msgs.Count > 0) 182 { 183 msg = _msgs.Dequeue(); 184 _count -= 1L; 185 } 186 187 if (msg != null) 188 { 189 if (_bOutputCount) 190 { 191 msg.Text = msg.Text + string.Format("{0}", _count); 192 } 193 FileWrite(msg); 194 } 195 } 196 } 197 198 if (_state) 199 { 200 Thread.Sleep(1); 201 goto Label_0000; 202 } 203 FileClose(); 204 } 205 206 public void Write(LogMsg msg) 207 { 208 if (msg != null) 209 { 210 lock (_msgs) 211 { 212 _count += 1L; 213 _msgs.Enqueue(msg); 214 } 215 } 216 } 217 218 public void Write(string text, EunmMsgType type) 219 { 220 Write(new LogMsg(text, type)); 221 } 222 223 public void Write(string text, string category) 224 { 225 Write(new LogMsg(text, category)); 226 } 227 }
初始化框架類,調用TraceLinster監聽日志輸入,重寫WriteLine方法(非常重要)--->調用logger寫方法
public class LogConsole : TraceListener { public static readonly LogConsole InstanceLogConsole = new LogConsole(); private Logger _logger; public void Init(bool UserDebugOutput, bool UseCrForWriteLine, string sPath) { if (!Directory.Exists(sPath)) { Directory.CreateDirectory(sPath); } _logger = new Logger(sPath, EnumLogType.Daily); if (UserDebugOutput) { Debug.Listeners.Add(this); } else { Trace.Listeners.Add(this); } } protected override void Dispose(bool disposing) { if (disposing && (_logger != null)) { _logger.Dispose(); _logger = null; } } public override void WriteLine(object o) { var logMsg = o as LogMsg; if (logMsg != null) { var msg = logMsg; if (_logger != null) { _logger.Write(msg); } Console.WriteLine(msg.ToString()); } } public override void WriteLine(string message, string category) { if (_logger != null) { _logger.Write(message, category); } } public override void WriteLine(string message) { if (_logger != null) { _logger.Write(message, EunmMsgType.Info); } } public override void Write(string message) { if (_logger != null) { _logger.Write(message, EunmMsgType.Info); } } }
測試代碼:
class Program { static void Main(string[] args) { var path = AppDomain.CurrentDomain.BaseDirectory + "Log\\"; LogConsole.InstanceLogConsole.Init(true,true,path); Test test = new Test(); test.Work(); Console.ReadLine(); } } public class Test { public void Work() { for (int i = 0; i < 100; i++) { ThreadPool.QueueUserWorkItem(Go, i.ToString()); } } private void Go(object state) { LogLightConsole.WriteLog(state.ToString(), EunmMsgType.Info); } }
希望可以幫到大家,如果你喜歡或者感覺還可以點個贊給作者點動力,如果轉載請注明連接。http://www.cnblogs.com/dongqinnanren/p/5964686.html