1 背景
我们大家都知道写日志是很重要的,但是要怎么写日志合适,什么节点该打日志,其实并没有人告诉我们。靠的是每一个各自的领悟能力,这里我们需要去完善这部分,让日志能传承,积累,发展下去。让我们(开发,测试,技术支持)一起知道一套规范,Follow一套规范。低成本,高效一起协助定位问题,提高软件的质量。
基于此,我们会疑惑,每次上报的问题,技术支持/测试 只有一个透传数据的任务,第一层接触的开发就需要去过滤,复现问题,确定问题应该找哪个部门来解决。借此引发,我们是否应该在日志的纬度能够去规避这个问题,让更多参与的人能直接看出问题是在哪里的?
2 日志规范
我们的日志里面有什么?
经过沟通,期望能统一 Android、iOS上日志的规范,让大家(开发、测试、技术支持)形成一个统一的规范,减少沟通和维护的成本
2.1 分析需求
期望日志能记录什么,能给我们带来什么样的内容?
- tag:可以用于标记系列的日志Id【可用于筛选出一个功能其流程是怎样产生的】
- Function: 函数名,具体日志是在哪里产生的
- line: 具体日志是在文件的哪一行产生的
- 当时软件、硬件环境是怎样的。到底遇到了什么问题?
- 问题是怎么产生的,应该找谁去解决问题
2.2 一个日志文件 开始与结束
目前的策略,采取的是一次APP进入到前台的时候,则会划分一个日志文件。可以简化日志的大小,也可以直接看到一次处于前台APP发生了什么事情。所有的日志将采取一个文件,这么做的一个好处,可以看到在时间维度上都发生了什么事情。而如果想要知道某一个功能具体的情况,可以通过 2.1 里所指的tag来划分出要的日志信息
2.3 应该写入什么
日志这部分是一个case by case的场景,无法一开始就能决定所有的日志要怎么打印才是对。那我们反思,什么信息是有用的:
- 环境信息
- 过程和出错日志,该找谁解决
2.3.1 环境信息
我们的研发过程,对于复现,或者发现是哪一个版本的固件才存在的问题,我们需要知道相关固件各个版本,软件版本,设备信息。此时可以使用日志将内容打印
2.3.2 过程和出错日志,该找谁解决
往往我们出现问题是某一个具体的功能,此时可以通过tag
来完成筛选一个功能的日志信息。那日志又应该怎么打印?
我们从(What,When,How)来思考问题:
- What:我们应该打印什么?此处我的经验告诉有几个地方可以打印:
- 功能流程触发,可以知道这个功能开始了
- 功能出错,可以知道当时出错的原因
出错这里会划分多个维度的:- 因为V1协议返回的异常【此时可以带上告知看日志的人,需要找哪个模块的固件定位】
- 因为状态校验不通过【此时可以带上告知看日志的人,需要找此功能的SDK研发定位】
- 因为当下的条件不满足引起无法触发功能【此时可能是上层调用的顺序问题,可以提出建议需要调用什么接口之后再使用此接口的建议】
- When:我们的日志要遵循一个规则,不能疯狂打印,这样会有打印的效率,建议只打印以下条件的
- 如果这个动作是一次性,只有用户驱动才会触发,可以打印
- 在满足条件1的情况下,出现判断错误的时候,需要打印
- How:对于流程过程,可以采取 info 等级的日志。对于出现异常,但是不影响流程的日志,使用warning。对于出现异常,但影响流程功能的采取error
以上我们打印出了一个功能的过程,与出错原因了。那还需要一个日志,那就是具体这个日志可以找谁解决问题。
这里我们将要求开发在打印出错定位的日志时,带上具体可能是谁引起的错误,(开发、测试、技术支持)应该找谁来解决这个问题。
2.3.3 日志等级的划分与作用
日志等级控制,在不同的配置环境下,打印不同等级的日志
对于日志部分,我们可以划分以下几个等级:
等级 | 作用 | Release环境 | Debug |
---|---|---|---|
fatal | 非常严重的问题,需要使用此等级来打印 | 可以 | 可以 |
error | 出现异常错误的等级 | 可以 | 可以 |
warning | 警告,虽然可以继续执行,但是建议消除 | 可以 | 可以 |
info | 打印相关信息 | 可以 | 可以 |
debug | 调试使用的等级 | 禁止 | 可以 |
verbose | 调试使用的等级 | 禁止 | 可以 |
2.3.4 一行日志的例子
上面讲了这么多,那一行日志应该是怎样?这里举个例子
1 | 20:19:30.0300 function:line [E][Camera_Shoot][Custom Information][Please find the SDK developer] |
一行的日志有以下的信息:
- 时间戳【例子中的 20:19:30.0300】:只需要 时,分,秒,毫秒的单位。哪年哪月那日由日志文件已经带上了,这里无需,可以简化日志量
- 具体的函数和行【例子中的 function:line】:给开发可以知道是在哪一行打印这个日志的。行数有时可以用于确定与出问题当时的代码是否一致
- 日志等级【例子中的 [E]】:这个日志是用来说明什么的,这块靠的更多是开发的sense。如果你明确要定位哪一个问题,可以通过第4点的tag,加上这个等级,可以直接筛选出一个功能所有的错误信息。比如例子可以筛选出
[E][Camera_Shoot]
- 功能的Tag【例子中的 [Camera_Shoot]】:可用于搜索一个功能的整个流程是怎么跑的
- 自定义内容【例子中的 [Custom Information]】:这块全由开发决定,主要是用于定位问题在哪里
- 建议问题可能要找谁解决【例子中的 [Please find the SDK developer]】:因为我们的日志是考虑 技术支持/测试 也可以参与进来指派问题给谁
可能有人会疑惑,那怎么保证第四点的tag一致?
这里就引发使用跨平台的方式来完成tag的定义,上层来传递枚举值,内部决定枚举对应的字符串内容是什么。这样能保证在不同平台一样的功能tag是一致的。
这里建议在写入日志方面采取:
- 尽量简洁,尽量能表达意思即可
- 避免内部自动持续疯狂打印同一个日志。非用户驱动的
3 快捷工具
3.1 使用tag划分日志
请按照一下的步骤完成筛选你要的日志部分:
- 安装 Visual Studio Code
- 安装 Visual Studio Code插件Filter Line
- 打开你想要从中筛选出来的完整日志文件(即夹杂各种信息)
- 使用快捷键 Command + Shift + P,搜索
- 输入你想要筛选日志行里面的目标关键词
- 即可得到你要的功能整个过程的日志信息