Log.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. //************************************************************************
  2. // https://github.com/yuzhengyang
  3. // author: yuzhengyang
  4. // date: 2017.3.29 - 2017.7.6
  5. // desc: 日志功能
  6. // Copyright (c) yuzhengyang. All rights reserved.
  7. //************************************************************************
  8. //R.Log.IsWriteFile = true;
  9. //R.Log.LogLevel = LogLevel.Warning | LogLevel.Debug;
  10. //Log.AllocConsole();
  11. //R.Log.v("this is v 啰嗦");
  12. //R.Log.d("this is d 调试");
  13. //R.Log.i("this is i 重要");
  14. //R.Log.w("this is w 警告");
  15. //R.Log.e("this is e 错误");
  16. using Azylee.Core.DataUtils.CollectionUtils;
  17. using Azylee.Core.DataUtils.StringUtils;
  18. using Azylee.Core.IOUtils.DirUtils;
  19. using Azylee.Core.IOUtils.TxtUtils;
  20. using System;
  21. using System.Collections.Concurrent;
  22. using System.Collections.Generic;
  23. using System.Linq;
  24. using System.Runtime.InteropServices;
  25. using System.Threading;
  26. using System.Threading.Tasks;
  27. namespace Azylee.Core.LogUtils
  28. {
  29. /// <summary>
  30. /// Log 输出工具
  31. ///
  32. /// 说明:
  33. /// 1、Log.AllocConsole();开启控制台
  34. /// 2、Log.FreeConsole();关闭控制台
  35. /// 3、Log.i("information");输出消息
  36. /// </summary>
  37. public class Log
  38. {
  39. #region 基础属性
  40. //输出的 Log 格式
  41. const string LOG_FORMAT = "{0} {1} {2}";
  42. const string TIME_FORMAT = "HH:mm:ss.fff";
  43. const string LOG_PATH = "Log";
  44. private object LogFileLock = new object();//写日志文件锁
  45. private bool IsWriteFile = false;//是否写日志文件
  46. public string LogPath = LOG_PATH;
  47. public LogLevel LogLevel = LogLevel.All;//日志输出等级
  48. bool IsStart = false;
  49. ConcurrentQueue<LogModel> Queue = new ConcurrentQueue<LogModel>();
  50. #endregion
  51. public Log()
  52. { }
  53. public Log(bool isWrite, string logPath = LOG_PATH, LogLevel level = LogLevel.All)
  54. {
  55. if (isWrite && !string.IsNullOrWhiteSpace(logPath))
  56. {
  57. LogPath = logPath.Trim();
  58. IsWriteFile = true;
  59. LogLevel = level;
  60. }
  61. }
  62. void Start()
  63. {
  64. return;
  65. if (!IsStart)
  66. {
  67. IsStart = true;
  68. Task.Factory.StartNew(() =>
  69. {
  70. while (IsStart)
  71. {
  72. Thread.Sleep(500);
  73. if (Queue.Any())
  74. {
  75. List<LogModel> list = new List<LogModel>();
  76. for (int i = 0; i < Queue.Count; i++)
  77. {
  78. LogModel model = null;
  79. if (Queue.TryDequeue(out model)) list.Add(model);
  80. }
  81. if (ListTool.HasElements(list)) WriteFile(list);
  82. }
  83. }
  84. });
  85. }
  86. }
  87. void Stop()
  88. {
  89. if (IsStart)
  90. IsStart = false;
  91. }
  92. public bool SetWriteFile(bool isWrite, string logPath)
  93. {
  94. if (isWrite && !string.IsNullOrWhiteSpace(logPath))
  95. {
  96. LogPath = logPath.Trim();
  97. IsWriteFile = true;
  98. return true;
  99. }
  100. IsWriteFile = false;
  101. return false;
  102. }
  103. #region Console 开启/关闭 API
  104. [DllImport("kernel32.dll")]
  105. public static extern Boolean AllocConsole();
  106. [DllImport("kernel32.dll")]
  107. public static extern Boolean FreeConsole();
  108. #endregion
  109. /// <summary>
  110. /// 获取输出颜色
  111. /// </summary>
  112. /// <param name="type">输出类型</param>
  113. /// <returns></returns>
  114. private ConsoleColor GetColor(LogType type)
  115. {
  116. switch (type)
  117. {
  118. case LogType.v: return ConsoleColor.Gray;
  119. case LogType.d: return ConsoleColor.Blue;
  120. case LogType.i: return ConsoleColor.Green;
  121. case LogType.w: return ConsoleColor.Yellow;
  122. case LogType.e: return ConsoleColor.Red;
  123. default: return ConsoleColor.Gray;
  124. }
  125. }
  126. /// <summary>
  127. /// 写出到控制台
  128. /// </summary>
  129. /// <param name="type">类型</param>
  130. /// <param name="tag">标记</param>
  131. /// <param name="message">消息</param>
  132. private void Write(LogType type, string message)
  133. {
  134. try
  135. {
  136. Console.ForegroundColor = GetColor(type);
  137. Console.WriteLine(LOG_FORMAT, DateTime.Now.ToString(TIME_FORMAT), type.ToString(), message);
  138. //取消单独线程输出日志文件(单独线程输出日志必然会有延迟)
  139. //if (IsWriteFile) Queue.Enqueue(new LogModel() { Type = type, Message = message, CreateTime = DateTime.Now });
  140. if (IsWriteFile) WriteFile(new LogModel() { Type = type, Message = message, CreateTime = DateTime.Now });
  141. }
  142. catch { }
  143. }
  144. private void WriteFile(LogModel log)
  145. {
  146. if (IsWriteFile)
  147. {
  148. lock (LogFileLock)
  149. {
  150. //设置日志目录
  151. string logPath = AppDomain.CurrentDomain.BaseDirectory + LogPath;
  152. string file = string.Format(@"{0}\{1}.txt", logPath, DateTime.Now.ToString("yyyy-MM-dd"));
  153. //创建日志目录
  154. DirTool.Create(logPath);
  155. //写出日志
  156. TxtTool.Append(
  157. file,
  158. string.Format(LOG_FORMAT,
  159. log.CreateTime.ToString(TIME_FORMAT),
  160. log.Type.ToString(),
  161. StringTool.ReplaceNewLine(log.Message)));
  162. }
  163. }
  164. }
  165. private void WriteFile(List<LogModel> list)
  166. {
  167. if (IsWriteFile)
  168. {
  169. lock (LogFileLock)
  170. {
  171. //设置日志目录
  172. string logPath = AppDomain.CurrentDomain.BaseDirectory + LogPath;
  173. string file = string.Format(@"{0}\{1}.txt", logPath, DateTime.Now.ToString("yyyy-MM-dd"));
  174. //创建日志目录
  175. DirTool.Create(logPath);
  176. //整理要输出的内容
  177. List<string> txts = new List<string>();
  178. foreach (var item in list)
  179. {
  180. txts.Add(string.Format(LOG_FORMAT, item.CreateTime.ToString(TIME_FORMAT), item.Type.ToString(), item.Message));
  181. }
  182. //写出日志
  183. TxtTool.Append(file, txts);
  184. }
  185. }
  186. }
  187. #region 分类详细输出
  188. /// <summary>
  189. /// 输出 verbose (啰嗦信息)
  190. /// </summary>
  191. /// <param name="message">消息</param>
  192. /// <param name="tag">可选:标记</param>
  193. public void v<T>(T msg)
  194. {
  195. if ((LogLevel & LogLevel.Verbose) == LogLevel.Verbose)
  196. Write(LogType.v, msg.ToString());
  197. }
  198. /// <summary>
  199. /// 输出 Debug (调试信息)
  200. /// </summary>
  201. /// <param name="message">消息</param>
  202. /// <param name="tag">可选:标记</param>
  203. public void d<T>(T msg)
  204. {
  205. if ((LogLevel & LogLevel.Debug) == LogLevel.Debug)
  206. Write(LogType.d, msg.ToString());
  207. }
  208. /// <summary>
  209. /// 输出 Information (重要信息)
  210. /// </summary>
  211. /// <param name="message">消息</param>
  212. /// <param name="tag">可选:标记</param>
  213. public void i<T>(T msg)
  214. {
  215. if ((LogLevel & LogLevel.Information) == LogLevel.Information)
  216. Write(LogType.i, msg.ToString());
  217. }
  218. /// <summary>
  219. /// 输出 Warning (警告信息)
  220. /// </summary>
  221. /// <param name="message">消息</param>
  222. /// <param name="tag">可选:标记</param>
  223. public void w<T>(T msg)
  224. {
  225. if ((LogLevel & LogLevel.Warning) == LogLevel.Warning)
  226. Write(LogType.w, msg.ToString());
  227. }
  228. /// <summary>
  229. /// 输出 Error (错误信息)
  230. /// </summary>
  231. /// <param name="message">消息</param>
  232. /// <param name="tag">可选:标记</param>
  233. public void e<T>(T msg)
  234. {
  235. if ((LogLevel & LogLevel.Error) == LogLevel.Error)
  236. Write(LogType.e, msg.ToString());
  237. }
  238. #endregion
  239. }
  240. }