U3D客户端框架之日志写入器 把Log日志写入到可写区 方便调试

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: U3D客户端框架之日志写入器 把Log日志写入到可写区 方便调试

1 日志写入器概要


设计目的


有一段时间游戏战斗系统里出现了一个不是必现的BUG,偶尔出现偶尔不出现,Unity虽然安装了Reporter调试插件,但是日志还是无法写入本地,就很蛋疼。同事说可以连接logcat做定位,可是logcat用过的小伙伴都知道,总是会输出一大堆不需要的log,容易遗漏关键信息。最麻烦的是需要插着线调试非常麻烦。定位一些不是很好复现的BUG的时候,很麻烦。 unity3d打印出来的日志不会写入本地,有时候移动端开发如果没有log很难定位BUG。所以搭这套框架的时候考虑到了这点,加了日志写入器。


2 代码设计


为了避免频繁写入,文件频繁IO影响程序性能,根据数量策略向用户可写区Append日志数据。好困,想到再写~


LoggerManager.cs代码


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using YouYou;
namespace Myh
{
    public class LoggerManager : ManagerBase, IDisposable
    {
        //日志数组
        private List<string> m_LogArray;
        //记录(写入)日志的路径
        private string m_LogPath = null;
        //单个日志文件最大日志数量
        private int m_LogMaxCapacity = 500;
        //当前日志数量(当前日志文件写入的日志数量)
        private int m_CurrLogCount = 0;
        //日志缓存的数量(内存中有多少条log会写入磁盘一次,应该叫落地数量吧)
        private int m_LogBufferMaxNumber = 10;
        public override void Init()
        {
            m_LogArray = new List<string>();
            if (string.IsNullOrEmpty(m_LogPath))
            {
                //在可写区(persistent data path 也叫local path)创建日志文件
                //文件格式以年-月-日-时-分-秒+Start.txt 命名
                m_LogPath = Application.persistentDataPath + "//" + "MYH_LOG_"+DateTime.Now.ToString("yyyy-MM-dd_hh.mm.ss") + "-Start.txt";
            }
            GameEntry.Log(LogCategory.Normal, "LoggerManager.Init LogPath{0}", m_LogPath);
        }
        //写入日志,并且检查是否存在日志文件,弱不存在则创建日志文件
        private void CreateFile(string pathAndName, string info)
        {
            StreamWriter sw;
            FileInfo fileInfo = new FileInfo(pathAndName);
            if (!fileInfo.Exists)
            {
                //CreateText方法限定了文本文件,只能创建文本文件
                //Create应该可以创建任何类型的文件
                sw = fileInfo.CreateText();
            }
            else
            {
                sw = fileInfo.AppendText();
            }
            //写入一行
            sw.WriteLine(info);
            //关闭流
            sw.Close();
            //销毁?
            sw.Dispose();
        }
        //同步日志(写入磁盘)
        public void SyncLog()
        {
            if (!string.IsNullOrEmpty(m_LogPath))
            {
                int iLen = m_LogArray.Count;
                for (int i = 0; i < iLen; ++i)
                {
                    //写入日志
                    CreateFile(m_LogPath, m_LogArray[i]);
                }
                ClearLogArray();
            }
        }
        //附加日志到文件尾部
        public void AppendDataToFile(string writerFileData)
        {
            if (!string.IsNullOrEmpty(writerFileData))
            {
                m_LogArray.Add(writerFileData);
            }
            if (m_LogArray.Count % m_LogBufferMaxNumber == 0)
            {
                SyncLog();
            }
        }
        //写入日志
        public void Write(string strWriteFileData, LogType logType)
        {
            //判断单个文件写入数量是否超过上限,如果超过上限用当前时间新创建一个日志文件
            if (m_CurrLogCount >= m_LogMaxCapacity)
            {
                m_LogPath = Application.persistentDataPath + "//" + "MYH_LOG_" + DateTime.Now.ToString("yyyy-MM-dd_hh.mm.ss") + ".txt";
                m_CurrLogCount = 0;
            }
            ++m_CurrLogCount;
            if (!string.IsNullOrEmpty(strWriteFileData))
            {
                //拼接写入的时间
                strWriteFileData = "[" + DateTime.Now.ToString("yyyy-MM-dd hh.mm.ss") + "] [" + logType + "] " + strWriteFileData;
                AppendDataToFile(strWriteFileData);
            }
        }
        //清理Log数组
        private void ClearLogArray()
        {
            if (null != m_LogArray)
            {
                m_LogArray.Clear();
            }
        }
        public void Dispose()
        {
            m_LogArray.Clear();
        }
    }
}


3 测试


设计完之后,最重要的是测试并且验证实现过的功能。在Win32平台测试后,日志可以正常写入到可写区。


测试代码


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YouYou;
using UnityEngine;
public class TestUtils : ITest
{
    private void TestLogger()
    {
        GameEntry.Log(LogCategory.Normal, "TestLogger start");
        //int iLen = 0;
        for (int i = 0; i < 400; ++i)
        {
            GameEntry.Logger.Write("我是一般Log:" + i.ToString(), LogType.Log);
            GameEntry.Logger.Write("我是警告Log:" + i.ToString(), LogType.Warning);
            GameEntry.Logger.Write("我是断言Log:" + i.ToString(), LogType.Assert);
            GameEntry.Logger.Write("我是错误Log:" + i.ToString(), LogType.Error);
            GameEntry.Logger.Write("我是异常Log:" + i.ToString(), LogType.Exception);
        }
        GameEntry.Log(LogCategory.Normal, "TestLogger end");
    }
    private void TestLog()
    {
        GameEntry.Log(LogCategory.Normal, "这是一个Normal测试日志 value:{0} {1}", "xx", 1);
        GameEntry.Log(LogCategory.Procedure, "这是一个Procedure测试日志 value:{0} {1}", "xx", 2);
        GameEntry.Log(LogCategory.Proto, "这是一个Proto测试日志 value:{0} {1}", "xx", 3);
        GameEntry.Log(LogCategory.Resource, "这是一个Resource测试日志 value:{0} {1}", "xx", 4);
    }
    public void OnTestStart()
    {
        //TestLog();
        //TestLogger();
    }
    public void OnTestUpdate()
    {
    }
}
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
打赏
0
0
0
0
1
分享
相关文章
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log、原理、写入过程;binlog与redolog区别、update语句的执行流程、两阶段提交、主从复制、三种日志的使用场景;查询日志、慢查询日志、错误日志等其他几类日志
140 35
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
Tomcat log日志解析
理解和解析Tomcat日志文件对于诊断和解决Web应用中的问题至关重要。通过分析 `catalina.out`、`localhost.log`、`localhost_access_log.*.txt`、`manager.log`和 `host-manager.log`等日志文件,可以快速定位和解决问题,确保Tomcat服务器的稳定运行。掌握这些日志解析技巧,可以显著提高运维和开发效率。
78 13
图解MySQL【日志】——Redo Log
Redo Log(重做日志)是数据库中用于记录数据页修改的物理日志,确保事务的持久性和一致性。其主要作用包括崩溃恢复、提高性能和保证事务一致性。Redo Log 通过先写日志的方式,在内存中缓存修改操作,并在适当时候刷入磁盘,减少随机写入带来的性能损耗。WAL(Write-Ahead Logging)技术的核心思想是先将修改操作记录到日志文件中,再择机写入磁盘,从而实现高效且安全的数据持久化。Redo Log 的持久化过程涉及 Redo Log Buffer 和不同刷盘时机的控制参数(如 `innodb_flush_log_at_trx_commit`),以平衡性能与数据安全性。
43 5
图解MySQL【日志】——Redo Log
简单聊聊MySQL的三大日志(Redo Log、Binlog和Undo Log)各有什么区别
在MySQL数据库管理中,理解Redo Log(重做日志)、Binlog(二进制日志)和Undo Log(回滚日志)至关重要。Redo Log确保数据持久性和崩溃恢复;Binlog用于主从复制和数据恢复,记录逻辑操作;Undo Log支持事务的原子性和隔离性,实现回滚与MVCC。三者协同工作,保障事务ACID特性。文章还详细解析了日志写入流程及可能的异常情况,帮助深入理解数据库日志机制。
图解MySQL【日志】——Undo Log
Undo Log(回滚日志)是 MySQL 中用于实现事务原子性和一致性的关键机制。在默认的自动提交模式下,MySQL 隐式开启事务,每条增删改语句都会记录到 Undo Log 中。其主要作用包括:
48 0
Spring Boot中的日志框架选择
在Spring Boot开发中,日志管理至关重要。常见的日志框架有Logback、Log4j2、Java Util Logging和Slf4j。选择合适的日志框架需考虑性能、灵活性、社区支持及集成配置。本文以Logback为例,演示了如何记录不同级别的日志消息,并强调合理配置日志框架对提升系统可靠性和开发效率的重要性。
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
1410 31
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
110 9

热门文章

最新文章