文章目录

  • Logging
  • commons-logging
  • Slf4j
  • Log4j
  • Logback
  • 日志级别选择
  • 日志级别
  • 如何正确的打日志
  • 规范日志样例


比较常用的搭配是commons-logging+log4j,slf4j+logback

Logging

Java 自带的日志工具类,很少使用

commons-logging

commons-logging 就是日志的门面接口,用户可以根据喜好选择不同的日志实现框架,而不必改动日志定义,这就是日志门面的好处,符合面对接口抽象编程。

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class XXXService {
    private static final Log log = LogFactory.getLog(XXXService.class);
    public void doSomething(){
        log.info("begin dosomething....");
    }
}

Slf4j

简单日志门面接口。官方文档:官方文档

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class XXXService {
    private static final Logger logger = LoggerFactory.getLogger(XXXService.class);
    public void doSomething() {
        logger.info("begin dosomething...");
    }
}

好处:

1、更好的可读性;

2、不需要使用logger.isDebugEnabled()来解决日志因为字符拼接产生的性能问题。比如:logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol)

Log4j

Log4j 是 Apache 的一个开源日志框架,是一个具体的日志框架的实现。我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。并且只需要一个配置文件来灵活地进行配置,而不需要修改应用的代码。

Logback

Logback 是 Slf4j 的原生实现框架,同样也是出自 Log4j 一个人之手,但拥有比 log4j 更多的优点、特性和更做强的性能,现在基本都用来代替 log4j 成为主流。

日志级别选择

日志级别

日志级别

描述

OFF

关闭:最高级别,不输出日志。

FATAL

致命:输出非常严重的可能会导致应用程序终止的错误。

ERROR

错误:输出错误,但应用还能继续运行。

WARN

警告:输出可能潜在的危险状况。

INFO

信息:输出应用运行过程的详细信息。

DEBUG

调试:输出更细致的对调试应用有用的信息。

TRACE

跟踪:输出更细致的程序运行轨迹。

如何正确的打日志

1.定义日志

private static final Logger LOG = LoggerFactory.getLogger(this.getClass());

2.使用参数化形式{}占位,[] 进行参数隔离

LOG.debug("Save order with order no:[{}], and order amount:[{}]");

3.输出不同级别的日志

  • ERROR(错误)

影响到程序正常运行、当前请求正常运行的异常情况,一般用来记录程序中发生的任何异常错误信息(Throwable),或者是记录业务逻辑出错。如:

(1)打开配置文件失败

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

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

  • WARN(警告)

不影响程序、当前请求正常运行的,不应该出现的异常情况:一般用来记录一些用户输入参数错误

(1)有容错机制的时候出现的错误情况

(2)业务异常的记录

  • INFO(信息)

这个也是平时用的最低的,也是默认的日志级别,用来记录程序运行中的一些有用的信息。如程序运行开始、结束、耗时、重要参数等信息

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