日志规范

1 背景

我们大家都知道写日志是很重要的,但是要怎么写日志合适,什么节点该打日志,其实并没有人告诉我们。靠的是每一个各自的领悟能力,这里我们需要去完善这部分,让日志能传承,积累,发展下去。让我们(开发,测试,技术支持)一起知道一套规范,Follow一套规范。低成本,高效一起协助定位问题,提高软件的质量。

基于此,我们会疑惑,每次上报的问题,技术支持/测试 只有一个透传数据的任务,第一层接触的开发就需要去过滤,复现问题,确定问题应该找哪个部门来解决。借此引发,我们是否应该在日志的纬度能够去规避这个问题,让更多参与的人能直接看出问题是在哪里的?

2 日志规范

我们的日志里面有什么?
经过沟通,期望能统一 Android、iOS上日志的规范,让大家(开发、测试、技术支持)形成一个统一的规范,减少沟通和维护的成本

2.1 分析需求

期望日志能记录什么,能给我们带来什么样的内容?

  1. tag:可以用于标记系列的日志Id【可用于筛选出一个功能其流程是怎样产生的】
  2. Function: 函数名,具体日志是在哪里产生的
  3. line: 具体日志是在文件的哪一行产生的
  4. 当时软件、硬件环境是怎样的。到底遇到了什么问题?
  5. 问题是怎么产生的,应该找谁去解决问题

2.2 一个日志文件 开始与结束

目前的策略,采取的是一次APP进入到前台的时候,则会划分一个日志文件。可以简化日志的大小,也可以直接看到一次处于前台APP发生了什么事情。所有的日志将采取一个文件,这么做的一个好处,可以看到在时间维度上都发生了什么事情。而如果想要知道某一个功能具体的情况,可以通过 2.1 里所指的tag来划分出要的日志信息

2.3 应该写入什么

日志这部分是一个case by case的场景,无法一开始就能决定所有的日志要怎么打印才是对。那我们反思,什么信息是有用的:

  1. 环境信息
  2. 过程和出错日志,该找谁解决

2.3.1 环境信息

我们的研发过程,对于复现,或者发现是哪一个版本的固件才存在的问题,我们需要知道相关固件各个版本,软件版本,设备信息。此时可以使用日志将内容打印

2.3.2 过程和出错日志,该找谁解决

往往我们出现问题是某一个具体的功能,此时可以通过tag来完成筛选一个功能的日志信息。那日志又应该怎么打印?

我们从(What,When,How)来思考问题:

  1. What:我们应该打印什么?此处我的经验告诉有几个地方可以打印:
    1. 功能流程触发,可以知道这个功能开始了
    2. 功能出错,可以知道当时出错的原因
      出错这里会划分多个维度的:
      1. 因为V1协议返回的异常【此时可以带上告知看日志的人,需要找哪个模块的固件定位】
      2. 因为状态校验不通过【此时可以带上告知看日志的人,需要找此功能的SDK研发定位】
      3. 因为当下的条件不满足引起无法触发功能【此时可能是上层调用的顺序问题,可以提出建议需要调用什么接口之后再使用此接口的建议】
  2. When:我们的日志要遵循一个规则,不能疯狂打印,这样会有打印的效率,建议只打印以下条件的
    1. 如果这个动作是一次性,只有用户驱动才会触发,可以打印
    2. 在满足条件1的情况下,出现判断错误的时候,需要打印
  3. 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]

一行的日志有以下的信息:

  1. 时间戳【例子中的 20:19:30.0300】:只需要 时,分,秒,毫秒的单位。哪年哪月那日由日志文件已经带上了,这里无需,可以简化日志量
  2. 具体的函数和行【例子中的 function:line】:给开发可以知道是在哪一行打印这个日志的。行数有时可以用于确定与出问题当时的代码是否一致
  3. 日志等级【例子中的 [E]】:这个日志是用来说明什么的,这块靠的更多是开发的sense。如果你明确要定位哪一个问题,可以通过第4点的tag,加上这个等级,可以直接筛选出一个功能所有的错误信息。比如例子可以筛选出 [E][Camera_Shoot]
  4. 功能的Tag【例子中的 [Camera_Shoot]】:可用于搜索一个功能的整个流程是怎么跑的
  5. 自定义内容【例子中的 [Custom Information]】:这块全由开发决定,主要是用于定位问题在哪里
  6. 建议问题可能要找谁解决【例子中的 [Please find the SDK developer]】:因为我们的日志是考虑 技术支持/测试 也可以参与进来指派问题给谁

3 快捷工具

3.1 使用tag划分日志

请按照一下的步骤完成筛选你要的日志部分:

  1. 安装 Visual Studio Code
  2. 安装 Visual Studio Code插件Filter Line
  3. 打开你想要从中筛选出来的完整日志文件(即夹杂各种信息)
  4. 使用快捷键 Command + Shift + P,搜索
  5. 输入你想要筛选日志行里面的目标关键词
  6. 即可得到你要的功能整个过程的日志信息