Ferramenta de log para o framework TEngine

A impressão das informações do projeto do jogo ainda é muito importante. O mecanismo Unity fornece uma interface de depuração básica, mas não é especialmente personalizada. Para melhor uso, alguns encapsulamentos simples são necessários. 

using System.Diagnostics;
using System.Text;
using UnityEngine;
using Debug = UnityEngine.Debug;

namespace TEngine.Runtime
{
    /// <summary>
    /// 颜色工具
    /// </summary>
    public static class ColorUtils
    {
        #region ColorStr

        public const string White = "FFFFFF";
        public const string Black = "000000";
        public const string Red = "FF0000";
        public const string Green = "00FF18";
        public const string Oringe = "FF9400";
        public const string Exception = "FF00BD";
        #endregion

        public static string ToColor(this string str, string color)
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }

            return string.Format("<color=#{0}>{1}</color>", color, str);
        }
    }


    /// <summary>
    /// 日志工具
    /// </summary>

    public class TLogger : TSingleton<TLogger>
    {

        /// <summary>
        /// 初始化
        /// </summary>
        protected override void Init()
        {
            _outputType = OutputType.EDITOR;
            _logToFile = new LogToFile();
            _logToFile.Init();
            UnityEngine.Application.logMessageReceivedThreaded += OnLogMessageReceivedThreaded;
        }


        /// <summary>
        /// 输出日志文件
        /// </summary>
        private LogToFile _logToFile;
        private void OnLogMessageReceivedThreaded(string condition, string stackTrace, LogType type)
        {
            if (!condition.StartsWith("TLogger]"))
            {
                _stringBuilder.Clear();

                _stringBuilder.AppendFormat("[System][{0}][{1}] {2}", type.ToString(), System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), condition);

                if (type == LogType.Warning || type == LogType.Error || type == LogType.Exception)
                {
                    _stringBuilder.AppendLine(stackTrace);
                }

                string strToWrite = _stringBuilder.ToString();

                _logToFile.Write(strToWrite);
            }
        }

        ~TLogger()
        {
            
        }


        /// <summary>
        /// 释放
        /// </summary>
        public override void Release()
        {
            Application.logMessageReceivedThreaded -= OnLogMessageReceivedThreaded;
            _logToFile.DeInit();
            _logToFile = null;
            base.Release();
        }


        /// <summary>
        /// 修改输出日志方式
        /// </summary>
        /// <param name="type"></param>
        private void ChangeOutputChannel(OutputType type)
        {
            if (type != _outputType)
            {
                _outputType = type;
            }
        }


        /// <summary>
        /// 设置信息打印类型
        /// </summary>
        /// <param name="filterLevel"></param>
        public static void SetFilterLevel(LogLevel filterLevel)
        {
            Instance._filterLevel = filterLevel;
        }


        /// <summary>
        /// 打印资源信息
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="logStr"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_ASSERT")]
        public static void LogAssert(bool condition, string logStr = "")
        {
            if (!condition)
            {
                if (string.IsNullOrEmpty(logStr))
                {
                    logStr = string.Format("{0}", "Assert Failed");
                }
                Instance.Log(LogLevel.ASSERT, logStr);
            }
        }


        /// <summary>
        /// 打印资源信息
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="format"></param>
        /// <param name="args"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_ASSERT")]
        public static void LogAssert(bool condition, string format, params System.Object[] args)
        {
            if (!condition)
            {
                string logStr = string.Format(format, args);
                Instance.Log(LogLevel.ASSERT, logStr);
            }
        }


        /// <summary>
        /// 打印信息
        /// </summary>
        /// <param name="logStr"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_INFO")]
        public static void LogInfo(string logStr)
        {
            Instance.Log(LogLevel.INFO, logStr);
        }


        /// <summary>
        /// 打印信息
        /// </summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_INFO")]
        public static void LogInfo(string format, params System.Object[] args)
        {
            string logStr = string.Format(format, args);
            Instance.Log(LogLevel.INFO, logStr);
        }


        /// <summary>
        /// 打印成功信息
        /// </summary>
        /// <param name="logStr"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_SUCCESS")]
        public static void LogInfoSuccessd(string logStr)
        {
            Instance.Log(LogLevel.Successd, logStr);
        }


        /// <summary>
        /// 打印成功信息
        /// </summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_SUCCESS")]
        public static void LogInfoSuccessd(string format, params System.Object[] args)
        {
            string logStr = string.Format(format, args);
            Instance.Log(LogLevel.Successd, logStr);
        }


        /// <summary>
        /// 打印警告信息
        /// </summary>
        /// <param name="logStr"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_WARNING")]
        public static void LogWarning(string logStr)
        {
            Instance.Log(LogLevel.WARNING, logStr);
        }


        /// <summary>
        /// 打印警告信息
        /// </summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_WARNING")]
        public static void LogWarning(string format, params System.Object[] args)
        {
            string logStr = string.Format(format, args);
            Instance.Log(LogLevel.WARNING, logStr);
        }


        /// <summary>
        /// 打印错误信息
        /// </summary>
        /// <param name="logStr"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_ERROR")]
        public static void LogError(string logStr)
        {
            Instance.Log(LogLevel.ERROR, logStr);
        }


        /// <summary>
        /// 打印错误信息
        /// </summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_ERROR")]
        public static void LogError(string format, params System.Object[] args)
        {
            string logStr = string.Format(format, args);
            Instance.Log(LogLevel.ERROR, logStr);
        }


        /// <summary>
        /// 打印异常信息
        /// </summary>
        /// <param name="logStr"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_EXCEPTION")]
        public static void LogException(string logStr)
        {
            Instance.Log(LogLevel.EXCEPTION, logStr);
        }


        /// <summary>
        /// 打印异常信息
        /// </summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        [Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_EXCEPTION")]
        public static void LogException(string format, params System.Object[] args)
        {
            string msg = string.Format(format, args);
            Instance.Log(LogLevel.EXCEPTION, msg);
        }


        /// <summary>
        /// 打印信息字符串处理
        /// </summary>
        /// <param name="logLevel"></param>
        /// <param name="logString"></param>
        /// <param name="bColor"></param>
        /// <returns></returns>
        private StringBuilder GetFormatedString(LogLevel logLevel, string logString, bool bColor)
        {
            _stringBuilder.Clear();
            switch (logLevel)
            {
                case LogLevel.Successd:
                    if (UseCustomColor)
                    {
                        _stringBuilder.AppendFormat("[TLogger][SUCCESSED][{0}] - <color=#{2}>{1}</color>",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString, ColorUtils.Green);
                    }
                    else
                    {
                        _stringBuilder.AppendFormat(
                            bColor ? "[TLogger][INFO][{0}] - <color=#00FF18>{1}</color>" : "[TLogger][SUCCESSED][{0}] - {1}",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
                    }
                    break;
                case LogLevel.INFO:
                    if (UseCustomColor)
                    {
                        _stringBuilder.AppendFormat("[TLogger][INFO][{0}] - <color=#{2}>{1}</color>" , 
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString,ColorUtils.Black);
                    }
                    else
                    {
                        _stringBuilder.AppendFormat(
                            bColor ? "[TLogger][INFO][{0}] - <color=gray>{1}</color>" : "[TLogger][INFO][{0}] - {1}",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
                    }
                    break;
                case LogLevel.ASSERT:
                    if (UseCustomColor)
                    {
                        _stringBuilder.AppendFormat("[TLogger][ASSERT][{0}] - <color=#{2}>{1}</color>",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString,ColorUtils.Exception);
                    }
                    else
                    {
                        _stringBuilder.AppendFormat(
                            bColor ? "[TLogger][ASSERT][{0}] - <color=green>{1}</color>" : "[TLogger][ASSERT][{0}] - {1}",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
                    }
                    break;
                case LogLevel.WARNING:
                    if (UseCustomColor)
                    {
                        _stringBuilder.AppendFormat("[TLogger][WARNING][{0}] - <color=#{2}>{1}</color>",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString, ColorUtils.Oringe);
                    }
                    else
                    {
                        _stringBuilder.AppendFormat(
                            bColor
                                ? "[TLogger][WARNING][{0}] - <color=yellow>{1}</color>"
                                : "[TLogger][WARNING][{0}] - {1}", System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"),
                            logString);
                    }
                    break;
                case LogLevel.ERROR:
                    if (UseCustomColor)
                    {
                        _stringBuilder.AppendFormat("[ERROR][WARNING][{0}] - <color=#{2}>{1}</color>",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString, ColorUtils.Red);
                    }
                    else
                    {
                        _stringBuilder.AppendFormat(
                            bColor ? "[TLogger][ERROR][{0}] - <color=red>{1}</color>" : "[TLogger][ERROR][{0}] - {1}",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
                    }
                    break;
                case LogLevel.EXCEPTION:
                    if (UseCustomColor)
                    {
                        _stringBuilder.AppendFormat("[ERROR][EXCEPTION][{0}] - <color=#{2}>{1}</color>",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString, ColorUtils.Exception);
                    }
                    else
                    {
                        _stringBuilder.AppendFormat(
                            bColor
                                ? "[TLogger][EXCEPTION][{0}] - <color=red>{1}</color>"
                                : "[TLogger][EXCEPTION][{0}] - {1}",
                            System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
                    }
                    break;
            }

            return _stringBuilder;
        }


        /// <summary>
        /// 打印
        /// </summary>
        /// <param name="type"></param>
        /// <param name="logString"></param>
        private void Log(LogLevel type, string logString)
        {
            if (_outputType == OutputType.NONE)
            {
                return;
            }

            if (type < _filterLevel)
            {
                return;
            }

            StringBuilder infoBuilder = GetFormatedString(type, logString, UseSystemColor);
            string logStr = infoBuilder.ToString();

            //获取C#堆栈,Warning以上级别日志才获取堆栈
            if (type == LogLevel.ERROR || type == LogLevel.WARNING || type == LogLevel.EXCEPTION)
            {
                StackFrame[] sf = new StackTrace().GetFrames();
                for (int i = 0; i < sf.Length; i++)
                {
                    StackFrame frame = sf[i];
                    string declaringTypeName = frame.GetMethod().DeclaringType.FullName;
                    string methodName = sf[i].GetMethod().Name;

                    infoBuilder.AppendFormat("[{0}::{1}\n", declaringTypeName, methodName);
                }
            }

            if (type == LogLevel.INFO || type == LogLevel.Successd)
            {
                Debug.Log(logStr);
            }
            else if (type == LogLevel.WARNING)
            {
                Debug.LogWarning(logStr);
            }
            else if (type == LogLevel.ASSERT)
            {
                Debug.LogAssertion(logStr);
            }
            else if (type == LogLevel.ERROR)
            {
                Debug.LogError(logStr);
            }
            else if (type == LogLevel.EXCEPTION)
            {
                Debug.LogError(logStr);
            }
        }

        #region Properties
        public bool UseCustomColor = false;
        public bool UseSystemColor = true;


        /// <summary>
        /// 信息打印类型枚举
        /// </summary>
        public enum LogLevel
        {
            INFO,//普通信息打印
            Successd,//成功信息打印
            ASSERT,//资源信息打印
            WARNING,//警告信息打印
            ERROR,//错误信息打印
            EXCEPTION,//异常信息打印
        }


        /// <summary>
        /// 输出日志方式枚举
        /// </summary>
        [System.Flags]
        public enum OutputType
        {
            NONE = 0,
            EDITOR = 0x1,//编辑器模式
            GUI = 0x2,//UI模式
            FILE = 0x4//文件模式
        }

        private LogLevel _filterLevel = LogLevel.INFO;
        private OutputType _outputType = OutputType.EDITOR;
        private StringBuilder _stringBuilder = new StringBuilder();
        #endregion
    }
}

O acima é o encapsulamento da interface básica para impressão de logs. Às vezes, precisamos enviar o log de operação diária para um arquivo e também podemos definir o número máximo de dias para manter o arquivo de log.

using System;
using System.Collections.Generic;
using System.IO;

namespace TEngine.Runtime
{
    /// <summary>
    /// 日志文件的处理
    /// </summary>
    public class LogToFile
    {
        private FileWriter _fileWriter = new FileWriter();
        /// <summary>
        /// 存储日志文件的根目录
        /// </summary>
        private static readonly string mLogRootPath = Path.Combine(FileSystem.PersistentDataPath, "Log").FixPath();
        /// <summary>
        /// 日志保留天数
        /// </summary>
        private static int MaxLogDays = 3;
        private static string _currentLogName = string.Empty;

        /// <summary>
        /// 获得日志文件路径
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        private string GetLogPath(DateTime dt)
        {
            string dataDir = dt.ToString("yyyy_MM_dd");
            string logPath = Path.Combine(mLogRootPath, dataDir);
            return logPath.FixPath();
        }


        /// <summary>
        /// 日志文件中断
        /// </summary>
        public void DeInit()
        {
            if (_fileWriter == null)
            {
                return;
            }
            _fileWriter.Flush();
            _fileWriter.Shutdown();
        }


       /// <summary>
       /// 初始化
       /// </summary>
        public void Init()
        {
            DateTime currentTime = DateTime.Now;
            RemoveOldLogs(currentTime);
            string logDir = GetLogPath(currentTime);
            string logFileName = string.Format("Log_{0}.log", currentTime.ToString("yyyy_MM_dd-HH_mm_ss"));
            _currentLogName = logFileName;
            string fullPath = Path.Combine(logDir, logFileName).FixPath();
            try
            {
                if (!Directory.Exists(logDir))
                {
                    Directory.CreateDirectory(logDir);
                }

                if (File.Exists(fullPath))
                {
                    File.Delete(fullPath);
                }

                _fileWriter.OpenFile(fullPath);
            }
            catch (Exception e)
            {
                TLogger.LogException( e.ToString());
            }
        }


        /// <summary>
        /// 写
        /// </summary>
        /// <param name="msg"></param>
        public void Write(string msg)
        {
            if (_fileWriter == null)
            {
                return;
            }
            _fileWriter.Write(msg);
        }


        /// <summary>
        /// 删除超出最大保留天数的旧日志文件
        /// </summary>
        /// <param name="now"></param>
        private void RemoveOldLogs(DateTime now)
        {
            HashSet<string> foldersToKeep = new HashSet<string>();
            for (int i = 0; i < MaxLogDays; i++)
            {
                DateTime current = now.AddDays(-i);
                string folder = GetLogPath(current);
                foldersToKeep.Add(folder);
            }
            if (Directory.Exists(mLogRootPath))
            {
                try
                {
                    string[] allLogDir = Directory.GetDirectories(mLogRootPath);
                    foreach (string dir in allLogDir)
                    {
                        string fixedDir = dir.FixPath();
                        if (!foldersToKeep.Contains(fixedDir))
                        {
                            try
                            {
                                Directory.Delete(fixedDir, true);
                            }
                            catch (Exception e)
                            {
                                TLogger.LogException(e.ToString());
                            }

                        }
                    }
                }
                catch (Exception e)
                {
                    TLogger.LogException(e.ToString());
                }
            }
        }
    }
}

おすすめ

転載: blog.csdn.net/hppyW/article/details/130306927