如何使用Log4j2 xml Rewrite appender在LogEvent登录文件之前对其进行修改



我想在我的log4j2.xml文件中使用Rewrite appender,以便在日志记录之前可以修改日志。我没有从谷歌得到太多帮助。根据log4j2文档,Rewrite是一个具有重写方法的接口,MapRewritePolicy是实现类,当我运行它时,我可以看到我的web3.log文件正在生成,但没有看到日志内容中的任何修改。我看到了MapRewritePolicy的源代码,并在我的项目中创建了本地实现类MapRewritePolicyImpl.java,并放了一些System.out来查看代码流是从log4j2.xml文件进入这个类的。我已经修改了我的log4j2.xml以使用MapRewritePolicyImpl.java,但代码流不会进入我的MapRewritePolicy Impl.java类。

<Rewrite name="rewrite" >
<Appender-Ref ref="web3" />
<MapRewritePolicyImpl">
<KeyValuePair key="creditCard" value="new12345"/>
</MapRewritePolicyImpl> 
</Rewrite>

<Configuration monitorInterval="5" status="debug" strict="true">
<Appenders>
<RollingFile name="web3" fileName="../logs/web3.log" 
filePattern="${sys:catalina.home}/logs/$${date:yyyy-MM-dd}/web3-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout
pattern="%d{dd/MM/yyyy HH:mm:ss,SSS} [%X{cartID}] [%X{sessionId}] [%p] [%t] [%c] (%F:%L)  - %m%n" />
<Policies>
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
</RollingFile>
<Rewrite name="rewrite" >
<Appender-Ref ref="web3" />
<MapRewritePolicy">
<KeyValuePair key="creditCard" value="new12345"/>
</MapRewritePolicy> 
</Rewrite>
</Appenders>
<Loggers>
<Logger name="com.virginamerica" level="info" additivity="false">
<!-- <Appender-Ref ref="web3" /> -->
<Appender-Ref ref="rewrite"/>
</Logger>
</Loggers>
</Configuration>

解决方案1:使用重写附件

你的例子似乎几乎是正确的。正如@Remko Popma所提到的,您选择的"重写"实现不适合您的用例。

如果你使用自己的"重写器"实现,你就可以让它发挥作用。

我在这里找到了一个很好的例子:重写附加示例

该示例包含log4j2.xml和RewriteAppender的实现。在RewriteAppender(此处称为MarkerInjectorRewritePolicy)中,您可以根据需要修改事件。在作者注入一些标记数据的示例中,您不需要该部分。

解决方案2:使用LogEventFactory

解决方案1有一些缺点。想象一下,你有100个记录器和50个Appenders。现在尝试实现解决方案1,您将得到另外50个RewriteAppender声明,并对所有记录器进行调整,以使用重定向记录器而不是实际的目标Appender。这可能非常乏味并且容易出错。

一个更简单的解决方案是:

// Do this somewhere before using the logger
System.setProperty(Constants.LOG4J_LOG_EVENT_FACTORY, MyLogEventFactory.class.getName());

或者使用启动参数设置:

-DLog4jLogEventFactory=my.package.MyLogEventFactory

编辑:更好:一种更稳健的设置方法是使用log4j2.component.properties:

  • 创建一个名为log4j2.component.properties的文本文件,并将其放入类路径中
  • 把这个代码放进去:Log4jLogEventFactory = my.package.MyLogEventFactory

此文件由log4j自动加载,用于配置多个核心设置。使用此文件,您不必每次都传递启动参数,而且也不会遇到类初始化顺序问题的潜在问题(如使用System.setProperty()时)。

LogEventFactory的实现非常简单:

public class MyLogEventFactory implements LogEventFactory {
@Override
public LogEvent createEvent(String loggerName, Marker marker, String fqcn, Level level, Message message,
List<Property> properties, Throwable t) {
{ // In my case i wanted "log.error(new Exception(msg))"
// to pass the exception properly to the event,
// as if "log.error(msg, new Exception(msg))" was called.
if (t == null && message instanceof ObjectMessage) {
ObjectMessage msg = (ObjectMessage) message;
t = msg.getThrowable();
}
}
// XXX do your adjustments here
return new Log4jLogEvent(loggerName, marker, fqcn, level, message, properties, t);
}
}

LogEventFactory用于创建LogEvents。因此,我们不需要稍后拦截和操纵它们,而是简单地找到源代码并在这里完成我们的工作。

有了这个,我们可以举办所有活动!

祝你好运!玩得高兴

MapRewritePolicy将评估包含MapMessage的LogEvents,并添加或更新Map的元素。只有当您的应用程序调用logger.info(new MapMessage(keyValueMap))时,这才有效。我怀疑这不是您的应用程序当前正在做的事情。

通常,您的消息将是SimpleMessage(如果您调用logger.info("Just a string without parameters"))或ParameterizedMessage(如果调用logger.info("Hi {}!", name))。RewriteAppender将无法对SimpleMessage或ParameterizedMessages执行任何操作,因此不会替换任何内容。。。

您可能需要查看PatternLayout的文档:如果使用replace{pattern}{regex}{substitution}模式,它可以用一些替换值替换字符串消息中的正则表达式。

最新更新