Log.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. //************************************************************************
  2. // author: yuzhengyang
  3. // date: 2017.3.29 - 2018.4.27
  4. // desc: 日志功能
  5. // Copyright (c) yuzhengyang. All rights reserved.
  6. //************************************************************************
  7. //R.Log.IsWriteFile = true;
  8. //R.Log.LogLevel = LogLevel.Warning | LogLevel.Debug;
  9. //Log.AllocConsole();
  10. //R.Log.v("this is v 啰嗦");
  11. //R.Log.d("this is d 调试");
  12. //R.Log.i("this is i 重要");
  13. //R.Log.w("this is w 警告");
  14. //R.Log.e("this is e 错误");
  15. using Azylee.Core.DataUtils.CollectionUtils;
  16. using Azylee.Core.DataUtils.StringUtils;
  17. using Azylee.Core.IOUtils.DirUtils;
  18. using Azylee.Core.IOUtils.FileUtils;
  19. using Azylee.Core.IOUtils.TxtUtils;
  20. using Azylee.Core.WindowsUtils.ConsoleUtils;
  21. using System;
  22. using System.Collections.Concurrent;
  23. using System.Collections.Generic;
  24. using System.IO;
  25. using System.Linq;
  26. using System.Runtime.InteropServices;
  27. using System.Threading;
  28. using System.Threading.Tasks;
  29. namespace Azylee.Core.LogUtils.SimpleLogUtils
  30. {
  31. /// <summary>
  32. /// Log 输出工具
  33. ///
  34. /// 说明:
  35. /// 1、Log.AllocConsole();开启控制台
  36. /// 2、Log.FreeConsole();关闭控制台
  37. /// 3、Log.i("information");输出消息
  38. /// </summary>
  39. public class Log
  40. {
  41. #region 基础属性
  42. //输出的 Log 格式
  43. const string LOG_FORMAT = "{0} {1} {2}";
  44. const string TIME_FORMAT = "HH:mm:ss.fff";
  45. const string LOG_PATH = "azylee.log";
  46. private int CACHE_DAYS = 30;//缓存天数
  47. private object LogFileLock = new object();//写日志文件锁
  48. private string LogPath = AppDomain.CurrentDomain.BaseDirectory + LOG_PATH;
  49. private LogLevel ConsoleLogLevel = LogLevel.All;//日志输出到"控制台"等级
  50. private LogLevel FileLogLevel = LogLevel.All;//日志输出到"文件"等级
  51. #endregion
  52. private Log() { }
  53. /// <summary>
  54. /// 初始化 Log 工具
  55. /// </summary>
  56. /// <param name="isWrite">已失效,使用WriteLevel代替</param>
  57. /// <param name="logLevel"></param>
  58. /// <param name="writeLevel"></param>
  59. [Obsolete]
  60. public Log(bool isWrite, LogLevel logLevel = LogLevel.All, LogLevel writeLevel = LogLevel.All)
  61. {
  62. if (isWrite)
  63. {
  64. //IsWriteFile = true;//已禁用,使用文件输出等级控制
  65. ConsoleLogLevel = logLevel;
  66. FileLogLevel = writeLevel;
  67. }
  68. }
  69. /// <summary>
  70. /// 初始化 Log 工具
  71. /// </summary>
  72. /// <param name="console">控制台输出级别</param>
  73. /// <param name="file">文件输出级别</param>
  74. public Log(LogLevel console = LogLevel.All, LogLevel file = LogLevel.All)
  75. {
  76. ConsoleLogLevel = console;
  77. FileLogLevel = file;
  78. }
  79. /// <summary>
  80. /// 设置日志路径
  81. /// </summary>
  82. /// <param name="path"></param>
  83. public void SetLogPath(string path)
  84. {
  85. if (!string.IsNullOrWhiteSpace(path))
  86. {
  87. LogPath = DirTool.Combine(path, LOG_PATH);
  88. }
  89. }
  90. /// <summary>
  91. /// 设置日志缓存天数(默认30天)
  92. /// </summary>
  93. /// <param name="days"></param>
  94. public void SetCacheDays(int days)
  95. {
  96. if (days >= 0) CACHE_DAYS = days;
  97. }
  98. #region Console 开启/关闭 API
  99. /// <summary>
  100. /// 启用系统控制台输出
  101. /// </summary>
  102. /// <returns></returns>
  103. [DllImport("kernel32.dll")]
  104. public static extern Boolean AllocConsole();
  105. /// <summary>
  106. /// 关闭系统控制台
  107. /// </summary>
  108. /// <returns></returns>
  109. [DllImport("kernel32.dll")]
  110. public static extern Boolean FreeConsole();
  111. #endregion
  112. /// <summary>
  113. /// 获取输出颜色
  114. /// </summary>
  115. /// <param name="type">输出类型</param>
  116. /// <returns></returns>
  117. private ConsoleColor GetColor(LogType type)
  118. {
  119. switch (type)
  120. {
  121. case LogType.v: return ConsoleColor.Gray;
  122. case LogType.d: return ConsoleColor.Blue;
  123. case LogType.i: return ConsoleColor.Green;
  124. case LogType.w: return ConsoleColor.Yellow;
  125. case LogType.e: return ConsoleColor.Red;
  126. default: return ConsoleColor.Gray;
  127. }
  128. }
  129. /// <summary>
  130. /// 写出到控制台
  131. /// </summary>
  132. /// <param name="type">类型</param>
  133. /// <param name="message">消息</param>
  134. private void WriteConsole(LogType type, string message)
  135. {
  136. try
  137. {
  138. message = Cons.FormatLine(message); //处理日志信息(换行)
  139. Cons.SetColor(GetColor(type), ConsoleColor.Black);
  140. Console.WriteLine(LOG_FORMAT, DateTime.Now.ToString(TIME_FORMAT), type.ToString(), message);
  141. Cons.ResetColor();
  142. //取消单独线程输出日志文件(单独线程输出日志必然会有延迟)
  143. //if (IsWriteFile) Queue.Enqueue(new LogModel() { Type = type, Message = message, CreateTime = DateTime.Now });
  144. }
  145. catch { }
  146. }
  147. /// <summary>
  148. /// 写出到日志文件
  149. /// </summary>
  150. /// <param name="log"></param>
  151. private void WriteFile(LogModel log)
  152. {
  153. lock (LogFileLock)
  154. {
  155. //设置日志目录和日志文件
  156. string filePath = GetFilePath(log.Type);
  157. string file = DirTool.Combine(filePath, DateTime.Now.ToString("yyyy-MM-dd") + ".txt");
  158. //创建日志目录
  159. DirTool.Create(filePath);
  160. //处理日志信息(换行)
  161. log.Message = Cons.FormatLine(log.Message);
  162. //写出日志
  163. TxtTool.Append(
  164. file,
  165. string.Format(LOG_FORMAT,
  166. log.CreateTime.ToString(TIME_FORMAT),
  167. log.Type.ToString(),
  168. log.Message));
  169. Cleaner(log.Type);
  170. }
  171. }
  172. /// <summary>
  173. /// 根据分类分配目录
  174. /// </summary>
  175. /// <param name="type"></param>
  176. /// <returns></returns>
  177. private string GetFilePath(LogType type)
  178. {
  179. string filePath = LogPath;
  180. switch (type)
  181. {
  182. case LogType.d: filePath = DirTool.Combine(LogPath, "debug"); break;
  183. case LogType.i: filePath = DirTool.Combine(LogPath, "information"); break;
  184. case LogType.e: filePath = DirTool.Combine(LogPath, "error"); break;
  185. case LogType.w: filePath = DirTool.Combine(LogPath, "warning"); break;
  186. case LogType.v: filePath = DirTool.Combine(LogPath, "verbose"); break;
  187. }
  188. return filePath;
  189. }
  190. /// <summary>
  191. /// 清理过多的日志文件
  192. /// </summary>
  193. private void Cleaner(LogType type)
  194. {
  195. List<string> files = FileTool.GetFile(GetFilePath(type));
  196. if (ListTool.HasElements(files))
  197. {
  198. files.ForEach(f =>
  199. {
  200. try
  201. {
  202. string filename = Path.GetFileNameWithoutExtension(f);
  203. if (filename.Length == 10)
  204. {
  205. DateTime date = DateTime.Parse(filename);
  206. if (date < DateTime.Now.AddDays(-CACHE_DAYS - 1)) FileTool.Delete(f);
  207. }
  208. else { FileTool.Delete(f); }
  209. }
  210. catch { FileTool.Delete(f); }
  211. });
  212. }
  213. }
  214. #region 分类详细输出
  215. #region 因大小写命名规范冲突,将次类方法标记为弃用
  216. /// <summary>
  217. /// 输出 verbose (啰嗦信息)
  218. /// </summary>
  219. /// <param name="msg">消息</param>
  220. [Obsolete]
  221. public void v<T>(T msg)
  222. {
  223. V(msg);
  224. }
  225. /// <summary>
  226. /// 输出 Debug (调试信息)
  227. /// </summary>
  228. /// <param name="msg">消息</param>
  229. [Obsolete]
  230. public void d<T>(T msg)
  231. {
  232. D(msg);
  233. }
  234. /// <summary>
  235. /// 输出 Information (重要信息)
  236. /// </summary>
  237. /// <param name="msg">消息</param>
  238. [Obsolete]
  239. public void i<T>(T msg)
  240. {
  241. I(msg);
  242. }
  243. /// <summary>
  244. /// 输出 Warning (警告信息)
  245. /// </summary>
  246. /// <param name="msg">消息</param>
  247. [Obsolete]
  248. public void w<T>(T msg)
  249. {
  250. W(msg);
  251. }
  252. /// <summary>
  253. /// 输出 Error (错误信息)
  254. /// </summary>
  255. /// <param name="msg">消息</param>
  256. [Obsolete]
  257. public void e<T>(T msg)
  258. {
  259. E(msg);
  260. }
  261. #endregion
  262. /// <summary>
  263. /// 输出 verbose (啰嗦信息)
  264. /// </summary>
  265. /// <param name="msg">消息</param>
  266. public void V<T>(T msg)
  267. {
  268. if ((ConsoleLogLevel & LogLevel.Verbose) == LogLevel.Verbose)
  269. WriteConsole(LogType.v, msg?.ToString());
  270. if ((FileLogLevel & LogLevel.Verbose) == LogLevel.Verbose)
  271. WriteFile(new LogModel() { Type = LogType.v, Message = msg?.ToString(), CreateTime = DateTime.Now });
  272. }
  273. /// <summary>
  274. /// 输出 Debug (调试信息)
  275. /// </summary>
  276. /// <param name="msg">消息</param>
  277. public void D<T>(T msg)
  278. {
  279. if ((ConsoleLogLevel & LogLevel.Debug) == LogLevel.Debug)
  280. WriteConsole(LogType.d, msg?.ToString());
  281. if ((FileLogLevel & LogLevel.Debug) == LogLevel.Debug)
  282. WriteFile(new LogModel() { Type = LogType.d, Message = msg?.ToString(), CreateTime = DateTime.Now });
  283. }
  284. /// <summary>
  285. /// 输出 Information (重要信息)
  286. /// </summary>
  287. /// <param name="msg">消息</param>
  288. public void I<T>(T msg)
  289. {
  290. if ((ConsoleLogLevel & LogLevel.Information) == LogLevel.Information)
  291. WriteConsole(LogType.i, msg?.ToString());
  292. if ((FileLogLevel & LogLevel.Information) == LogLevel.Information)
  293. WriteFile(new LogModel() { Type = LogType.i, Message = msg?.ToString(), CreateTime = DateTime.Now });
  294. }
  295. /// <summary>
  296. /// 输出 Warning (警告信息)
  297. /// </summary>
  298. /// <param name="msg">消息</param>
  299. public void W<T>(T msg)
  300. {
  301. if ((ConsoleLogLevel & LogLevel.Warning) == LogLevel.Warning)
  302. WriteConsole(LogType.w, msg?.ToString());
  303. if ((FileLogLevel & LogLevel.Warning) == LogLevel.Warning)
  304. WriteFile(new LogModel() { Type = LogType.w, Message = msg?.ToString(), CreateTime = DateTime.Now });
  305. }
  306. /// <summary>
  307. /// 输出 Error (错误信息)
  308. /// </summary>
  309. /// <param name="msg">消息</param>
  310. public void E<T>(T msg)
  311. {
  312. if ((ConsoleLogLevel & LogLevel.Error) == LogLevel.Error)
  313. WriteConsole(LogType.e, msg?.ToString());
  314. if ((FileLogLevel & LogLevel.Error) == LogLevel.Error)
  315. WriteFile(new LogModel() { Type = LogType.e, Message = msg?.ToString(), CreateTime = DateTime.Now });
  316. }
  317. #endregion
  318. }
  319. }