zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【项目实战】关于日志,你需要了解这些

项目日志 实战 关于 了解 需要 这些
2023-09-14 09:04:55 时间

一、日志框架入门介绍

【项目实战】一文说完日志开发框架汇总介绍

二、日志输出时间(何时输出)

2.1 系统初始化:

系统启动参数、环境变量

2.2 预期外的错误:

异常发生时,要有详尽记录,并通知相关人员介入处理,第一时间作出响应,因为这种错误已经影响系统的正常使用

2.3 可预期的异常:

这类异常应该有效记录起来,通过警告方式反馈给相关人员加以关注,避免频繁发生,最终演化为不可控的错误。

2.4 关键操作:

增删改

2.5 函数:

函数出入口,重点关注入口

2.6 核心业务操作:

核心或者逻辑复杂的代码,建议添加详细的注释,以及较详细的日志。

2.7 流程分支:

在关键代码流程分支上打印日志。

2.8 调用外部接口:

在调用外部接口的时候,需要打印请求参数、响应值相关信息。

三、日志级别

软件中总免不了要使用诸如 Log4net, Log4j, Tracer 等东东来写日志
不管用什么,这些东东大多是大同小异的,一般都提供了以下5种日志级别:

3.1 fatal:致命日志

所谓Fatal,那就是相当严重的了,可以肯定这种错误已经无法修复,并且如果系统继续运行下去的话,可以肯定必然会越来越乱。这时候采取的最好的措施不是试图将系统状态恢复到正常,而是尽可能地保留系统有效数据并停止运行。

3.2 error:错误日志

  • 指比较严重的错误,对正常业务有影响,需要运维配置监控的;
  • 该级别的错误也需要马上被处理,但是紧急程度要低于fatal级别。
  • error应该尽量详细记录。
  • 可以进行一些修复性的工作,但无法确定系统会正常的工作下去,系统在以后的某个阶段,很可能会因为当前的这个问题,导致一个无法修复的错误(例如宕机),但也可能一直工作到停止也不出现严重问题。

3.3 warn:警告日志

  • 一般的错误,对业务影响不大,但是需要开发关注;
  • 该级别日志表示系统可能出现问题,也可能没有。
  • 可以使用 warn 日志级别来记录用户输入参数错误的情况
  • 此时可进行一些修复性工作,应该还可以把系统恢复到正常状态中来,系统应该可以继续运行下去。

3.4 info:信息日志

  • 记录排查问题的关键信息,如调用时间、出参入参等等;
  • 该级别日志记录系统的正常运行状态,通过查看info级别的日志,可以很快地对系统中出现的 warn,error,fatal错误进行定位。
  • 可以将初始化系统配置、业务状态变化信息,或者用户业务流程中的核心处理记录到info日志中,方便日常运维工作以及错误回溯时上下文场景复现。
  • 这个应该用来反馈系统的当前状态给最终用户的,所以,在这里输出的信息,应该对最终用户具有实际意义,也就是最终用户要能够看得明白是什么意思才行。从某种角度上说,Info 输出的信息可以看作是软件产品的一部分(就像那些交互界面上的文字一样),所以需要谨慎对待,不可随便。

3.5 debug:调试日志

  • 用于开发DEBUG的,关键逻辑里面的运行时数据;
  • 该级别日志的主要作用是对系统每一步的运行状态进行精确的记录。
  • 可以将各类详细信息记录到DEBUG里,起到调试的作用,包括参数信息、调试细节信息、返回值信息等
  • 级别最低,一般的来说,在系统实际运行过程中,一般都是不输出的。
  • 因此这个级别的信息,可以随意的使用,任何觉得有利于在调试时更详细的了解系统运行状态的东东,比如变量的值等等,都输出来看看也无妨。当然,在每一个 Debug 调用之前,一定要加上 If 判断。

四、日志内容

4.1 推荐使用英文内容

推荐输出英文日志内容,作用如下:

  1. 避免出现日志乱码;
  2. 使用ELK查询日志更方便

4.2 参数占位,唯一标识在前

  1. 禁止使用+操作符进行字符串的拼接,因为有一定的性能损耗,建议使用{}占位符;
  2. 建议将唯一标识放在日志内容前,如:userId、VIN、SN、deviceId等唯一标识,有利于快速定位log

4.3 异常打印

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} [${project.name}-${app.name}]
[%thread]%-5level %logger - %msg%n
</pattern>
</encoder>
</appender>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger =LoggerFactory.getLogger(Person.class);
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Person {}
log.info("{}:Processing trade with , symbol : {} ", id, symbol);
log.info("{}:loginOrLogoutLogList param={}", userId, param);

4.4 禁止做这些

4.4.1 禁止使用e.printStackTrace();

try {
    // 业务代码处理
} catch (Exception e) {
    e.printStackTrace(); //不要使用e.printStackTrace();
}

4.4.2 异常日志不要只打印一半;

try {
    //业务代码处理
} catch (Exception e) {
    // 错误
    LOG.error('你的程序有异常啦', e.getMessage()); //异常日志不要只打印一半;
}

4.4.3 不要只是一句错误提示;

try {
    //业务代码处理
} catch (Exception e) {
    // 错误
    LOG.error('你的程序有异常啦'); //不要只是一句错误提示;
}

try {
    // 业务代码处理
} catch (Exception e) {
    log.error("Person study errer,param={},e={}", param, e);
}

4.4.4 不要既打印日志,又抛出异常

try {
    //业务代码处理
} catch (Exception e) {
    // 错误
    LOG.error('你的程序有异常啦'); //不要只是一句错误提示;
    throw .new Exception("异常信息");
}

4.4.5 重复日志

避免重复打印日志,会浪费磁盘空间。
如有一行日志清楚表达了意思,避免再冗余打印;

if (user.isVip()) {
    log.info("该用户是会员,Id:{}", user, getUserId());
    //冗余,可以跟前面的日志合并一起
    log.info("开始处理会员逻辑,id:{}", user, getUserId());
    //会员逻辑
} else {
    //非会员逻辑
}

4.6 禁止输出的信息

  1. 禁止在日志中输出一些敏感信息,
    例如用户密码,身份证、手机号、银行卡、姓名、住址、邮箱等
    如需要可以考虑掩码脱敏,以及要保持编码的一致
  2. 禁止使用System.out.println(“xxxxxxx”)语句;
  3. 禁止使用e.printStackTrace();
  4. 禁止无意义打印,如连续的等号、星号或数字:***、=======、-------等
  5. 禁止循环打印Log
  6. 避免打印过长的日志内容:如列表、大json、大对象、数据库内容、天气详细信息、新闻列表等

五、日志格式

日志应当包括基本的信息:如

  • 当前时间戳(一般毫秒精确度)
  • 日志级别
  • 线程名字

六、日志脱敏方案

日志里的敏感信息还在打明文?3 种日志脱敏方案任你选
https://blog.csdn.net/JiuQianWan/article/details/127020281