自己動手豐衣足食 ,C#框架系列----- 日志框架


工作快三年,入園子差不多有三年了,每天茶余飯后,輕敲鼠標偷偷的打開博客園,肆無忌憚的品嘗着各種干貨,慢慢的從新人變成了老司機,從軟香蕉變成了硬橡膠,一篇篇優質的博客讓我陶醉其中無法自拔,俗話說三年之痛,七年之癢,在這個我認為不痛不癢的時候,是時候奉獻一下自己的積累,開始准備一個簡單框架系列主要包括----日志,基於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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM