文章目录

  • 日志是什么?
  • 日志有什么用?
  • 问题诊断
  • 日志审计
  • 运维管理
  • 日志、大数据分析
  • 什么时候记录日志?
  • 系统初始化
  • 编程语言提示异常
  • 业务流程预期不符
  • 系统核心角色,组件关键动作
  • 第三方服务调用
  • 日志基本格式要求
  • 日志时间
  • 服务唯一标识
  • 日志级别
  • ERROR
  • WARN
  • INFO
  • DEBUG
  • DEBUG / INFO 的选择
  • WARN / ERROR 的选择
  • 强调ERROR报警
  • 线程名称
  • 日志记录器名称
  • 日志内容
  • opentracing 标识
  • biz 标识
  • 小技巧
  • 参数隔离


日志是什么?

日志是网络设备、系统及服务程序等,在运作时都会产生一个事件记录。

日志有什么用?

问题诊断

可以用日志来记录变量或者某一段逻辑。记录程序运行的流程,即程序运行了哪些代码,方便排查逻辑问题。
程序出异常或者出故障时快速的定位问题,方便后期解决问题。

日志审计

通过日志查询功能,快速分析访问行为,例如查询某个账户、某个对象、某个操作的操作记录。

运维管理

收集不同应用程序的日志(包括错误、访问日志、操作日志等)。
通过不同的日志库、机器组对应用程序进行集中式管理。
对不同日志进行处理。例如,访问日志进行流计算做实时监控;对操作日志进行索引、实时查询;对重要日志进行离线存档。

日志、大数据分析

记录用户的操作行为,用于大数据分析,比如监控、风控、推荐等等。当然,要记录哪些行为、操作,一般也是约定好的,因此,开发者主要是执行的角色。

什么时候记录日志?

系统初始化

系统或者服务的启动参数。核心模块或者组件初始化过程中往往依赖一些关键配置,根据参数不同会提供不一样的服务。务必在这里记录 INFO 日志,打印出参数以及启动完成态服务表述。

编程语言提示异常

如今各类主流的编程语言都包括异常机制,业务相关的流行框架有完整的异常模块。这类捕获的异常是系统告知开发人员需要加以关注的,是质量非常高的报错。应当适当记录日志,根据实际结合业务的情况使用 WARN 或者 ERROR 级别。

业务流程预期不符

除开平台以及编程语言异常之外,项目代码中结果与期望不符时也是日志场景之一,简单来说所有流程分支都可以加入考虑。取决于开发人员判断能否容忍情形发生。常见的合适场景包括外部参数不正确,数据处理问题导致返回码不在合理范围内等等。

系统核心角色,组件关键动作

系统中核心角色触发的业务动作是需要多加关注的,是衡量系统正常运行的重要指标,建议记录 INFO 级别日志,比如电商系统用户从登录到下单的整个流程;微服务各服务节点交互;核心数据表增删改;核心组件运行等等,如果日志频度高或者打印量特别大,可以提炼关键点 INFO 记录,其余酌情考虑 DEBUG 级别。

第三方服务调用

微服务架构体系中有一个重要的点就是第三方永远不可信,对于第三方服务远程调用建议打印请求和响应的参数,方便在和各个终端定位问题,不会因为第三方服务日志的缺失变得手足无措。

日志基本格式要求

日志的基本内容应包括

  1. 日志时间
  2. 服务唯一标识
  3. 日志级别
  4. 线程名称
  5. 日志记录器名称
  6. 日志信息
  7. biz标识别
  8. opentraceing标识

8项基本内容,1到6为必选项,7根据业务要求酌情添加,8根据服务架构,调用链路情况酌情添加。

日志时间

日志时间是日志产生的日期和时间,一般精确到毫秒。

yyyy-MM-dd HH:mm:ss.SSS

服务唯一标识

服务的唯一标识是为了解决日志统一采集后无法根据辨别的问题。
命名方式建议采取 xxx—server的方式,例如order—server。

日志级别

通常日志分为4个级别,我们在不同场景给日志不同的级别属性。

ERROR

ERROR是最高级别错误,反映系统发生了非常严重的故障,无法自动恢复到正常态工作,需要人工介入处理。系统需要将错误相关痕迹以及错误细节记录ERROR日志中,方便后续人工回溯解决。

WARN

WARN是低级别异常日志,反映系统在业务处理时触发了异常流程,但系统可恢复到正常态,下一次业务可以正常执行。但WARN级别问题需要开发人员给予足够关注,往往表示有参数校验问题或者程序逻辑缺陷,当功能逻辑走入异常逻辑时,应该考虑记录WARN日志。

INFO

INFO日志主要记录系统关键信息,旨在保留系统正常工作期间关键运行指标,开发人员可以将初始化系统配置、业务状态变化信息,或者用户业务流程中的核心处理记录到INFO日志中,方便日常运维工作以及错误回溯时上下文场景复现。

DEBUG

DEBUG日志是INFO日志的好帮手,开发人员可以将各类详细信息记录到DEBUG里,起到调试的作用,包括参数信息,调试细节信息,返回值信息等等。其他等级不方便显示的信息都可以通过DEBUG日志来记录。

DEBUG / INFO 的选择

DEBUG 级别比 INFO低,包含调试时更详细的了解系统运行状态的东西,比如变量的值等等,都可以输出到 DEBUG 日志里。 INFO 是在线日志默认的输出级别,反馈系统的当前状态给最终用户看的。输出的信息,应该对最终用户具有实际意义的。从功能角度上说,INFO输出的信息可以看作是软件产品的一部分,所以需要谨慎对待,不可随便输出。如果这条日志会被频繁打印或者大部分时间对于纠错起不到作用,就应当考虑下调为 DEBUG 级别。

  • 由于 DEBUG 日志打印量远大于INFO,出于性能的考虑,如果代码为核心代码,执行频率非常高,务必推敲日志设计是否合理,是否需要下调为 DEBUG 级别日志。
    注意日志的可读性,不妨在写完代码 review 这条日志是否通顺,能否提供真正有意义的信息。
WARN / ERROR 的选择

当方法或者功能处理过程中产生不符合预期结果或者有框架报错时可以考虑使用,常见问题处理方法包括:

  • 增加判断处理逻辑,尝试本地解决:增加逻辑判断吞掉报警永远是最优选择抛出异常,交给上层逻辑解决
  • 抛出异常,交给上层逻辑解决
  • 记录日志,报警提醒
  • 使用返回码包装错误做返回

一般来说,WARN级别不会报警,ERROR级别则会报警,ERROR级别的日志意味着系统中发生了非常严重的问题,必须有人马上处理,比如数据库不可用,系统的关键业务流程走不下去等等。ERROR级别要慎用,需区分问题的重要程度,只要有问题就error记录下来,会引发频繁报警。

强调ERROR报警
  • ERROR 级别的日志打印通常伴随报警通知。ERROR的报出应该伴随着业务功能受损,即上面提到的系统中发生了非常严重的问题,必须有人马上处理。

ERROR日志目标

  • 给处理者直接准确的信息。

线程名称

输出该日志的线程名称,一般在一个应用中一个同步请求由同一线程完成,输出线程名称可以在各个请求产生的日志中进行分类,便于分清当前请求上下文的日志。

日志记录器名称

日志记录器名称一般使用类名,日志文件中可以输出简单的类名即可,看实际情况是否需要使用包名和行号等信息。主要用于看到日志后到哪个类中去找这个日志输出,便于定位问题所在。

日志内容

所要打印的内容

opentracing 标识

在分布式应用中,用户的一个请求会调用若干个服务完成,这些服务可能还是嵌套调用的,因此完成一个请求的日志并不在一个应用的日志文件,而是分散在不同服务器上不同应用节点的日志文件中。该标识是为了串联一个请求在整个系统中的调用日志。

唯一字符串(trace id)

通过搜索 trace id 就可以查到这个 trace id 标识的请求在整个系统中流转(处理)过程中产生的所有日志。

biz 标识

在业务开发中,我们的日志都是和业务相关联的,有时候是需要根据用户或者业务做聚类的,因此一次请求如果可以通过某项标识做聚类的时候,可以将聚类标识打印到日志中。
例如:
用户标识(user id)业务标识(biz id)

小技巧

参数隔离

[] 进行参数隔离,日志的可读性更高。

举例,通过[]我们能够清楚的知道userid是什么。

order is paying with userId:[1000100001]