十个Java编程中记录日志的小技巧
创始人
2025-07-10 14:01:33
0

在Java编程中,良好的日志记录是一项重要的实践。无论是在调试代码还是在生产环境中追踪问题,准确的日志信息能够提供有价值的上下文和跟踪数据。然而,对于许多开发者来说,正确地记录日志可能是个挑战。

本文介绍一些简单且实用的技巧,以帮助读者在Java编程中改善日志记录,使其更加高效和易于调试。

1 选择适当的日志格式

理想的日志格式应包含最基本的信息,例如当前时间戳(通常精确到毫秒)、日志级别、线程名称等。可以像下面这样配置logback日志:


    
       %d{HH:mm:ss.SSS} %-5level [%thread][%logger{0}] %m%n
    

如果开发者的日志格式不记录当前时间,那么甚至无法知道请求发生的时间。

2 选择适当的日志级别

常见的日志级别有五个,分别是error、warn、info、debug和trace。在日常开发中,开发者需要选择适当的日志级别,不要直接打印info级别的日志。

  • Error(错误):指相对严重的错误,会影响正常业务,并需要进行运维配置监控。
  • Warn(警告):一般的错误,对业务影响较小,但需要开发人员的注意。
  • Info(信息):记录关键的故障排查信息,例如调用时间、输入输出参数等。
  • Debug(调试):用于开发阶段的关键逻辑的运行时数据。
  • Trace(追踪):最详细的信息,一般只在日志文件中记录。

3 当日志级别较低时,进行日志开关判断

对于较低的日志级别,如trace/debug级别,必须进行日志级别开关判断。

User user = new User(666L, "demo");
if (log.isDebugEnabled()) {
    log.debug("userId is: {}", user.getId());
}

由于目前存在以下日志代码:

logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);

如果配置的日志级别是warn,上述日志将不会被打印,但仍会执行字符串拼接操作。如果符号是对象,还将执行toString()方法,这会浪费系统资源。尽管进行了上述操作,但最终日志并未打印出来,因此建议添加日志开关判断。

4 日志应打印出该方法的输入和输出参数

开发人员不需要打印大量的日志,只需要打印能够快速定位问题的有效日志。什么是有效和关键的日志呢?

  • 输入方法时,打印输入参数。
  • 方法返回时,打印出参数和返回值。

就参数而言,通常是关键信息,比如userId等。

5 日志系统中的API(如Log4j、Logback)不能直接使用,但可以使用日志框架SLF4J中的API

SLF4J是一个以门面模式(facade mode)工作的日志框架,有利于统一各个类的维护和日志处理方法,而且可以轻松替换底层的日志框架且不需要修改代码。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private static final Logger logger = LoggerFactory.getLogger(Demo.class);

6 当遇到诸如 if...else... 或 switch 等条件语句时,尽量在每个分支的第一行打印日志

当遇到 if...else... 或 switch 等条件语句时,应尽量在分支的第一行打印日志,这样在排查问题时,可以通过日志确定进入了哪个分支,代码逻辑更清晰,也更容易排查问题。

if (user.isVip()) {
  log.info("User isVip, Id: {}", user.getUserId());
} else {
  log.info("User not isVip, Id: {}", user.getUserId());
}

以上代码示例在每个分支的第一行使用日志打印。

7 建议使用参数占位符 {} 代替 + 进行字符串拼接

错误的用法:

logger.info("Processing trade with id: " + id + " and symbol: " + symbol);

在上面的例子中,使用 + 运算符来拼接字符串会带来一定的性能损失。

正确的用法:

logger.info("Processing trade with id: {} and symbol: {}", id, symbol);

在日志中使用花括号 {} 作为占位符,这比使用 + 运算符更加优雅和简洁。与负面示例相比,占位符的使用只是一个替换操作,可以有效提高性能。

8 不要使用e.printStackTrace()

错误的用法:

try {
  ...
} catch (Exception e) {
  e.printStackTrace();
}

正确的用法:

try {
  ...
} catch (Exception e) {
  log.error("error", e);
}

使用e.printStackTrace()打印的堆栈日志与业务代码日志交织在一起,通常不方便检查异常日志。

e.printStackTrace()语句生成的字符串记录了堆栈信息。如果信息过长,字符串常量池所在的内存块没有空间,也就是内存已满,那么用户的请求会被阻塞。

9 建议以异步方式输出日志

日志最终会输出到文件或其他输出流中,这涉及到IO性能。如果采用异步方式,可以显著提高IO性能。

除非有特殊要求,建议使用异步方式输出日志。以logback为例,配置异步非常简单,只需使用AsyncAppender:


    

以上配置使用AsyncAppender来实现异步输出日志。

10 禁止在联机环境中启用调试功能

在联机环境中禁用调试功能非常重要。

因为通常系统会有大量的调试日志,各种框架也会大量使用调试日志,在线调试可能会很快填满磁盘,影响业务系统的正常运行。

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
P2P的自白|我不生产内容,我... 现在一提起P2P,人们就会联想到正在被有关部门“围剿”的互联网理财服务。×租宝事件使得劳...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...