【系统架构教程——开发篇】之一:高效开发之自定义Log日志系统
本文由@唐三十胖子出品,转载请注明出处。
文章链接:https://blog.****.net/iceSony/article/details/83584666
这篇文章由唐三胖ヾ(•ω•`)o网络整理总结,将告诉你如何开发一个高效率的日志系统。
通过这篇文章,你可以知道
1)什么是日志系统
2)Unity下的Log日志系统的缺陷
3)自定义Log日志系统的好处
一.什么是日志系统
从你学C开始的那句hello,world开始,你就在接触日志系统
个人观点:输出你觉得有必要提示的信息,这就是日志
这也是为什么Android中会有那么复杂的日志系统
为了分工协作,为了问题定位,为了代码维护。。。。。。
Unity自带了三种日志输出:Log,Warning,Error
三种程度依次增加,系统提示的Error一定是代码逻辑出错
Warning警告可能出错
Log程度最轻,显示输出的作用。
二.Unity下的Log日志系统的缺陷
乍看起来很方便的日志系统背后,你有没有想过这样一些问题:
1.代码发生问题没法快速定位
你知道自己写的Logerror位置,可是同事不知道是哪个类进行了调用
需要花费大量时间去找出错区域,造成开发延期
PS:现在我正在做性能优化,这一点更为明显
2.其次没有相关信息输出
比如日期
当输出了错误A,B,但我根本不知道这两个BUG的先后顺序
3.最后项目运行结束发现了问题,你怎么集中管理呢??
事实上自带的Log日志我们没办法集中管理,尤其是项目发布以后
我们如何对用户信息进行获取也是个问题
就比如手机上logerror,编辑器模式下可以看到,服务器怎么知道呢?那我们也就没法定位问题
只能等到用户流失以后,赶紧打补丁
这时候我们需要把所有的问题搜集起来变成一个log日志,然后上传服务器来获取项目中的问题
附:而且要知道log其实是有性能消耗的(当然函数调用也会有,但是输出会更多些)我们Log的字符串占用了gc
并没有提供日志关闭的方式,所以我们需要重写日志系统。
事实上提供了一种方法,但本质还是重写:https://www.xuanyusong.com/archives/2782
具体思路:
重写Debug代码,添加我们需要的全局开关
开关开才干活,不然什么都不做
开关一共有四个,涉及了是否输出,是否输出时间,是否保存到文件,是否保存调用堆栈到文件
具体代码如下:
using System; using System.IO; namespace UnityEngine { public class Debuger { public static bool EnableLog = true; public static bool EnableTime = true; public static bool EnableSave = false; public static bool EnableStack = false; public static string LogFileDir = Application.persistentDataPath + "/DebugerLog"; public static string LogFileName = ""; public static string Prefix = "> "; public static StreamWriter LogFileWriter = null; public static void Log(object message) { if (!Debuger.EnableLog) return; string msg = GetLogTime() + message; Debug.Log(Prefix+msg,null); LogToFile("[I]" + msg); } public static void Log(object message,Object context) { if (!Debuger.EnableLog) return; string msg = GetLogTime() + message; Debug.Log(Prefix + msg, context); LogToFile("[I]" + msg); } public static void LogError(object message) { string msg = GetLogTime() + message; Debug.LogError(Prefix + msg, null); LogToFile("[E]" + msg); } public static void LogError(object message, Object context) { string msg = GetLogTime() + message; Debug.LogError(Prefix + msg, context); LogToFile("[E]" + msg); } public static void LogWarning(object message) { string msg = GetLogTime() + message; Debug.LogWarning(Prefix + msg, null); LogToFile("[W]" + msg); } public static void LogWarning(object message, Object context) { string msg = GetLogTime() + message; Debug.LogWarning(Prefix + msg, context); LogToFile("[W]" + msg); } public static void Log(string tag, string message) { if (!Debuger.EnableLog) return; message = GetLogText(tag, message); Debug.Log(Prefix + message); LogToFile("[I]" + message); } public static void Log(string tag, string format, params object[] args) { if (!Debuger.EnableLog) return; string message = GetLogText(tag, string.Format(format, args)); Debug.Log(Prefix + message); LogToFile("[I]" + message); } public static void LogError(string tag, string message) { message = GetLogText(tag, message); Debug.LogError(Prefix + message); LogToFile("[E]" + message, true); } public static void LogError(string tag, string format, params object[] args) { string message = GetLogText(tag, string.Format(format, args)); Debug.LogError(Prefix + message); LogToFile("[E]" + message, true); } public static void LogWarning(string tag, string message) { message = GetLogText(tag, message); Debug.LogWarning(Prefix + message); LogToFile("[W]" + message); } public static void LogWarning(string tag, string message, params object[] args) { message = GetLogText(tag, message); Debug.LogWarning(Prefix + message); LogToFile("[W]" + message); } private static string GetLogText(string tag, string message) { string str = ""; if (Debuger.EnableTime) { DateTime now = DateTime.Now; str = now.ToString("HH:mm:ss.fff") + " "; } str = str + tag + "::" + message; return str; } private static String GetLogTime() { string str = ""; if (Debuger.EnableTime) { DateTime now = DateTime.Now; str = now.ToString("HH:mm:ss.fff")+" "; } return str; } private static void LogToFile(string message, bool EnableStack = false) { if (!EnableSave) return; if (LogFileWriter == null) { DateTime now = DateTime.Now; LogFileName = now.GetDateTimeFormats('s')[0].ToString(); LogFileName = LogFileName.Replace("-", "_"); LogFileName = LogFileName.Replace(":", "_"); LogFileName = LogFileName.Replace(" ", ""); LogFileName += ".log"; string fullpath = LogFileDir + LogFileName; try { if (!Directory.Exists(LogFileDir)) { Directory.CreateDirectory(LogFileDir); } LogFileWriter = File.AppendText(fullpath); LogFileWriter.AutoFlush = true; } catch (Exception e) { LogFileWriter = null; Debug.LogError("LogToCache() " + e.Message + e.StackTrace); return; } if (LogFileWriter != null) { try { LogFileWriter.WriteLine(message); if (EnableStack || Debuger.EnableStack) { LogFileWriter.WriteLine(StackTraceUtility.ExtractStackTrace()); } } catch (Exception) { return; } } } } } }
具体调用也很简单:
public class AppMain : MonoBehaviour { void Start () { Debuger.EnableLog = true; Debug.LogError("aaa"); } void Update() { this.Log("asdasd"); } }
没什么太复杂的,但在调用方法的Update中看到一种更方便的调用
这也是下一章要做的升级2.0版本♪(・ω・)ノ
在下一章节,我们将进一步优化这个看起来复杂的Debuger类
让你仅仅需要this.Log this.LogError就可以实现日志输出
让书写更加便捷。