java中日志打印规范

1.选择恰当的日志级别

日常开发中常见日志级别有:trace、debug、info、warn、error(级别依次增大):
1.trace:最详细的日志信息,一般记录到日志文件中
2.debug:一般用于开发中DEBUG的关键逻辑的运行时数据
3.info:记录排查问题的关键信息,如出参,入参等
4.warn:警告日志,一般的错误,对正常业务影响不大,需要开发者关注
5.error:错误日志,对正常业务有影响,需要运维配置日志监控

2.日志要打印方法的入参和出参

例如在Controller层,请求入参、响应出参和响应异常,一般需要打印日志,出问题时,方便追踪代码逻辑运行的路线。建议这里使用日志切面进行统一日志打印;

其他层级的方法入参和出参,如有必要,可以打印整个出参和入参的数据,反之可以打印有效的关键日志,方便问题定位即可;

3.日志格式

一般日志中包含:时间、日志级别、线程名称、日志具体内容等

%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger:%line - %msg%n

4.在多个if-else等条件时,每个分支首行尽量打印日志

可以在进入分支前打印日志,后续可以快速定位到进入了哪个分支,方便排查问题

String requestNo = "RN7195458555001";
String channel = "weixin";
log.info("请求流水号[{}]支付处理,渠道为:{}", requestNo, channel);
if (Objects.equals("zhifubao", channel)) {
    // TODO
} else if (Objects.equals("yinlian", channel)) {
    // TODO
} else if (Objects.equals("weixin", channel)) {
    // TODO
} else {
    // TODO
}

5.日志级别比较低时,进行日志开关判断

对于trace、debug级别的日志打印,需要进行开关判断

if (log.isTraceEnabled()) {
    log.trace("trace log detail......");
}
if (log.isDebugEnabled()) {
    log.debug("debug log detail......");            
}

比如需要打印如下日志

log.debug("Payment processing,requestNo=" + requestNo + ",channel=" + channel);

当前配置的日志级别为info,则上面日志不会打印,但会进行字符串拼接;如果是对象,还会执行toString()方法,浪费了系统资源

6.不要直接使用日志系统(Log4j、Logback)中的 API,而是使用日志框架SLF4J中的API

SLF4J是门面模式的日志框架,需要更换日志框架实现时,在不改动代码的情况下,可以方便切换到不同的日志实现框架

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

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

// 或者使用Lombok  @Slf4j

7.建议使用参数占位{},而不是用+拼接

反例:

log.debug("Payment processing,requestNo=" + requestNo + ",channel=" + channel);

字符串使用"+"进行拼接操作,会有一定的性能损耗,虽然高版本的jdk对字符串拼接进行了性能优化,但不建议使用

正例:

log.info("Payment processing,requestNo={},channel={}", requestNo, channel);

使用大括号{}进行占位符的替换,相比字符串拼接,性能上更高,日志代码也更加优雅

8.不要使用e.printStackTrace() 和 System.out.println();

反例:

try{
  // TODO 业务代码处理
}catch(Exception e){
 //System.out.println("xxx业务处理异常,异常信息:" + e);
  e.printStackTrace();
}

正例:

try {
    // TODO 业务代码处理
} catch (Exception e) {
    log.error("xxx业务处理异常 requestNo={}", requestNo, e);
}
e.printStackTrace()打印在堆栈信息中,如果异常过多,会导致堆栈内存不足,出现卡(运行极慢)的现象,最后出现OOM,这是一种非常糟糕的现象;
使用log来打印日志会记录到日志文件中,占用的是磁盘内存,一般不会经常出现卡(运行极慢)的现象,但如果磁盘内存占用比较高时,需要对日志进行备份处理,然后清理日志;

9.异常日志不要只打一半,要输出全部错误信息

反例:

log.error("xxx业务处理异常");
log.error("xxx业务处理异常", e.getMessage());

e.getMessage()不会记录详细的堆栈异常信息,只会记录错误基本描述信息,不利于排查问题。

正例:

log.error("xxx业务处理异常 requestNo={}", requestNo, e);

10.禁止在线上环境开启 debug

一般业务系统的debug日志较多,引入的第三方框架debug日志也较多,随着业务交易的增多,容易占用磁盘内存空间,最后可能会影响正常业务系统的运行,所以生产环境禁止开启debug

11.不要既打印了异常日志,又抛出异常

try {
    // TODO 业务代码处理
} catch (Exception e) {
    log.error("xxx业务处理异常", e);
    // BusinessException:自定义业务处理异常类
    throw new BusinessException("xxx业务处理异常", e);
}

此处会打印两次异常日志:

第一次是log.error("xxx业务处理异常", e)会打印一次;
第二次是throw new BusinessException("xxx业务处理异常", e)会打印一次;

可以根据具体情况来选择,例如此处就应该抛异常处理,那么可以仅使用throw new BusinessException("xxx业务处理异常", e)即可

12.避免重复打印日志

如果一行日志可以表达清楚,则使用一行打印即可,避免日志信息冗余

反例:

log.info("创建用户信息 userId={}", userId);
log.info("创建用户信息 userName={}", userName);

正例:

log.info("创建用户信息 userId={},userName={}", userId, userName);

13.日志文件分离

根据不同的日志级别,打印在不同的日志文件中,例如debug、info、warn、error日志级别的日志分别创建一个日志文件debug.log、info.log、warn.log、error.log进行日志打印;

将不同类型的日志进行日志分类,例如access.log、error.log等

14.核心功能模块,建议打印较完整的日志

业务系统中,核心功能的代码,尽可能打印日志完整,核心代码执行频率极高,出问题时,根据日志信息能快速定位。

<think>好的,我现在需要回答用户关于如何在Java中配置和打印日志的问题。首先,我应该先理解用户的需求。用户可能是一个刚开始学习Java开发者,想要了解日志框架的基本配置和使用方法。根据提供的引用内容,用户已经接触过Log4j、Logback以及java.util.logging等日志框架,所以我的回答需要涵盖这些内容,并给出示例教程。 首先,我需要确定回答的结构。用户要求结构清晰,逐步解决问题,所以应该分步骤讲解。常见的步骤包括引入日志框架、配置日志级别、创建Logger对象、记录日志、配置输出格式和存储策略等。此外,用户还希望有示例代码,所以我需要为每个主要框架(如Log4j 2和Logback)提供配置文件和代码示例。 接下来,我需要参考提供的引用内容。引用[1]提到使用Log4j设置控制台日志级别,引用[2]提到Logback的MBean配置,引用[3]和[4]则涉及日志规范和最佳实践。因此,在回答中应强调选择合适的日志框架、配置日志级别、记录上下文信息以及遵循规范的重要性。 然后,我需要确保回答符合系统级指令的要求,比如行内数学表达式使用$...$,独立公式用$$...$$,但在这个问题中可能用不上数学公式。同时,需要生成相关问题,这通常在最后部分处理。 现在,开始组织内容。首先介绍日志框架的重要性,然后分步骤讲解配置方法。对于每个步骤,给出具体示例,比如Log4j 2的XML配置,Logback的配置,以及java.util.logging的简单示例。同时,提到最佳实践,如避免敏感信息、配置滚动策略等,引用[4]中的内容可以支持这部分。 在示例部分,需要确保代码块正确,并说明如何运行。可能还需要解释各部分的作用,比如Logger的获取,日志级别的设置,不同日志方法的使用等。此外,注意引用标记,比如在提到配置包级别日志时引用[2],提到日志规范时引用[4]。 最后,生成相关问题,需要考虑用户可能进一步想知道的内容,比如日志级别的作用、性能优化、日志分析工具等。 检查是否有遗漏,比如是否覆盖了所有主要日志框架,是否解释了配置的关键点,是否有示例代码,是否符合中文回答的要求,以及是否自然添加了引用标识。确保没有使用任何Markdown格式,代码块正确,语言标签准确。</think>在Java中配置和打印日志通常需借助日志框架(如Log4j 2、Logback或`java.util.logging`),以下是具体实现步骤和示例: --- ### **1. 选择并引入日志框架** - **Log4j 2**(推荐): 高性能,支持异步日志,需添加依赖: ```xml <!-- Maven 依赖 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.20.0</version> </dependency> ``` - **Logback**: Spring Boot默认框架,需添加`logback-classic`依赖[^2]。 - **JUL(java.util.logging)**: JDK内置,无需额外依赖[^1]。 --- ### **2. 配置日志级别和输出** #### **Log4j 2示例** 创建`log4j2.xml`文件(置于`src/main/resources`): ```xml <?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <!-- 设置包级别日志 --> <Logger name="com.example" level="DEBUG" additivity="false"> <AppenderRef ref="Console"/> </Logger> <Root level="INFO"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration> ``` 通过`level="DEBUG"`设置日志级别(从低到高:`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL`)。 #### **JUL示例** 代码中直接配置: ```java import java.util.logging.Level; import java.util.logging.Logger; public class Main { private static final Logger logger = Logger.getLogger(Main.class.getName()); public static void main(String[] args) { logger.setLevel(Level.FINE); // 设置级别为FINE(对应DEBUG) logger.info("这是一条INFO日志"); logger.warning("这是一条WARNING日志"); } } ``` --- ### **3. 在代码中打印日志** #### **Log4j 2代码示例** ```java import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Demo { private static final Logger logger = LogManager.getLogger(Demo.class); public static void main(String[] args) { logger.debug("调试信息: {}", someVariable); // 使用占位符避免字符串拼接开销 logger.info("业务操作完成"); logger.error("发生异常", exception); // 记录异常堆栈 } } ``` --- ### **4. 配置日志滚动策略(防止日志文件过大)** 在`log4j2.xml`中添加文件滚动配置: ```xml <RollingFile name="File" fileName="logs/app.log" filePattern="logs/app-%d{yyyy-MM-dd}.log.gz"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5level %msg%n"/> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> </Policies> </RollingFile> ``` 此配置按天压缩归档日志文件[^4]。 --- ### **5. 最佳实践** - **记录上下文信息**: 包含类名、方法名、线程ID等,便于排查问题。 - **避免敏感信息**: 如密码、密钥不应出现在日志中。 - **异步日志**: 使用`AsyncLogger`提升性能(Log4j 2支持)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值