正确的打日志姿势

2023-10-27

前言

比较认同,转载一下

使用slf4j

  1. 使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
  2. 实现方式统一使用: Logback框架

什么时候应该打日志

  1. 当你遇到问题的时候,只能通过debug功能来确定问题,你应该考虑打日志,良好的系统,是可以通过日志进行问题定位的。
  2. 当你碰到if…else 或者 switch这样的分支时,要在分支的首行打印日志,用来确定进入了哪个分支
  3. 经常以功能为核心进行开发,你应该在提交代码前,可以确定通过日志可以看到整个流程

基本格式

必须使用参数化信息的方式:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);

对于debug日志,必须判断是否为debug级别后,才进行使用:

if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " +id + " symbol: " + symbol);
}

不要进行字符串拼接,那样会产生很多String对象,占用空间,影响性能。
反例(不要这么做):

logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

使用[]进行参数变量隔离

如有参数变量,应该写成如下写法:

logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);

这样的格式写法,可读性更好,对于排查问题更有帮助。

不同级别的使用

ERROR:

基本概念
影响到程序正常运行、当前请求正常运行的异常情况:

  1. 打开配置文件失败
  2. 所有第三方对接的异常(包括第三方返回错误码)
  3. 所有影响功能使用的异常,包括:SQLException和除了业务异常之外的所有异常(RuntimeException和Exception)

不应该出现的情况:

  1. 比如要使用Azure传图片,但是Azure未响应

如果有Throwable信息,需要记录完成的堆栈信息:

log.error(“获取用户[{}]的用户信息时出错”,userName,e);

说明

  1. 如果进行了抛出异常操作,请不要记录error日志,由最终处理方进行处理:
    反例(不要这么做):
try{
    ....
}catch(Exception ex){
  String errorMessage=String.format("Error while reading information of user [%s]",userName);
  logger.error(errorMessage,ex);
  throw new UserServiceException(errorMessage,ex);
}

WARN

基本概念
不应该出现但是不影响程序、当前请求正常运行的异常情况:

  1. 有容错机制的时候出现的错误情况
  2. 找不到配置文件,但是系统能自动创建配置文件

即将接近临界值的时候,例如:

  1. 缓存池占用达到警告线

业务异常的记录,比如:

  1. 当接口抛出业务异常时,应该记录此异常

INFO:

基本概念
系统运行信息

  1. Service方法中对于系统/业务状态的变更
  2. 主要逻辑中的分步骤

外部接口部分

  1. 客户端请求参数(REST/WS)
  2. 调用第三方时的调用参数和调用结果

说明

  1. 并不是所有的service都进行出入口打点记录,单一、简单service是没有意义的(job除外,job需要记录开始和结束,)。
    反例(不要这么做):
public List listByBaseType(Integer baseTypeId) {

    log.info("开始查询基地");
	BaseExample ex=new BaseExample();
	BaseExample.Criteria ctr = ex.createCriteria();
	ctr.andIsDeleteEqualTo(IsDelete.USE.getValue());
	Optionals.doIfPresent(baseTypeId, ctr::andBaseTypeIdEqualTo);
    log.info("查询基地结束");
	return baseRepository.selectByExample(ex);
}
  1. 对于复杂的业务逻辑,需要进行日志打点,以及埋点记录,比如电商系统中的下订单逻辑,以及OrderAction操作(业务状态变更)。
  2. 对于整个系统的提供出的接口(REST/WS),使用info记录入参
  3. 如果所有的service为SOA架构,那么可以看成是一个外部接口提供方,那么必须记录入参。
  4. 调用其他第三方服务时,所有的出参和入参是必须要记录的(因为你很难追溯第三方模块发生的问题)

DEBUG

基本概念

  1. 可以填写所有的想知道的相关信息(但不代表可以随便写,debug信息要有意义,最好有相关参数)
  2. 生产环境需要关闭DEBUG信息
  3. 如果在生产情况下需要开启DEBUG,需要使用开关进行管理,不能一直开启。

说明
如果代码中出现以下代码,可以进行优化:

//1. 获取用户基本薪资

//2. 获取用户休假情况

//3. 计算用户应得薪资

优化后的代码:

logger.debug("开始获取员工[{}] [{}]年基本薪资",employee,year);

logger.debug("获取员工[{}] [{}]年的基本薪资为[{}]",employee,year,basicSalary);
logger.debug("开始获取员工[{}] [{}]年[{}]月休假情况",employee,year,month);

logger.debug("员工[{}][{}]年[{}]月年假/病假/事假为[{}]/[{}]/[{}]",employee,year,month,annualLeaveDays,sickLeaveDays,noPayLeaveDays);
logger.debug("开始计算员工[{}][{}]年[{}]月应得薪资",employee,year,month);

logger.debug("员工[{}] [{}]年[{}]月应得薪资为[{}]",employee,year,month,actualSalary);

TRACE

基本概念
特别详细的系统运行完成信息,业务代码中,不要使用.(除非有特殊用意,否则请使用DEBUG级别替代)
规范示例说明

@Override
@Transactional
public void createUserAndBindMobile(@NotBlank String mobile, @NotNull User user) throws CreateConflictException{
    boolean debug = log.isDebugEnabled();
    if(debug){
        log.debug("开始创建用户并绑定手机号. args[mobile=[{}],user=[{}]]", mobile, LogObjects.toString(user));
    }
    try {
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        userRepository.insertSelective(user);
        if(debug){
            log.debug("创建用户信息成功. insertedUser=[{}]",LogObjects.toString(user));
        }
        UserMobileRelationship relationship = new UserMobileRelationship();
        relationship.setMobile(mobile);
        relationship.setOpenId(user.getOpenId());
        relationship.setCreateTime(new Date());
        relationship.setUpdateTime(new Date());
        userMobileRelationshipRepository.insertOnDuplicateKey(relationship);
        if(debug){
            log.debug("绑定手机成功. relationship=[{}]",LogObjects.toString(relationship));
        }
        log.info("创建用户并绑定手机号. userId=[{}],openId=[{}],mobile=[{}]",user.getId(),user.getOpenId(),mobile);
    }catch(DuplicateKeyException e){
        log.info("创建用户并绑定手机号失败,已存在相同的用户. openId=[{}],mobile=[{}]",user.getOpenId(),mobile);
        throw new CreateConflictException("创建用户发生冲突, openid=[%s]",user.getOpenId());
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正确的打日志姿势 的相关文章

  • 无论线程如何,对象是否总是能看到其最新的内部状态?

    假设我有一个带有简单整数计数变量的可运行对象 每次可运行对象运行时该变量都会递增 该对象的一个 实例被提交以在计划的执行程序服务中定期运行 class Counter implements Runnable private int coun
  • 在 String 值之后打印 int 值

    我有以下示例代码 int pay 80 int bonus 65 System out println pay bonus bonus pay 有人可以向我解释一下为什么我得到以下输出 145 6580 您的代码正在从左到右解释表达式 pa
  • 了解 netty 通道缓冲区和水印

    我正在尝试了解网络缓冲区和水印 作为一个测试用例 我有一个 netty 服务器 它向客户端写入数据 客户端被阻止 基本上每次读取之间有 10 秒的睡眠时间 在正常 I O 下 如果接收方被阻塞 TCP 发送方将受到限制 由于流量控制 发送速
  • 如何在 Android 中的 Chrome 或 Firefox 等特定浏览器的 Web 视图中加载应用程序

    我是 Android 新手 我正在做一个应用程序 我需要在平板电脑上的 Web 视图中加载现有的应用程序 在平板电脑中 当我使用 Web 视图加载应用程序时 我的应用程序将加载到默认浏览器中 如何在平板电脑上的 Web 视图中的特定浏览器
  • 垂直 ViewPager 中的动画

    我需要垂直制作这个动画ViewPager https www youtube com watch v wuE 4jjnp3g https www youtube com watch v wuE 4jjnp3g 这是我到目前为止所尝试的 vi
  • 如何从 Java 访问 Windows 设备管理器中的信息?

    我有一个串行 USB 设备 并且其中多个设备可以连接到计算机 我需要查询和检索设备连接到的 COM 端口列表 在 Windows 设备管理器中 您可以获得当前连接的设备的 COM 端口 友好名称 该列表是动态的 从注册表中读取不工作 htt
  • 获取Android库中的上下文

    我正在编写一个 Android 应用程序 它的一些功能封装在内部库中 但是 要使此功能发挥作用 库需要一个应用程序上下文的实例 为图书馆提供这种上下文的最佳方式是什么 我看到了一些选择 但没有一个有吸引力 Have my library c
  • 使用 Jena 查询维基数据

    目前 Wikidata 有一个 SPARQL 端点 https query wikidata org https query wikidata org 我想使用 Jena 3 0 1 查询此网站 我使用以下代码 但收到错误消息 端点返回的
  • 对对象集合进行排序[重复]

    这个问题在这里已经有答案了 如果我有一个简单的字符串列表 List
  • 如何自动转换十六进制代码以将其用作 Java 中的 byte[]?

    我这里有很多十六进制代码 我想将它们放入 Java 中 而不需要向每个实体附加 0x 喜欢 0102FFAB 和我必须执行以下操作 byte test 0x01 0x02 0xFF 0xAB 我有很多很长的十六进制代码 有什么办法可以自动做
  • Java 中如何验证字符串的格式是否正确

    我目前正在用 Java 编写一个验证方法来检查字符串是否是要更改为日期的几种不同格式之一 我希望它接受的格式如下 MM DD YY M DD YY MM D YY 和 M D YY 我正在测试第一种格式 每次它都告诉我它无效 即使我输入了有
  • 膨胀类 android.support.design.widget.NavigationView 时出错

    我按照 NavigationView 的教程进行操作 但无法解决此错误消息 Error inflating class android support design widget NavigationView 教程链接 https www
  • 避免 @Secured 注释的重复值

    我正在尝试使用以下方法来保护我的服务方法 Secured如下 public interface IUserService Secured ROLE ROLE1 ROLE ROLE2 ResponseEntity saveUser Creat
  • 使用 Guava Ordering 对对象列表进行多条件排序

    我有一个类无法实现可比较 但需要根据 2 个字段进行排序 我怎样才能用番石榴实现这一目标 假设班级是 class X String stringValue java util Date dateValue 我有一个清单 List
  • Hibernate 标准接受 %% 值

    我正在使用下面的 Hibernate 代码来过滤workFlowName crt add Restrictions like workFlowName workFlow MatchMode ANYWHERE crt is the crite
  • Spring - 如何在不匹配列名的情况下使用 BeanPropertyRowMapper

    我正在开发一个应用程序 该应用程序已使用行映射器从纯 JDBC 转换为 Spring 模板 我遇到的问题是数据库中的列与属性名称不匹配 这阻止我使用BeanPropertyRowMapper容易地 我看到一些关于在查询中使用别名的帖子 这会
  • Proguard 正在破坏我的清洁度。 Gson 和泛型

    我有一个从持久性加载信息的函数 我只是以一种非常简单的方式告诉它的类型 该类称为SharedPreferencesHelper kt所以它是一个真正的生活问题解决者 fun
  • Firebase:用户注册后如何进行电话号码验证?

    所以我知道我可以使用电子邮件验证或电话号码验证 但我想做的是在用户注册或登录后进行电话号码验证 如何连接这两种身份验证方法 最后 Firebase中是否有一个函数可以检查用户是否通过电话号码验证 谢谢 即使用户已通过身份验证 您仍然可以使用
  • Android ClassNotFoundException:在路径上找不到类

    10 22 15 29 40 897 E AndroidRuntime 2561 FATAL EXCEPTION main 10 22 15 29 40 897 E AndroidRuntime 2561 java lang Runtime
  • 如何使用socket.io发送图像文件(二进制数据)?

    我无法从以下位置发送数据Android Client to NodeJS Server I use Socket IO 客户端 https github com socketio socket io client java我的客户端中的ja

随机推荐

  • python内点法_最优化问题(三) 之 外点法(罚函数法)

    1 基本概念 罚函数法又称乘子法 是将约束优化问题转换为无约束最优化问题的方法之一 其基本思想就是通过在原始的目标函数中添加一个障碍函数 也可以理解成惩罚函数 来代替约束条件中的不等式约束 如果当前解不满足约束条件 就在目标项上加上一个正向
  • Web前端——CSS复习(3.27-3.31)

    1 渐变 1 什么是渐变 渐变 指的是两种或多种颜色之间的平滑过渡 aa 渐变可指定多个中间颜色值 色标 bb 渐变可以用在任何适用背景图片的地方 线性渐变 径向渐变 重复渐变 2 渐变语法 在CSS3中使用background image
  • leetcode shell题解

    195 Tenth Line print just the 10th line of a file sed n 10 10p file txt 194 Transpose File For example if file txt has t
  • 主流编程语言介绍

    目录 前言 一 编程语言作用 1 1 Python 1 2 Java 1 3 JavaScript 1 4 Go 1 5 PHP 二 Python和PHP学习网站 2 1 菜鸟教程 2 2 W3school 总结 前言 主流的编程语言有很多
  • 流图(程序图)表示程序的控制流——>McCabe方法度量程序空间复杂度

    McCabe方法 McCabe方法根据程序控制流的复杂程度定量度量程序的复杂程度 这样度量出的结果称为程序的环形复杂度 为了突出表现程序的控制流 人们通常使用流图 也称程序图 1 流图 所谓流图实质上是 退化了的 程序流程图 它仅仅描绘程序
  • OpenCDA代码学习笔记(1)——CARLA-SUMO联合仿真demo

    本文主要记录一下自己最近学习开源项目OpenCDA代码的笔记 简而言之 该项目用Python实现了全栈式自动驾驶算法的开发 也实现了CARLA SUMO的联合仿真 该部分参考了CARLA官方给出的联合仿真实例代码 学习该项目代码的主要目的是
  • 超详细Python安装教程

    Python官网地址 https www python org 1 进入官网 点击download选择系统 2 点击最新的Python版本 3 进入新页面 下拉至Files处 选择系统位数的执行运行程序 我的系统是64位 4 点击安装文件
  • 微信小程序开发笔记—获取颜色十六进制值

    获取颜色十六进制值 十六进制颜色代码是在软件中设定颜色的代码 可以先查询以下目标颜色的RGB值 然后将三个值均转换成十六进制即是目标颜色的十六进制值 转换这里可以使用电脑计算器中的程序员模式 比如目标颜色为香芋紫 查询得知该颜色的RGB值分
  • C++57个入门知识点_55 函数模板(template<typename T>;T GetMin(T a, T b){};函数模板定义;隐式实例化;显式实例化;函数模板特例;实例化后模板才有效)

    本篇主要讨论函数模板的相关知识点 前言 typename 是一个C 程序设计语言中的关键字 当用于泛型编程时是另一术语 class 的同义词 这个关键字用于指出模板声明 或定义 中的非独立名称 dependent names 是类型名 而非
  • 从 BBR 失速到带宽探测

    看一下 pacing 流失速的成因 一段时间收不到 ack 丢了 ack 自时钟 cwnd 将耗尽 bbr 虽有 cwnd gain 上图没有表现 但在该 cwnd gain 下不依赖 ack 持续坚持发送多久取决于 cwnd gain 的
  • hashmap的常见静态属性和方法

    1 hashmap的常见的静态属性 hashmap默认的容器大小 16 static final int DEFAULT INITIAL CAPACITY 1 lt lt 4 hashmap默认最大的容器大小 超过不再扩容 static f
  • MySQL存储过程调试工具dbForge Studio for MySQL

    https blog csdn net zhanghongzheng3213 article details 51462113 https blog csdn net ggjlvzjy article details 49069569 ut
  • pytorch【生成自己的数据集】

    文章目录 一 导入相关的库 二 生成数据集 定义一个创建数据集的函数 三 创建我们分类数据集 定义一个创建数据集的函数 一 导入相关的库 import skimage from skimage import io 用来导入图片 import
  • vue项目全局去掉网页滚动条

    在App vue里增加以下样式
  • python包相对导入导入上层文件夹包功能使用

    python导入当前文件夹中的包非常简单 但是导入上层文件夹的包就比较困难了 不过还好python解释器给出了包相对导入功能 但是与平常的相对目录写法不太一样 新手比较难以发现 以下为对python官方文档的装载 给定以下的包布局结构 pa
  • keil5仿真错误:Encountered an improper argument 原因及解决办法

    报错如图 现象 仿真结束 退出仿真时报错 无法正常关闭keil软件 只能通过任务管理器强制结束进程关闭 解决办法 清除所有断点再关闭
  • 基于Java基础的家庭收支记账软件

    文章目录 前言 一 前期准备 二 整体功能 三 功能模块 四 功能浅谈 1 AccountInfo 类 2 收支明细 3 登记收入 支出 4 查询账单 五 收获 六 总结 前言 学习完Java基础之后 狗子我便在网上 尚硅谷 寻找了这个练手
  • [力扣刷题总结](字典树篇)

    文章目录 字典树 字典树的概念 字典树的功能 字典树的实现及代码实现 208 实现 Trie 前缀树 解法1 实现Trie 472 连接词 解法1 字典树 DFS 820 单词的压缩编码 解法1 字典树 字典树 字典树的概念 本小节主要参考
  • 讲讲BW/4 HANA和BW on HANA的区别

    前言部分 大家可以关注我的公众号 公众号里的排版更好 阅读更舒适 正文部分 很多人知道BW on HANA BO on HANA 但却不太了解BW 4 HANA 这篇文章我们就来简单讲讲区别 从BW onHANA 7 3开始 直到BW在HA
  • 正确的打日志姿势

    前言 比较认同 转载一下 使用slf4j 使用门面模式的日志框架 有利于维护和各个类的日志处理方式统一 实现方式统一使用 Logback框架 什么时候应该打日志 当你遇到问题的时候 只能通过debug功能来确定问题 你应该考虑打日志 良好的