千家信息网

怎么正确用Java代码打日志

发表于:2024-10-21 作者:千家信息网编辑
千家信息网最后更新 2024年10月21日,这篇文章主要讲解了"怎么正确用Java代码打日志",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么正确用Java代码打日志"吧!使用slf4j使用门面
千家信息网最后更新 2024年10月21日怎么正确用Java代码打日志

这篇文章主要讲解了"怎么正确用Java代码打日志",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么正确用Java代码打日志"吧!

使用slf4j

  • 使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

  • 实现方式统一使用: Logback框架

打日志的正确方式

什么时候应该打日志

  • 当你遇到问题的时候,只能通过debug功能来确定问题,你应该考虑打日志,良好的系统,是可以通过日志进行问题定为的。

  • 当你碰到if…else 或者 switch这样的分支时,要在分支的首行打印日志,用来确定进入了哪个分支

  • 经常以功能为核心进行开发,你应该在提交代码前,可以确定通过日志可以看到整个流程

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

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:基本概念影响到程序正常运行、当前请求正常运行的异常情况:

  • 打开配置文件失败

  • 所有第三方对接的异常(包括第三方返回错误码)

  • 所有影响功能使用的异常,包括:SQLException和除了业务异常之外的所有异常(RuntimeException和Exception)

不应该出现的情况:比如要使用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代码打日志"的内容了,经过本文的学习后,相信大家对怎么正确用Java代码打日志这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

日志 用户 信息 代码 情况 业务 系统 参数 员工 薪资 问题 手机 概念 第三方 运行 手机号 接口 方式 时候 影响 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 数据库原理中主数据文件是什么 数据库技术适合哪些专业 传奇服务器怎么修改升级经验 网络安全张兰 网吧的电脑是服务器么 网络安全大赛退役什么意思 战时网络安全龙头股 数据库原理与技术图书电子版 一个服务器能启动两个项目吗 服务器 远程桌面 服务器文件给员工编辑安全吗 数据库多行数据添加命令的代码 广东智通网络技术有限公司 软件开发需要英语厉害吗 揭秘软件开发 阿里服务器提示挖矿 软件开发成本评估专家意见 正规网络技术服务优化价格 广州蔚米网络技术有限公司 电视盒子的软件开发 河南集装客互联网科技 学习计算机网络技术英语的app 免费服务器地址用户名和密码 生猪数据库 王者荣耀新服务器什么时候出一次 安装数据库时那几个不选 浙江瑞金网络技术有限公司 企业单位计算机网络安全剖析 倚天网吧服务器 网络技术实现资源共享
0