You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java如何实现仅Debug及以下级别日志携带Throwable异常栈

方案1:封装统一日志工具类(侵入性最小,无需修改日志框架配置)

把判断逻辑收拢到工具类中,配合IDE全局替换可以快速完成存量代码改造:

import org.slf4j.Logger;

public class LogUtils {
    // warn级别条件输出异常栈
    public static void warnWithConditionalStack(Logger logger, String msg, Throwable e) {
        if (logger.isDebugEnabled()) {
            logger.warn(msg, e);
        } else {
            logger.warn("{} | 异常信息: {}", msg, e.toString());
        }
    }

    // 可按需扩展error、info等其他级别的对应方法
    public static void errorWithConditionalStack(Logger logger, String msg, Throwable e) {
        if (logger.isDebugEnabled()) {
            logger.error(msg, e);
        } else {
            logger.error("{} | 异常信息: {}", msg, e.toString());
        }
    }
}

业务代码仅需替换原有日志打印语句即可:

try {
    // ...
} catch (Exception e){
    LogUtils.warnWithConditionalStack(logger, "ERR Occurs", e);
}

方案2:自定义日志框架转换器(零业务代码侵入,推荐)

主流日志框架(Logback/Log4j2)都支持自定义格式转换器,只需修改框架配置即可全局生效,完全不需要改动业务代码。
以Logback为例实现逻辑如下:

  1. 自定义异常转换器类
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import org.slf4j.event.Level;

public class ConditionalStackTraceConverter extends ThrowableProxyConverter {
    @Override
    protected String throwableProxyToString(IThrowableProxy tp) {
        ILoggingEvent event = getEvent();
        // 判断当前logger生效级别低于等于DEBUG时输出完整栈
        if (event.getLoggerContextVO().getLevel().toInt() <= Level.DEBUG.toInt()) {
            return super.throwableProxyToString(tp);
        }
        // 高日志级别下仅输出异常类名和错误信息
        return tp.getClassName() + ": " + tp.getMessage();
    }
}
  1. 修改Logback配置文件,注册转换器
<configuration>
    <!-- 注册自定义转换器 -->
    <conversionRule conversionWord="condEx" converterClass="com.yourpackage.ConditionalStackTraceConverter" />

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 用自定义的condEx替换原有%ex/%exception占位符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%condEx%n</pattern>
        </encoder>
    </appender>
    <!-- 其余原有配置保持不变 -->
</configuration>

配置完成后业务代码正常写logger.warn("ERR Occurs", e)即可,框架会自动根据日志级别判断是否输出完整异常栈。Log4j2也有类似的ThrowablePatternConverter扩展机制,实现逻辑一致。

方案3:SLF4J 2.0+ Fluent API实现(适合新项目)

如果使用SLF4J 2.0及以上版本,可以用原生Fluent API实现条件化传入异常参数,代码更简洁:

try {
    // ...
} catch (Exception e) {
    logger.atWarn()
          .setMessage("ERR Occurs")
          .setCause(logger.isDebugEnabled() ? e : null)
          .log();
}

内容的提问来源于stack exchange,提问作者KM H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 12:15:08