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

Log4j2.properties配置Rewrite Policy不生效问题求助

Log4j2 Properties配置Rewrite Policy掩码不生效问题修复

问题背景

需要通过Log4j2的Rewrite Policy实现日志字段掩码,已找到XML格式的可行配置,但切换到log4j2.properties后Rewrite功能未生效。自定义RewritePolicy函数本身运行正常,但日志文件中无掩码效果。


参考的XML配置(可行)

<Configuration status="warn" name="MyApp" packages="">
  <Properties>
    <Property name="LOG_DIR">/logs</Property>
  </Properties>

  <Appenders>
    <RollingFile
      name="rollingFile"
      fileName="D:/logs/omnichannel/application.log"
      filePattern="D:/logs/omnichannel/application.%i.log.gz"
      ignoreExceptions="false">
      <PatternLayout>
          <Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n</Pattern>
      </PatternLayout>
      <Policies>
          <SizeBasedTriggeringPolicy size="10MB" />
      </Policies>
      <DefaultRolloverStrategy max="5">
        <Delete basePath="D:/logs/" maxDepth="2">
          <IfFileName glob="*/app-*.log.gz" />
          <IfLastModified age="P30D" />
        </Delete>
      </DefaultRolloverStrategy>
    </RollingFile>
     <Console name="STDOUT" target="SYSTEM_OUT" ignoreExceptions="false">
      <PatternLayout pattern="%m%n"/>
    </Console>
    <Rewrite name="Rewrite">
      <LogInterceptor />
      <AppenderRef ref="rollingFile"/>
    </Rewrite>
  </Appenders>

  <Loggers>
    <Root level="info">
      <AppenderRef ref="Rewrite"/>
    </Root>
  </Loggers>

</Configuration>

我的log4j2.properties配置(未生效)

status = warn
name= PropertiesConfig

# Give directory path where log files should get stored
property.basePath = D://logs//

appenders = rolling, console, Rewrite 

appender.Rewrite.type = Rewrite
appender.Rewrite.name = Rewrite
appender.Rewrite.layout.type = LogInterceptor
appender.Rewrite.layout.RewriteAppender = fileLogger

# ConsoleAppender will print logs on console
appender.console.type = Console
appender.console.name = consoleLogger
appender.console.target = SYSTEM_OUT
appender.console.layout.type = PatternLayout
# Specify the pattern of the logs
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight{[%-5level]}{TRACE=magenta} %mask %logger{36}.%M(%L) : %msg%n%throwable
appender.console.layout.disableAnsi=false

# RollingFileAppender will print logs in file which can be rotated based on time or size
appender.rolling.type = RollingFile
appender.rolling.name = fileLogger
appender.rolling.fileName = ${basePath}${hostName}.log
appender.rolling.filePattern = ${basePath}${hostName}_%d{yyyy-MM-dd}-%i.log.gz
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern =  %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%-5level] %logger{36}.%M(%L) : %msg%n%throwable
appender.rolling.policies.type = Policies

# Rotate log file each day and keep 30 days worth
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 1
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.action.type = Delete
appender.rolling.strategy.action.basePath = ${basePath}
appender.rolling.strategy.action.maxDepth = 1
appender.rolling.strategy.action.ifLastModified.type = IfLastModified
appender.rolling.strategy.fileIndex = nomax

# For hibernate tracing query parameter, make this default not opened
#loggers = application, hibernate
loggers = application, httpclient, Client


# Mention package name here. Classes in this package or sub packages will use ConsoleAppender and RollingFileAppender for logging         
logger.application.name = com.project
logger.application.level = info
logger.application.appenderRefs = rolling
logger.application.appenderRef.rolling.ref = fileLogger

logger.httpclient.name = org.apache.http
logger.httpclient.level = info
logger.httpclient.appenderRefs = rolling
logger.httpclient.appenderRef.rolling.ref = fileLogger

logger.Client.name = com.sun.jersey.api
logger.Client.level = info
logger.Client.appenderRefs = rolling
logger.Client.appenderRef.rolling.ref = fileLogger

# For hibernate tracing query parameter, make this default not opened
#logger.hibernate.name = org.hibernate.type
#logger.hibernate.level = trace
#Logger.hibernate.Additivity = false

# Configure root logger for logging error logs in classes which are in package other than above specified package
rootLogger.level = info
rootLogger.appenderRefs = Rewrite
rootLogger.appenderRef.Rewrite.ref = Rewrite

自定义RewritePolicy实现

@Plugin(name = "LogInterceptor", category = "Core", elementType = "rewritePolicy", printObject = true)
public class LoggingMaskingConverter implements RewritePolicy {
    
    protected static final Logger log = LogManager.getLogger(LoggingMaskingConverter.class);

    private static final List<String> loggingSetting = Arrays.asList("pin,password".split(","));
    
    private static final String loggingMasking = "1";
    
    private static final List<String> excludePath = Collections.emptyList();
    
    private static final String STR_BODY = "body=[";
    
    Properties prop = new Properties();
    
     @PluginFactory
     public static LoggingMaskingConverter createPolicy() {
         return new LoggingMaskingConverter();
     }
     
     @Override
     public LogEvent rewrite(LogEvent event) {
         if (event.getLoggerName().contains("com.project")) {
             
             Message outputMessage = logInfoMasking(event.getMessage());

             return new Log4jLogEvent.Builder(event).setMessage(outputMessage).build();
         } else {
             return new Log4jLogEvent.Builder(event).build();
         }
        
     }
     
     public Message logInfoMasking(Message message) {
         StringBuilder stringBuilder = new StringBuilder();
         try {
             String body = message.getFormattedMessage();
             ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
             if (StringUtils.isNotBlank(loggingMasking) && loggingMasking.equalsIgnoreCase("1")) {
                 if (body != null) {
                     Collection<String> whitelist = loggingSetting;
                     Collection<String> excludeKeys = excludePath;
                     JsonMasker masker = new JsonMasker(whitelist, excludeKeys);
                        
                     JsonNode jsonNode = new ObjectMapper().readTree(body);
                     JsonNode masked =  masker.mask(jsonNode);
                     stringBuilder.append(STR_BODY + masked.toString() + "]");
                 }
             } else {
                 String json = ow.writeValueAsString(body);
                 stringBuilder.append(STR_BODY + json + "]");
             }
                
         } catch (JsonProcessingException e) {
             log.error(e, e);
         }
         return new ObjectMessage(stringBuilder.toString());
    }
}

修复方案

1. 修正Rewrite Appender配置

原配置错误使用layout绑定RewritePolicy,且目标Appender配置方式有误,替换为以下配置:

appender.Rewrite.type = Rewrite
appender.Rewrite.name = Rewrite
# 绑定自定义RewritePolicy插件
appender.Rewrite.policy.type = LogInterceptor
# 指定Rewrite后要转发的目标Appender
appender.Rewrite.appenderRefs = fileLogger
appender.Rewrite.appenderRef.fileLogger.ref = fileLogger

2. 让自定义Logger通过Rewrite处理

原自定义Logger直接关联fileLogger,绕过了Rewrite,需修改为指向Rewrite Appender:

logger.application.name = com.project
logger.application.level = info
logger.application.appenderRefs = Rewrite
logger.application.appenderRef.Rewrite.ref = Rewrite

logger.httpclient.name = org.apache.http
logger.httpclient.level = info
logger.httpclient.appenderRefs = Rewrite
logger.httpclient.appenderRef.Rewrite.ref = Rewrite

logger.Client.name = com.sun.jersey.api
logger.Client.level = info
logger.Client.appenderRefs = Rewrite
logger.Client.appenderRef.Rewrite.ref = Rewrite

3. 可选:控制台日志也启用掩码

若需要控制台日志也被掩码,修改Rewrite的AppenderRefs同时包含控制台:

appender.Rewrite.appenderRefs = fileLogger, consoleLogger
appender.Rewrite.appenderRef.fileLogger.ref = fileLogger
appender.Rewrite.appenderRef.consoleLogger.ref = consoleLogger

4. 验证插件加载

确保Log4j2能扫描到自定义插件,可在配置开头添加packages属性指定插件所在包:

packages = com.your.package.path

(替换为LoggingMaskingConverter类所在的包路径)

5. 开启调试日志排查

临时将status = debug,查看Log4j2启动日志,确认:

  • LogInterceptor插件是否被成功加载
  • Rewrite Appender是否正确初始化并关联了目标Appender

内容的提问来源于stack exchange,提问作者Fernando Alexsandro Siregar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 00:18:00