1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Reflection;
6 using System.Threading;
7
8 namespace Common
9 {
10 /// <summary>
11 /// 处理日志输出的类
12 /// </summary>
13 public class Log
14 {
15 /// <summary>
16 /// 构造函数
17 /// </summary>
18 static Log()
19 {
20 // 打印日志的独立线程
21 Thread thread = new Thread(ThreadStart);
22 thread.IsBackground = true;
23 thread.Start();
24 }
25
26 #region 字段
27 private static readonly Queue<string[]> _logQueue = new Queue<string[]>(); // 日志队列
28 private static readonly object _lock = new object(); // 日志队列锁
29 private static string _path = null; // 工程路径
30 private static readonly int _fileSize = 10 * 1024 * 1024; //日志分隔文件大小
31 #endregion
32
33 #region 写文件
34 /// <summary>
35 /// 写文件
36 /// </summary>
37 private static void WriteFile(string log, string time, string path)
38 {
39 try
40 {
41 // 创建文件
42 if (!Directory.Exists(Path.GetDirectoryName(path)))
43 {
44 Directory.CreateDirectory(Path.GetDirectoryName(path));
45 }
46 // 写文件
47 using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write))
48 {
49 using (StreamWriter sw = new StreamWriter(fs))
50 {
51 sw.WriteLine(string.Format(@"{0}{1}", time, log));
52 }
53 }
54 }
55 catch { }
56 }
57 #endregion
58
59 #region 生成日志文件路径
60 /// <summary>
61 /// 生成日志文件路径
62 /// </summary>
63 private static string CreateLogPath(string folder)
64 {
65 if (_path == null)
66 {
67 UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().Location);
68 _path = Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
69 }
70
71 int index = 0;
72 string logPath;
73 bool bl = true;
74 do
75 {
76 index++;
77 logPath = Path.Combine(_path, folder + DateTime.Now.ToString("yyyyMMdd") + (index == 1 ? "" : "_" + index.ToString()) + ".log");
78 if (File.Exists(logPath))
79 {
80 FileInfo fileInfo = new FileInfo(logPath);
81 if (fileInfo.Length < _fileSize)
82 {
83 bl = false;
84 }
85 }
86 else
87 {
88 bl = false;
89 }
90 } while (bl);
91
92 return logPath;
93 }
94 #endregion
95
96 #region 写错误日志
97 /// <summary>
98 /// 输出error日志
99 /// </summary>
100 /// <param name="ex">Exception对象</param>
101 public static void WriteError(Exception ex)
102 {
103 // 调用者的方法名
104 StackTrace trace = new StackTrace();
105 string className = trace.GetFrame(1).GetMethod().ReflectedType.Name;
106 string methodName = trace.GetFrame(1).GetMethod().Name;
107 // 日志内容
108 string logMseeage = " [ERROR] " +
109 "【" + className + "." + methodName + "】" +
110 ex.GetType() + "\r\n" +
111 ex.Message + "\r\n" +
112 ex.StackTrace;
113 // 写日志
114 WriteLog(logMseeage);
115 }
116 #endregion
117
118 #region 写操作日志
119 /// <summary>
120 /// 输出info日志
121 /// </summary>
122 /// <param name="formatMessage">输出消息格式</param>
123 /// <param name="args">参数</param>
124 public static void WriteInfo(string formatMessage, params object[] args)
125 {
126 // 调用者的方法名
127 StackTrace trace = new StackTrace();
128 string className = trace.GetFrame(1).GetMethod().ReflectedType.Name;
129 string methodName = trace.GetFrame(1).GetMethod().Name;
130 if (className == "BaseAccess")//自定义输出堆栈信息,也可以递归输出堆栈信息
131 {
132 className = trace.GetFrame(2).GetMethod().ReflectedType.Name;
133 methodName = trace.GetFrame(2).GetMethod().Name;
134 }
135 // 日志内容
136 string logMseeage = " [INFO] " +
137 "【" + className + "." + methodName + "】" +
138 String.Format(formatMessage, args);
139 // 写日志
140 WriteLog(logMseeage);
141 }
142 #endregion
143
144 #region 队列方法
145 /// <summary>
146 /// 添加日志队列
147 /// </summary>
148 /// <param name="msg"></param>
149 private static void WriteLog(string msg)
150 {
151 lock (_lock)
152 {
153 // 添加队列
154 _logQueue.Enqueue(new string[] { msg, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") });
155 }
156 }
157 /// <summary>
158 /// 读取日志队列
159 /// </summary>
160 private static void ThreadStart()
161 {
162 while (true)
163 {
164 if (_logQueue.Count > 0)
165 {
166 try
167 {
168 //从队列中取出
169 string[] arr = _logQueue.Dequeue();
170 WriteFile(arr[0], arr[1], CreateLogPath("Logs//"));
171 }
172 catch { }
173 }
174 else
175 {
176 Thread.Sleep(1000);
177 }
178 }
179 }
180 #endregion
181
182 }
183 }