当前位置:   article > 正文

[Unity] 自定义日志系统 解决Unity Log的痛点

unity log

当前Unity日志存在的问题:

1.日志打印没有时间

2.日志文件中Log、Warning、和Error区分度不大

3.长时间没有清理容易产生动辄几十MB,几十万行的日志文件

本日志系统区别于Unity原生Log主要有以下几点:

1.日志打印添加时间戳

2.普通打印可忽略堆栈信息

3.每次启动生成一份日志文件

4.日志文件包含设备信息

5.关闭Log可自定义关闭内容,关闭Log默认情况下仅屏蔽普通打印,不屏蔽Warning和Error

6.关闭Log情况下出现Error自动打印前20条Log方便跟踪报错

效果展示:

使用方式:

需要在程序初始化时调用初始化日志系统,以便日志系统捕获系统报错

Editor:

日志文件:

源码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using UnityEngine;
  5. namespace AuthorZhidai
  6. {
  7. public class Log
  8. {
  9. private const int LOG_COUNT = 20;// 最多临时保存LOG_COUNT条日志
  10. private const int LOG_FILE_COUNT = 10;// 最多保存的日志文件数
  11. public static bool EnableLog = true;// 是否启用日志,仅可控制普通级别的日志的启用与关闭,LogError和LogWarn都是始终启用的。
  12. public static bool EnableSave = true;// 是否允许保存日志,即把日志写入到文件中
  13. public static string LogFileDir = Application.dataPath.Replace("Assets", "") + "Log";// 日志存放目录:和Assets同级目录下的Log
  14. public static string LogFileName = "";
  15. public static string Prefix = "> ";// 用于与Unity默认的系统日志做区分。本日志系统输出的日志头部都会带上这个标记。
  16. public static StreamWriter LogFileWriter = null;
  17. //日志列表,忽略Info时报错回溯使用
  18. public static List<string> ListLogs = new List<string>();
  19. //第一次执行打印log
  20. private static bool FirstLogTag = true;
  21. public static void Init()
  22. {
  23. Application.logMessageReceived += OnLogByUnity;
  24. }
  25. #region 日志
  26. public static void Info(object message, bool recordStackTrace = false)
  27. {
  28. string str = "[I]" + GetLogTime() + message;
  29. AddListLogs(str);
  30. if (!EnableLog)
  31. return;
  32. Debug.Log(Prefix + str, null);
  33. LogToFile(str, recordStackTrace);
  34. }
  35. public static void Warning(object message)
  36. {
  37. string str = "[W]" + GetLogTime() + message;
  38. AddListLogs(str);
  39. Debug.LogWarning(Prefix + str, null);
  40. LogToFile(str, true);
  41. }
  42. public static void Error(object message)
  43. {
  44. string str = "[E]" + GetLogTime() + message;
  45. Debug.LogError(Prefix + str, null);
  46. if (!EnableLog)
  47. {
  48. OutputListLogs(LogFileWriter);// 忽略Info时报错,自动将日志记录到文件中方便回溯
  49. }
  50. else
  51. {
  52. AddListLogs(str);
  53. }
  54. LogToFile(str, true);
  55. }
  56. /// <summary>
  57. /// 输出列表中所有日志
  58. /// 可能会造成卡顿,谨慎使用。
  59. /// </summary>
  60. /// <param name="sw"></param>
  61. public static void OutputListLogs(StreamWriter sw)
  62. {
  63. if (sw == null || ListLogs.Count < 1)
  64. return;
  65. sw.WriteLine($"---------------- Log History Start [以下是报错前{ListLogs.Count}条日志]---------------- ");
  66. foreach (var i in ListLogs)
  67. {
  68. sw.WriteLine(i);
  69. }
  70. sw.WriteLine($"---------------- Log History End [以上是报错前{ListLogs.Count}条日志]---------------- ");
  71. ListLogs.Clear();
  72. }
  73. #endregion
  74. public static void CloseLog()
  75. {
  76. if (LogFileWriter != null)
  77. {
  78. try
  79. {
  80. LogFileWriter.Flush();
  81. LogFileWriter.Close();
  82. LogFileWriter.Dispose();
  83. LogFileWriter = null;
  84. }
  85. catch (Exception)
  86. {
  87. }
  88. }
  89. }
  90. public static void CheckClearLog()
  91. {
  92. if (!Directory.Exists(LogFileDir))
  93. {
  94. return;
  95. }
  96. DirectoryInfo direction = new DirectoryInfo(LogFileDir);
  97. var files = direction.GetFiles("*");
  98. if (files.Length >= LOG_FILE_COUNT)
  99. {
  100. var oldfile = files[0];
  101. var lastestTime = files[0].CreationTime;
  102. foreach (var file in files)
  103. {
  104. if (lastestTime > file.CreationTime)
  105. {
  106. oldfile = file;
  107. lastestTime = file.CreationTime;
  108. }
  109. }
  110. oldfile.Delete();
  111. }
  112. }
  113. private static void OnLogByUnity(string condition, string stackTrace, LogType type)
  114. {
  115. // 过滤自己的输出
  116. if (type == LogType.Log || condition.StartsWith(Prefix))
  117. {
  118. return;
  119. }
  120. var str = type == LogType.Warning ? "[W]" : "[E]" + GetLogTime() + condition + "\n" + stackTrace;
  121. if (!EnableLog && type != LogType.Warning)
  122. OutputListLogs(LogFileWriter);// 忽略Info时报错,自动将日志记录到文件中方便回溯
  123. else
  124. AddListLogs(str);
  125. LogToFile(str);
  126. }
  127. private static void AddListLogs(string str)
  128. {
  129. if (ListLogs.Count > LOG_COUNT)
  130. {
  131. ListLogs.RemoveAt(0);
  132. }
  133. ListLogs.Add(str);
  134. }
  135. private static string GetLogTime()
  136. {
  137. string str = "";
  138. str = DateTime.Now.ToString("HH:mm:ss.fff") + " ";
  139. return str;
  140. }
  141. /// <summary>
  142. /// 将日志写入到文件中
  143. /// </summary>
  144. /// <param name="message"></param>
  145. /// <param name="EnableStack"></param>
  146. private static void LogToFile(string message, bool EnableStack = false)
  147. {
  148. if (!EnableSave)
  149. return;
  150. if (LogFileWriter == null)
  151. {
  152. CheckClearLog();
  153. LogFileName = DateTime.Now.GetDateTimeFormats('s')[0].ToString();
  154. LogFileName = LogFileName.Replace("-", "_");
  155. LogFileName = LogFileName.Replace(":", "_");
  156. LogFileName = LogFileName.Replace(" ", "");
  157. LogFileName = LogFileName.Replace("T", "_");
  158. LogFileName = LogFileName + ".log";
  159. if (string.IsNullOrEmpty(LogFileDir))
  160. {
  161. try
  162. {
  163. if (!Directory.Exists(LogFileDir))
  164. {
  165. Directory.CreateDirectory(LogFileDir);
  166. }
  167. }
  168. catch (Exception exception)
  169. {
  170. Debug.Log(Prefix + "获取 Application.streamingAssetsPath 报错!" + exception.Message, null);
  171. return;
  172. }
  173. }
  174. string path = LogFileDir + "/" + LogFileName;
  175. Debug.Log("Log Path :" + LogFileDir + "\nLog Name :" + LogFileName);
  176. try
  177. {
  178. if (!Directory.Exists(LogFileDir))
  179. {
  180. Directory.CreateDirectory(LogFileDir);
  181. }
  182. LogFileWriter = File.AppendText(path);
  183. LogFileWriter.AutoFlush = true;
  184. }
  185. catch (Exception exception2)
  186. {
  187. LogFileWriter = null;
  188. Debug.Log("LogToCache() " + exception2.Message + exception2.StackTrace, null);
  189. return;
  190. }
  191. }
  192. if (LogFileWriter != null)
  193. {
  194. try
  195. {
  196. if (FirstLogTag)
  197. {
  198. FirstLogTag = false;
  199. PhoneSystemInfo(LogFileWriter);
  200. }
  201. LogFileWriter.WriteLine(message);
  202. if (EnableStack)
  203. {
  204. //把无关的log去掉
  205. var st = StackTraceUtility.ExtractStackTrace();
  206. #if UNITY_EDITOR
  207. for (int i = 0; i < 3; i++)
  208. #else
  209. for (int i = 0; i < 2; i++)
  210. #endif
  211. {
  212. st = st.Remove(0, st.IndexOf('\n') + 1);
  213. }
  214. LogFileWriter.WriteLine(st);
  215. }
  216. }
  217. catch (Exception)
  218. {
  219. }
  220. }
  221. }
  222. private static void PhoneSystemInfo(StreamWriter sw)
  223. {
  224. sw.WriteLine("*********************************************************************************************************start");
  225. sw.WriteLine("By " + SystemInfo.deviceName);
  226. DateTime now = DateTime.Now;
  227. sw.WriteLine(string.Concat(new object[] { now.Year.ToString(), "年", now.Month.ToString(), "月", now.Day, "日 ", now.Hour.ToString(), ":", now.Minute.ToString(), ":", now.Second.ToString() }));
  228. sw.WriteLine();
  229. sw.WriteLine("操作系统: " + SystemInfo.operatingSystem);
  230. sw.WriteLine("系统内存大小: " + SystemInfo.systemMemorySize);
  231. sw.WriteLine("设备模型: " + SystemInfo.deviceModel);
  232. sw.WriteLine("设备唯一标识符: " + SystemInfo.deviceUniqueIdentifier);
  233. sw.WriteLine("处理器数量: " + SystemInfo.processorCount);
  234. sw.WriteLine("处理器类型: " + SystemInfo.processorType);
  235. sw.WriteLine("显卡标识符: " + SystemInfo.graphicsDeviceID);
  236. sw.WriteLine("显卡名称: " + SystemInfo.graphicsDeviceName);
  237. sw.WriteLine("显卡标识符: " + SystemInfo.graphicsDeviceVendorID);
  238. sw.WriteLine("显卡厂商: " + SystemInfo.graphicsDeviceVendor);
  239. sw.WriteLine("显卡版本: " + SystemInfo.graphicsDeviceVersion);
  240. sw.WriteLine("显存大小: " + SystemInfo.graphicsMemorySize);
  241. sw.WriteLine("显卡着色器级别: " + SystemInfo.graphicsShaderLevel);
  242. sw.WriteLine("是否图像效果: " + SystemInfo.supportsImageEffects);
  243. sw.WriteLine("是否支持内置阴影: " + SystemInfo.supportsShadows);
  244. sw.WriteLine("*********************************************************************************************************end");
  245. sw.WriteLine("LogInfo:");
  246. sw.WriteLine();
  247. }
  248. }
  249. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/116842
推荐阅读
相关标签
  

闽ICP备14008679号