本文来源:http://t.cn/E9BkD7a

使用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);

说明

如果进行了抛出异常操作,请不要记录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);
}

2. 对于复杂的业务逻辑,需要进行日志打点,以及埋点记录,比如电商系统中的下订单逻辑,以及OrderAction操作(业务状态变更)。

3. 对于整个系统的提供出的接口(REST/WS),使用info记录入参

4. 如果所有的service为SOA架构,那么可以看成是一个外部接口提供方,那么必须记录入参。

5. 调用其他第三方服务时,所有的出参和入参是必须要记录的(因为你很难追溯第三方模块发生的问题)

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());}
}
特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

别在 Java 代码里乱打日志了,这才是打印日志的正确姿势!相关推荐

  1. 别在 Java 代码里乱打日志了,这才是正确的日志打印姿势!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 转自:公众号   石杉的架构笔记  作者:Lrwin 打日志的正确 ...

  2. 别在 Java 代码里乱打日志了,这才是正确的打日志姿势

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:lrwin 使用slf4j 使用门面模式的日志框架,有利于维 ...

  3. 别在 Java 代码里乱打日志了,这才是正确的打日志姿势!

    点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 来源:http://t.cn/E9BkD7a 使用slf4j 使用门面模式的日志框架,有利于维护 ...

  4. 别在Java代码里乱打日志了,这才是正确的打日志姿势!

    原文链接:http://t.cn/E9BkD7a 使用slf4j 使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一. 实现方式统一使用: Logback框架 打日志的正确方式 什么时候应该 ...

  5. java执行sql列名无效_列名无效!java代码里的SQL语句!数据库里可以得到正确为什么放java里出错了?...

    在数据库里执行下面的SQL语句可得到正确结果,放在java代码里错误了!Stringsql="SELECTtradeId,t.cardNo,tradeType,tradeAmount,tar ...

  6. JAVA 代码里中文乱码问题

    为什么80%的码农都做不了架构师?>>>    1.中文在代码里, 输出到控制台出现了乱码 解决方法:右键项目属性,修改编码格式为UTF-8,重新打包,部署启动.即可. 转载于:ht ...

  7. springboot开启debug日志_SpringBoot 如何优雅的打印日志?

    一.打印日志注意事项 1.使用 Slf4j 注解 这个代码相信大家都很熟悉,你是否曾经看到或者自己因 copy 而 没有改变"当前类名"? 如果你们项目用到 lombok ,可以在 ...

  8. spring boot使用logback时控制台不打印日志,使用slf4j解决不打印日志问题

    maven项目在pom中添加slf4j依赖 <!--用于解决日志不打印问题--> <dependency><groupId>org.slf4j</groupI ...

  9. java代码里的JSON格式怎么写好看_谁会不爱让代码骚里骚气的VSCode扩展插件呢?...

    点击上方 "Python人工智能技术" 关注,星标或者置顶22点24分准时推送,第一时间送达 来自:公众号 读芯术 | 编辑:真经君 码农真经(ID:coder_experienc ...

最新文章

  1. 【工具软件】webstorm配置
  2. 学习Linux命令神器-看不懂直接给你解释
  3. 消除代码中的坏味道,编写高质量代码
  4. 【转载】计算机操作系统出现死锁的原因
  5. java 百度爬虫_零基础写Java知乎爬虫之先拿百度首页练练手
  6. 06 php 单例模式
  7. 强制选择“你是不是喜欢我” python实现
  8. 2000-2018年各省能源消费和碳排放数据
  9. 经典软件架构设计模式
  10. 南方cass计算表面积_CASS-工程应用“计算表面积”教程
  11. linux7启动ib子网管理器,IB_Switch交换机SB7890配置及Band网卡
  12. RS485MODBUS转PROFINET网关配置-科隆OPTIFLUX7000MODBUS通信协议电磁流量计接入西门子PLC S7-1500PROFINET以太网通讯网络配置方法
  13. 311、FirebaseAnalytics和Google Analytics总结
  14. 鸿蒙系统宣传标语,有多项新功能加持,搭载鸿蒙系统的华为手表WATCH 3来了!...
  15. 为什么要使用memcache?memcache有什么作用?
  16. 关于Java中Scanner获取Char字符类型的方法
  17. 自媒体,如何提高文章曝光率?
  18. LambdaMart一些浅薄理解
  19. ReactNative 原生UI组件 桥接原生 Android
  20. 微信H5棋牌游戏APP下载链接被屏蔽的解决办法

热门文章

  1. 介绍下Nginx 反向代理与负载均衡
  2. 下一代图片压缩格式 AVIF怎么样?
  3. Swagger3.0新版带来的新变化
  4. 51单片机教程哪个好?
  5. 7的整除特征 三位一截_小学生三位数加法的策略与表现
  6. 【数据结构】 哈希表 详解
  7. 第3关:递归实现二叉树左右子树交换
  8. poj1236(强连通分量)
  9. Codeforces Round #406 (Div. 1) B. Legacy(线段树上优化建图)
  10. 贪心 双指针----Codeforces Round #727 (Div.2) D. PriceFixed