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

原文链接: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);

说明

  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);}
    
  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());}
}

关注下方二维码,订阅更多精彩内容。

转发朋友圈,是对我最大的支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/546586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

局域网IP地址查看软件V2.0使用教程 Python办公自动化

简介: 在企业、公司都有自己的局域网,作为维护网络运维人员还在使用纸质或电子excel表记录计算机IP信息。是不是很希望有一款工具软件能够管理局域网内的计算机IP地址,可以统计出不同VLAN下的已使用IP-MAC记录和未使用的IP地址?再…

Oracle 10g RAC 升级(CPU Update)之--升级CRS

Oracle 10g RAC 升级(CPU Update)之--升级CRS系统环境:操作系统:RedHat EL5Cluster: Oracle CRS 10.2.0.1.0Oracle: Oracle 10.2.0.1.0如图所示:RAC 系统架构案例:本案例是从 Oracl…

面试题:聊一聊设计模式的基本原则

设计模式(Design pattern)代表了程序开发的最佳实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结…

python爬虫程序requests采用get和post方式

第1个爬虫程序: main.py #! python # -*- coding: utf-8 -*- from urllib.request import urlopen url "https://www.hao123.com/"if __name__ __main__:resp urlopen(url)# 把读取到网页的页面源代码写入myGetFile.html文件with open("myGetFil…

带你走近AngularJS - 基本功能介绍

带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍带你走近AngularJS - 体验指令实例带你走近AngularJS - 创建自定义指令------------------------------------------------------------------------------------------------ AngularJS是Google推出的一款…

解决SpringBoot多模块发布时99%的问题?SpringBoot发布的8个原则和4个问题的解决方案

如果使用 SpringBoot 多模块发布到外部 Tomcat,可能会遇到各种各样的问题。本文归纳了以下 8 个原则和发布时经常出现的 4 个问题的解决方案,掌握了这些原则和解决方案,几乎可以解决绝大数 SpringBoot 发布问题。 SpringBoot 多模块发布的 8 …

python爬虫 正则表达式 re.finditer 元字符 贪婪匹配 惰性匹配

测试代码1: main5.py # -*- coding: utf-8 -*- import reif __name__ __main__:# findall匹配字符串中所有的符合正则的内容lst re.findall(r"\d", "濮阳电话区号:0393,郑州电话区号:0371")print(lst)# 【…

如何在路由器的局域网下使用IIS发布网页

这两天尝试着使用IIS发布网页,但是学校宿舍只有一个网线接口,所以宿舍只申请了一个IP然后使用路由器共享网络。但是问题出现了:发布后的网页通过“IP:端口号”只能被自己宿舍的电脑(同一路由器)访问&#x…

U盘安装ubuntu20.04 Linux系统分区方案 Invalid Partition Table

一、简介: 一般磁盘分区表有两种格式:MBR和GPT,目前主要的BIOS系统引导方式也有两种:传统的Legacy BIOS和新型的UEFI BIOS 如果主机BIOS系统引导方式采用传统的Legacy BIOS,那么安装ubuntu系统的磁盘分区表使用MBR格式…

面试珍藏:最常见的200多道Java面试题(2019年最新版)

作者:老王来自公众号:Java中文社群(ID:javacn666)2015 年,因为工作岗位的变动,开始负责给集团招聘一些技术人员,出于对公司的负责,也为了更好的胜任技术经理的职位&#…

ubuntu20.04使用终端命令安装谷歌Chrome浏览器稳定版

使用命令行安装谷歌浏览器稳定版 sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list.d/wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -sudo apt-get updatesudo apt-get install google-chr…

面试官:数据量大的情况下分页查询很慢,有什么优化方案?

来源: http://uee.me/aVSnD当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询。对于数据库分页查询,也有很多种方法和优化的点。下面简单说一下我知道…

python爬虫获取中国天气网天气数据 requests BeautifulSoup re

python获取中国天气网天气数据:http://www.weather.com.cn/textFC/henan.shtml main.py # -*- coding: utf-8 -*- import requests from xpinyin import Pinyin from bs4 import BeautifulSoup import

使用Exchange反垃圾邮件组件解决内部仿冒邮件

最近一个朋友遇到一个很有意思的问题,在生产环境中我们装好Exchange之后,肯定需要配置外部邮件的收发。按照我们对邮件系统的理解,我们必须在default 接收连接器上的权限设置,允许匿名连接,才能实现外部邮件的接收。如…

VMware ubuntu20.04 server随win10自动启动与关闭

一、背景简介: 在win10下安装虚拟机,此虚拟机作为服务器使用,但是wi10电脑经常开关机,有的情况下,关机前没有主动关闭虚拟机,到此服务器需要收到重启,且数据容易丢失,配置 win10开机…

秋招注意事项和面试通关攻略

首先给大家说声抱歉,最近由于个人工作(突然996)和精力上的原因,导致公众号断更了一段时间,后面会逐渐恢复公众号的更新,在此感谢大家的理解和支持。国内主流的互联网公司在 8 月份都开放了秋招申请,那秋招有哪些需要注…

python爬虫 单线程的多任务异步协程

在input()、sleep(2)、request.get()等时,都会导致线程阻塞,协程可以解决IO等操作时的阻塞现象,提高CPU利用效率。 1.单线程的多任务异步协程 main.py """ coding: UTF8 """ import asyncio import timeasyn…

阿里2020届校招笔试劝退题——你大爷还是你大爷

阿里巴巴 2020 届的校招笔试结束了,群里哀声一片,来看这些经历了阿里秋招“洗礼”的小伙伴的真实状态。下面这些人嘛......就有些偏激了,哈哈哈先来说一下阿里笔试题构成:10 道单选题 2 道附加题。什么?单选题简单&am…

面试题:图解深克隆和浅克隆

获得好工作的秘密:有效的准备面试。在开始之前,我们先来看以下代码存在什么问题?class CloneTest {public static void main(String[] args) throws CloneNotSupportedException {// 等号赋值( 基本类型)int number 6…

python爬虫 threading 多线程 ThreadPoolExecutor线程池

1.创建多线程,无参数 main.py """ coding: UTF8 """ # 线程类 from threading import Threadclass myThread(Thread):def run(self): # 当线程被执行的时候,被执行的就是run()for i in range(1000):print("子线程&…