日志记录类LogHelper
开源日志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”文件接着存放日志。