问题

今天在工作中,Redis接收到消息,入库失败了,只看到了有报错,但是没有看到是什么异常,还有具体的堆栈信息。

public class ExceptionTest {
    public static void main(String[] args) {
        try {
            System.out.println(1 / 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

上面这段程序只会将日志,输出到idea的控制台,并不会将,错误日志写入到log文件中。

e.printStackTrace()方法是用于打印异常堆栈信息到控制台,并不会将日志写入到log文件中。它会将异常的跟踪信息输出到标准错误流(System.err),通常会在控制台或终端显示。

Soga,原来是这样。。。。。

正确的日志打印方式是

@Slf4j
public class ExceptionTest {
    public static void main(String[] args) {
        try {
            System.out.println(1 / 0);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("程序出现异常:", e);
        }
    }
}

这样就可以将错误日志,写到log文件中,方便后续排查问题。

log.error 日志打印对比

public class TestLogError {
  public static final Logger LOGGER = LogManager.getLogger(TestLogError.class);
  
  public static void main(String[] args) {
    try{
      // 模拟空指针异常
      //Integer nullInt = Integer.valueOf(null);
      int[] array = {1,2,3,4,5};
      int outBoundInt = array[5];
    }catch (Exception e){
      // 直接打印,则只输出异常类型
      LOGGER.error(e);
      // 使用字符串拼接
      LOGGER.error("使用 + 号连接直接输出 e : " + e);
      LOGGER.error("使用 + 号连接直接输出 e.getMessage() : " + e.getMessage());
      LOGGER.error("使用 + 号连接直接输出 e.toString() : " + e.toString());
      // 使用逗号分隔,调用两个参数的error方法
      LOGGER.error("使用 , 号 使第二个参数作为Throwable : ", e);
      // 尝试使用分隔符,第二个参数为Throwable,会发现分隔符没有起作用,第二个参数的不同据,调用不同的重载方法
      LOGGER.error("第二个参数为Throwable,使用分隔符打印 {} : ", e);
      // 尝试使用分隔符,第二个参数为Object,会发现分隔符起作用了,根据第二个参数的不同类型,调用不同的重载方法
      LOGGER.error("第二个参数为Object,使用分隔符打印 {} ",123);
    }
  }
}

输出结果

23:24:04.753 [main] ERROR com.yu.test.exception.TestLogError - java.lang.ArrayIndexOutOfBoundsException: 5
23:24:04.760 [main] ERROR com.yu.test.exception.TestLogError - 使用 + 号连接直接输出 e : java.lang.ArrayIndexOutOfBoundsException: 5
23:24:04.760 [main] ERROR com.yu.test.exception.TestLogError - 使用 + 号连接直接输出 e.getMessage() : 5
23:24:04.760 [main] ERROR com.yu.test.exception.TestLogError - 使用 + 号连接直接输出 e.toString() : java.lang.ArrayIndexOutOfBoundsException: 5
23:24:04.764 [main] ERROR com.yu.test.exception.TestLogError - 使用 , 号 使第二个参数作为Throwable : 
java.lang.ArrayIndexOutOfBoundsException: 5
	at com.yupi.yupao.test.exception.TestLogError.main(TestLogError.java:14)
23:24:04.764 [main] ERROR com.yu.test.exception.TestLogError - 第二个参数为Throwable,使用分隔符打印 {} : 
java.lang.ArrayIndexOutOfBoundsException: 5
	at com.yu.test.exception.TestLogError.main(TestLogError.java:14)
23:24:04.771 [main] ERROR com.yu.test.exception.TestLogError - 第二个参数为Object,使用分隔符打印 123 

Process finished with exit code 0

总结:

使用Logger.error(e)、Logger.error(e.getMessage())、Logger.error("some msg" + e)、Logger.error("some msg" + e.getMessage()) 都是调用的error(Object message),这个方法都会将入参当作Object输出,不会打印堆栈信息。

在使用Logger.error("first param ",e)时会调用error(String message, Throwable t),此方法会完整的打印出错误堆栈信息。

最后,推荐一篇关于日志打印优秀实践的好文!值得收藏!

https://mp.weixin.qq.com/s/Bd7ldWUpUjDW_oHVM_IPhw?poc_token=HNyWFWWjd5_XINP7kwLWf2vkWVJrQi-hH6uMAuTC