关于如何设计打印日志的一些思考

1.本文概述

(简单介绍一下这个规范到底是怎么样的,方便读者能够第一时间了解本文)
阅读前,请先理解,这个仅是个人理解,有错误或者不恰当的地方,欢迎指正

本文共分为三个部分,概述,设计原则,设计方法。
设计原则,将阐述为什么要打日志,什么样的日志是好的。说明一些原则性的通用原则,主要是基于一些宏观的角度进行日志的设计。
设计方法,则将从宏观走向微观,将会从细节入手,体系化的讲述该怎么打印日志。
希望通过两部分的介绍能够完整的形成适合计费的日志打印规范
在这里插入图片描述

2.日志设计原则

(简述我们该怎么设计日志,说几条总领的纲领,说一下,笔者现在公司日志存在的问题,主要说一下,日志也是需要设计的,日志的重要性)

a. 打印日志的目的

日志一般会在三个地方进行使用:开发debug调用,服务运行状态监控,以及线上客诉问题排查。根据使用场景的不同,日志需求也不一样
开发调用日志要求,详细记录每个流程的相关数据,且会经常性的删减。服务运行日志,则要求我们详细记录服务的运行状态参数,对于启动状态,运行过程都进行覆盖监控。而客诉问题,则主要是通过代码埋点业务属性进行的。
在我们的开发过程中,开发日志经常性的会删减,然后发布。在现有的taf发布方式下,可能一个问题会多次增减日志进行问题定位,这种方式大大的增加我们开发的相关的成本,所以开发日志推荐通过 Arthas(!!!大力推荐) 通过该工具包,可实时查看某个切面的数据情况。所以本文不在阐述开发日志的相关问题

b. 什么样的日志是好的日志?

回到我们日志的目的描述,一个好的日志应该可以让我们仅通过观察日志即可了解服务运行状态和快速查找问题,而无需进一步了解服务代码才可知晓日志含义。其关键点就是打破服务壁垒,让任何人都在自己不了解的服务中高效使用日志。
通过调研文档, 不难发现,目前的我司的日志打印还处于各自为政,盘综复杂的情况。简单描述,就是主要以下几个问题:

  • 日志阅读困难,需要结合服务代码,极大的拖延了日志的排查速度
    在这里插入图片描述
    当我们查看该日志的时候,首先面临的问题就是,各个参数到底是什么?我们需要打开服务代码,通过查找日志打印位置,确定各个参数打印顺序(如果代码中有注释的话,还可大致了解每个属性的含义,如果没有,则大致含义都只能靠个人推测)。此外,寻找某个参数,还需要在数一数个数,过程相当困难痛苦。
  • 日志文档分类,各自为政,没有可统一的分类范式
    在这里插入图片描述
  • 部分日志过大,导致排查速度过慢
    在这里插入图片描述
  • 存在无意义日志打印

c.该怎么打印好日志呢?

总结起来就一句话,日志也需要有设计。目前,我司的日志打印,通常情况是想怎么打就怎么打,没有设计,也没有评审。完全根据开发者的个人喜好决定日志的打印。在这种情况下的日志,自然就拥有较高的服务壁垒,极大程度上依赖个人对服务的熟悉程度。
下面将会阐述,日志设计原则

  • 原则一:系统技术方案设计,应包括日志设计。
    当我们进行技术方案设计评审的时候,不仅需要考虑到代码逻辑,还需要考虑日志应打印什么东西,我们需要通过日志解决什么问题。
    我们主要要明确,基于业务场景下,我们在现有日志中,我们在什么场景下,会用到日志,解决该场景我们的日志需要有什么内容。通过这样得到我们需要的日志要求。
    在这里插入图片描述
    简单来讲,就是我们去总结,我们都会遇到什么业务场景,每个业务场景需要还说什么数据去解决,最后将重复的数据需求总结,划分日志内容。
  • 原则二:通过流程图,设计日志打印位置
    当我们在上述过程中,确定了我们都需要什么日志后,还存在的问题是我们改在代码的什么地方记录这些日志呢?
    这就需要我们通过流程图来进行日志位置的定位。以笔者之前编写的一个的过期红点提醒功能为例
    在这里插入图片描述

3.日志设计方法

(怎么样具体的设计日志,顺带包括相关的日志规范)
通过上述宏观角度的说明,大家应该可以明确,一个系统,我们需要打什么日志,在什么地方打日志。但我们还差一个更为重要的东西,就是这个日志该长什么样?回到这个问题,只有日志长得一样了,形成了相关的规范,我们才可以打破服务壁垒,让每个人都可以直接读懂日志,看出问题。
所以该部分将从微观角度,阐述我们的日志要打成什么样,怎么打。

a. 日志分类

常规日志分类,是通过日志级别进行分类的,比如info,error,debug等日志分类。笔者日志分类设计中,也参照这个分类,但存在些许不同
一共四类日志,五种具体分类,其中业务日志中下分为info,与warn级别的日志

业务日志接口日志启动日志错误日志
info、warninfoinfoerror

【必须】各自的命名规则:
<> 标识必须,[ ]标识如果有就加上
业务info日志:<服务名称><业务标识名称>info[日志下标].log.<时间>
业务warn日志:<服务名称>
<业务标识名称>warn[日志下标].log.<时间>
接口日志:<服务名称>_[接口名]access[日志下标].log.<时间>
启动日志:<服务名称>startup[日志下标].log.<时间>
错误日志:<服务名称>error[日志下标].log.<时间>

b. 日志大小与保存时间

大家可以看这样这样一个例子
在这里插入图片描述
该日志文件的大小,已经达到了两百多G的大小,对于这样大小的日志来讲,如果我们想要查询到自己想要的日志内容,无疑需要跑很久的脚本内容。所以我们需要规定单个日志的大小内容
【必须】日志大小规定:初步规定单个日志最大为1G,超过则要通过日志下标进行划分
举例:
服务名_error_2.log.2022-06-24
服务名_error.log.2022-06-24

【推荐】日志保留时间,初步设计为15天,但特殊情况下,可对部分日志保留时间进行延长

c. 日志打印内容详解

i. 启动日志

目前计费服务启动的相关信息,并没有单独打印,而是放在的了info日志中,同时,大多数情况,并没有对数据库,缓存,redis等中间件进行确活确认。所以启动日志的主要目标是:在服务发布的时候,对服务的各项状态进行记录,确保发布出现问题的及时感知
启动日志名:<服务名称>startup[日志下标].log.<时间>

  • 启动日志在什么地方打印?
    目前,我司的各项服务都配置了监听器或者启动类,用以加载各类配置
    【必须】启动日志打印在服务启动类的最后
  • 【必须】启动类打印的具体内容顺序:
    1. 开关配置
    2. 业务配置
    3. 数据库配置
    4. 缓存配置
    5. redis配置
    6. cmq配置
    7. 其他中间件配置
    8. 数据库确活
    9. redis确活
    10. 缓存确活
    11. cmq确活
    12. 其他中间件确活
  • 【必须】日志打印格式
配置打印:
<ip> <时间> INFO server start up :
    switch config : {<开关名>:<开关内容>,......}
    business config : {<业务配置名>:<业务配置内容>,......}
    databases config : {<数据库配置名>:<数据库配置内容>,......}
    cache config : {<缓存配置名>:<缓存配置内容>,......}
    redis config : {<redis配置名>:<redis配置内容>,......}
    cmq config : {<cmq配置名>:<cmq配置内容>,......}
    ...........
config end 

确活日志打印:
<ip> <时间> INFO server confirming start:
    databases:{<数据库名>:<是否存活>,.......}
    cache:{<缓存名>:<是否存活>,.......}
    redis:{<redis名>:<是否存活>,.......}
    cmq:{<cmq名>:<是否存活>,.......}
    .............
server confirming end

ii. 错误日志

错误日志的原则是:凡打印出来的,都是非设计预设的问题。简单解释就是,error日志中打印出来的东西,都是需要我们去处理的,而不是一些设计出现的业务错误。
举两个例子:
在这里插入图片描述
在这里插入图片描述
这串代码的逻辑是,先插入,如果插入失败,则更新
如果插入失败,数据库报错,这种错误,是属于设计时,存在的问题,则不应该放在error日志中,应该放在warn日志中
另一个例子

这个日志是验签失败的报错,但这个错误是属于业务错误,跟系统无关,是在设计中的错误。所以也不应该打印在error日志中,而是放在warn日志中。

  • error日志在什么地方打印?
    【必须】error日志必须打印在try catch的catch中
  • error日志的打印内容
    • 【必须】error只打印非设计错误(例子在上面)
    • 【必须】一个请求的错误,仅打印一条,不能一个错误分开,打印多条信息
      在这里插入图片描述
      如图,一个错误却分成了两条,同时一条堆栈信息没有说明文字
    • 【必须】error的内容由错误说明,错误信息以及错误堆栈信息组成
      错误说明:由开发者自行编写,主要是为了说明该错误出现什么地方,是为什么出现的。
      错误信息以及错误堆栈信息:e.getMessage()
  • 【必须】error日志打印格式
<ip> <时间> ERROR <错误说明>|<错误信息>
        <错误堆栈信息>
iii. 接口日志

接口日志会比较简单,总的来说就是在作为主调或者被调的时候,打印出参,入参,便于排查问题。但需要注意的是,如果部分接口调用大,参数内容多,需要谨慎考虑打印内容,能不能在不影响信息完整性的情况下, 少打部分参数。

  • 接口日志在什么地方打印?
    【必须】接口日志打印在jce接口处以及调用其他服务处

  • 接口日志记录什么内容?
    【必须】接口入参,出参,但需要根据实际情况对入参,出参进行处理,减少日志长度大小
    举例:

    比如该日志是记录档位拉取内容结果的,我们可以记录返回了什么档位,但部分无意义属性就可以不用打出来,比如companyName等通用的日志信息

  • 【必须】接口日志格式(出参入参,打印json格式)

<ip> <时间> INFO <接口名>|{入参一},{入参二},{入参三}|{出参一},{出参二}
IV.业务info日志

主要收集业务逻辑信息,比如消费时候,对扣减金额,明细单过滤等业务逻辑信息进行打印。是可能遇到的最多的日志类型。所以日志名为

<服务名称>_<业务标识名称>info[日志下标].log.<时间>

可在同一个服务中,根据个人需求,填入不同的业务标识名称,将各个日志输出到不同的日志中。

  • 日志打印在什么地方?
    通过 目录 2.c. 的原则二,确定打印在什么地方
  • 日志打印什么内容
    通过 目录 2.c. 的原则一,确定打印什么内容
  • 日志打印格式:
    【必须】日志主要采用k-v值的方式进行打印,可直接通过日志即可找到相关属性问题,无需打开服务代码
<ip> <时间> INFO <业务说明>{K:V},{K:V},{K:V}
v. 业务warn日志

主要收集业务容错信息,比如参数校验没通过,数据查询结果为空,还有错误码中的各种业务逻辑错误都可进行打印。

  • 日志打印在什么地方?
    【推荐】 业务warn日志一般打印在 if 语句中。绝大部分情况都是因为某些操作不符合正常情况情况所以通过if判断进行处理

  • 【推荐】 日志打印什么内容
    主要有参数校验没通过,数据查询为空,数据库防重校验等

  • 日志打印格式
    【必须】打印的主要格式还是K-V值,通过说明描述,简述发生了什么,然后选择关键属性打印K-V值

<ip> <时间> WARN <说明描述>{K:V},{K:V},{K:V}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值