開源日志log4net使用起來很方便,但是項目中不讓用,所以自己重寫了一個類,用來記錄日志,比較簡單。
1、首先是可以把日志分成多個類型,分別記錄到不同的文件中
1 /// <summary> 2 /// 日志類型 3 /// </summary> 4 public enum LogType 5 { 6 /// <summary> 7 /// 插入型 8 /// </summary> 9 Insert, 10 /// <summary> 11 /// 更新型 12 /// </summary> 13 Update, 14 /// <summary> 15 /// 所有 16 /// </summary> 17 All, 18 /// <summary> 19 /// 結尾,放在最后 20 /// </summary> 21 End 22 }
我的是分三個,insert插入,update更新,all包括所有的日志。
2、接下來是LogHelper類,代碼中已注釋,不多說,直接上代碼
1 /// <summary> 2 /// 記錄日志 3 /// </summary> 4 public class LogHelper 5 { 6 7 #region 自定義變量 8 /// <summary> 9 /// 異常信息的隊列 10 /// </summary> 11 private static Queue<string> qMsg = null; 12 /// <summary> 13 /// 文件大小最大值,單位:Mb 14 /// </summary> 15 private static int maxFileSize = 10; 16 /// <summary> 17 /// 當天創建同一類型的日志文件的個數 18 /// </summary> 19 private static int[] createdFileCounts = new int[(int)LogType.End]; 20 /// <summary> 21 /// 日志文件存放路徑 22 /// </summary> 23 private static string logFilePath = ""; 24 #endregion 25 26 #region 屬性 27 /// <summary> 28 /// 文件大小最大值,單位:Mb。小於0時則不限制 29 /// </summary> 30 public static int MaxFileSize 31 { 32 get { return maxFileSize; } 33 set { maxFileSize = value; } 34 } 35 /// <summary> 36 /// 日志文件存放路徑 37 /// </summary> 38 public static string LogFilePath 39 { 40 set { logFilePath = value; } 41 get 42 { 43 if (!String.IsNullOrEmpty(logFilePath)) 44 { 45 return logFilePath; 46 } 47 else 48 { 49 return System.Windows.Forms.Application.StartupPath + "\\Log\\" + DateTime.Now.ToString("yyyy-MM-dd"); 50 } 51 } 52 } 53 #endregion 54 55 #region 構造函數 56 /// <summary> 57 /// 靜態構造函數 58 /// </summary> 59 static LogHelper() 60 { 61 qMsg = new Queue<string>(); 62 SetCreatedFileCount(); 63 RunThread(); 64 } 65 #endregion 66 67 #region 輔助 68 /// <summary> 69 /// 獲取日志文件的全路徑 70 /// </summary> 71 /// <param name="logType"></param> 72 /// <returns></returns> 73 private static string GetLogPath(LogType logType, bool isCreateNew) 74 { 75 string logPath = LogFilePath; 76 if (!Directory.Exists(logPath)) 77 { 78 Directory.CreateDirectory(logPath); 79 //看成是新的一天,要將昨天的數據清空 80 for (int i = 0; i < createdFileCounts.Length; i++) 81 { 82 createdFileCounts[i] = 0; 83 } 84 } 85 switch (logType) 86 { 87 case LogType.Insert: 88 logPath = logPath + "\\" + "Insert"; 89 break; 90 case LogType.Update: 91 logPath = logPath + "\\" + "Update"; 92 break; 93 default: 94 logPath = logPath + "\\" + "All"; 95 break; 96 } 97 if (isCreateNew) 98 { 99 int num = ++createdFileCounts[(int)logType]; 100 logPath += string.Format("({0}).log", num); 101 return logPath; 102 } 103 104 logPath += ".log"; 105 //createdFileCounts[(int)logType] = 0; 106 if (!File.Exists(logPath)) 107 { 108 //File.Create(logPath); 109 FileStream fs = File.Create(logPath); 110 fs.Close(); 111 fs.Dispose(); 112 } 113 114 return logPath; 115 } 116 117 /// <summary> 118 /// 運行線程 119 /// </summary> 120 private static void RunThread() 121 { 122 ThreadPool.QueueUserWorkItem(u => 123 { 124 while (true) 125 { 126 string tmsg = string.Empty; 127 lock (qMsg) 128 { 129 if (qMsg.Count > 0) 130 tmsg = qMsg.Dequeue(); 131 } 132 133 //往日志文件中寫錯誤信息 134 if (!String.IsNullOrEmpty(tmsg)) 135 { 136 int index = tmsg.IndexOf("&&"); 137 string logTypeStr = tmsg.Substring(0, index); 138 LogType logType = LogType.All; 139 if (logTypeStr == string.Format("{0}", LogType.Insert)) 140 { 141 logType = LogType.Insert; 142 } 143 else if (logTypeStr == string.Format("{0}", LogType.Update)) 144 { 145 logType = LogType.Update; 146 } 147 148 //記錄所有日志 149 WriteLog(tmsg.Substring(index + 2)); 150 //分開記錄日志 151 if (logType != LogType.All) 152 { 153 WriteLog(tmsg.Substring(index + 2), logType); 154 } 155 } 156 157 if (qMsg.Count <= 0) 158 { 159 Thread.Sleep(1000); 160 } 161 } 162 }); 163 } 164 165 /// <summary> 166 /// 程序剛啟動時 檢測已創建的日志文件個數 167 /// </summary> 168 private static void SetCreatedFileCount() 169 { 170 string logPath = LogFilePath; 171 if (!Directory.Exists(logPath)) 172 { 173 for (int i = 0; i < createdFileCounts.Length; i++ ) 174 { 175 createdFileCounts[i] = 0; 176 } 177 } 178 else 179 { 180 DirectoryInfo dirInfo = new DirectoryInfo(logPath); 181 FileInfo[] fileInfoes = dirInfo.GetFiles("*.log"); 182 foreach (FileInfo fi in fileInfoes) 183 { 184 string fileName = Path.GetFileNameWithoutExtension(fi.FullName).ToLower(); 185 if (fileName.Contains('(') && fileName.Contains(')')) 186 { 187 fileName = fileName.Substring(0, fileName.LastIndexOf('(')); 188 switch (fileName) 189 { 190 case "insert": 191 createdFileCounts[(int)LogType.Insert]++; 192 break; 193 case "update": 194 createdFileCounts[(int)LogType.Update]++; 195 break; 196 case "all": 197 createdFileCounts[(int)LogType.All]++; 198 break; 199 default: 200 break; 201 } 202 } 203 } 204 205 } 206 } 207 #endregion 208 209 #region 寫日志 210 211 /// <summary> 212 /// 寫日志 213 /// </summary> 214 /// <param name="strLog">日志內容</param> 215 public static void WriteLog(string strLog) 216 { 217 WriteLog(strLog, LogType.All); 218 } 219 220 /// <summary> 221 /// 寫日志 222 /// </summary> 223 /// <param name="strLog">日志內容</param> 224 /// <param name="logType">日志類型</param> 225 public static void WriteLog(string strLog, LogType logType) 226 { 227 if (String.IsNullOrEmpty(strLog)) 228 { 229 return; 230 } 231 strLog = strLog.Replace("\n", "\r\n"); 232 233 FileStream fs = null; 234 try 235 { 236 string logPath = GetLogPath(logType, false); 237 FileInfo fileInfo = new FileInfo(logPath); 238 if (MaxFileSize > 0 && fileInfo.Length > (1024 * 1024 * MaxFileSize)) 239 { 240 fileInfo.MoveTo(GetLogPath(logType, true)); 241 } 242 fs = File.Open(logPath, FileMode.OpenOrCreate); 243 //fs = File.OpenWrite(logPath); 244 byte[] btFile = Encoding.UTF8.GetBytes(strLog); 245 //設定書寫的開始位置為文件的末尾 246 fs.Position = fs.Length; 247 //將待寫入內容追加到文件末尾 248 fs.Write(btFile, 0, btFile.Length); 249 } 250 finally 251 { 252 if (fs != null) 253 { 254 fs.Close(); 255 fs.Dispose(); 256 } 257 } 258 } 259 260 /// <summary> 261 /// 寫入錯誤日志隊列 262 /// </summary> 263 /// <param name="msg">錯誤信息</param> 264 public static void WriteLogAsync(string strLog, LogType logType) 265 { 266 //將錯誤信息添加到隊列中 267 lock (qMsg) 268 { 269 qMsg.Enqueue(string.Format("{0}&&{1}\r\n", logType, strLog)); 270 } 271 } 272 #endregion 273 274 }
使用時,可以直接調用WriteLogAsync函數,將消息添加到隊列中,然后在另外的線程中處理隊列中的消息。
其中,如果沒有給LogFilePath屬性賦值,則有一個默認的文件存放路徑。MaxFileSize屬性是用來限制日志文件大小的,如果小於等於0則表示不限制。如果有限制,當文件大小超過這個最大值后會將原來的文件重命名,然后再創建一個“自己”。例如:正在存放日志的文件名為"All.log",當它滿了以后就成為“All(n).log”文件,n為從1開始遞增的數字,然后會重新創建一個“All.log”文件接着存放日志。