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

如何配置Log4j2的SMTP Appender仅在记录ConfigException异常时发送邮件

如何配置Log4j2的SMTP Appender仅在记录ConfigException异常时发送邮件

我看了你的问题和当前配置,核心问题是用RegexFilter做字符串匹配的方式不够精准,而且Log4j2的RegexFilter默认只匹配日志事件的message字段(不是渲染后的完整日志或异常栈),这就容易出现要么漏判(比如日志消息里没带ConfigException但异常确实是它)、要么误判(其他异常的日志里碰巧有这个字符串)的情况。你说现在两个异常都触发了邮件,大概率是因为RegexFilter没有按预期过滤——要么是RuntimeException的日志里无意中包含了匹配字符串,要么是你对RegexFilter的匹配范围理解有误。

下面给你两种更可靠的解决方案:

方案一:用ScriptFilter直接检查异常类型(最精准,推荐)

这种方式不依赖字符串匹配,而是通过脚本直接检查日志事件中的异常是否是ConfigException(或其派生类)的实例,甚至能遍历异常的cause链,确保不会漏判嵌套的ConfigException。

修改你的SMTP Appender的Filters部分,替换原来的RegexFilter:

<Filters>
    <!-- 先过滤出ERROR级别及以上的事件 -->
    <ThresholdFilter level="ERROR" onMatch="NEUTRAL" onMismatch="DENY"/>
    <!-- 用脚本检查异常类型 -->
    <ScriptFilter onMatch="ACCEPT" onMismatch="DENY">
        <Script language="JavaScript"><![CDATA[
            // 遍历异常链,检查是否存在目标异常
            function hasConfigException(throwable) {
                while (throwable != null) {
                    // 替换成你的ConfigException的完整类名(比如com.yourpackage.ConfigException)
                    if (throwable.getClass().getName() === "com.yourpackage.ConfigException") {
                        return true;
                    }
                    throwable = throwable.getCause();
                }
                return false;
            }
            return hasConfigException(logEvent.getThrown());
        ]]></Script>
    </ScriptFilter>
</Filters>

⚠️ 注意:必须把com.yourpackage.ConfigException替换成你自定义ConfigException类的完整包路径+类名,否则脚本无法正确识别异常类型。

方案二:用Marker标记+MarkerFilter(性能更好,需修改代码)

如果不想用脚本,也可以通过Marker(日志标记)来区分事件,在记录ConfigException时添加专属标记,再在Appender里过滤这个标记。

步骤1:在代码中定义并使用Marker

// 定义一个静态Marker常量
private static final Marker CONFIG_ERROR_MARKER = org.apache.logging.log4j.MarkerManager.getMarker("CONFIG_ERROR");

// 记录ConfigException时带上这个Marker
catch (ConfigException cEx) {
    log4jLogger.error(CONFIG_ERROR_MARKER, "Hihi; " + cEx.getMessage(), cEx);
}

// 其他异常的日志记录保持不变
catch (RuntimeException ex) {
    log4jLogger.error("Oops; " + ex.getMessage(), ex);
}

步骤2:修改SMTP Appender的Filters

<Filters>
    <ThresholdFilter level="ERROR" onMatch="NEUTRAL" onMismatch="DENY"/>
    <!-- 只接受带有CONFIG_ERROR标记的日志事件 -->
    <MarkerFilter marker="CONFIG_ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>

为什么你的原始配置不工作?

回头看你的原始配置:

  1. RegexFilter默认只匹配日志事件的message字段,而你的第一个日志消息是"Hihi; Config failed",里面并没有ConfigException字符串——这说明你的测试环境中可能日志消息或异常栈里无意中包含了这个字符串,导致正则误匹配。
  2. 如果RuntimeException也触发了邮件,大概率是它的日志消息/异常栈里碰巧有ConfigException相关的字符串,或者RegexFilter的匹配逻辑没有按预期执行。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 06:59:34