我正在尝试使用Log4j2的新RoutingAppender来根据MDC(Log4j2中的ThreadContext)路由不同的日志。我想做的是以下几点:
我想在标记中使用通配符模式实现此目的,然后使用for contextId($ {ctx:contextId})中的key参数进行过滤,并使用默认(不带键参数)作为主appender,但是我不知道那个通配符是哪个值。
任何帮助都表示赞赏,也许我正在走错路。我一直在阅读有关过滤器的内容,但似乎没有按照我的意愿工作。
谢谢!
答案 0 :(得分:2)
这是否回答了你的问题? https://issues.apache.org/jira/browse/LOG4J2-326
的Remko
答案 1 :(得分:2)
我对使用https://issues.apache.org/jira/browse/LOG4J2-326和http://logging.apache.org/log4j/2.x/faq.html#separate_log_files中描述的技巧定义回退路由的解决方案感到不满,因为这迫使我复制路由中包含的appender配置。我不需要为默认路由配置不同的appender配置,只需要一般日志的正确文件名。
鉴于默认属性映射在其上下文中查找未定义的属性,请参阅https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution,我认为最直接的方法是定义默认值,例如。
<Properties>
<Property name="fruits">any_fruit</Property>
</Properties>
如果线程上下文没有$ {ctx:fruits},则会执行“any_fruit”。
答案 2 :(得分:1)
感谢Remko的链接,我找到了一个临时解决方案,直到该功能得到了Log4j2的改进。解决方案是使用RoutingAppender和Filters。这就是我的log4j2配置的样子(我已经定义了属性,但我没有在这里显示它们):
<appenders>
<appender name="applicationAppender" type="RollingFile" fileName="${logFileName}" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true">
<layout type="PatternLayout" pattern="${logPattern}" />
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="${logFileSize}" />
</Policies>
<DefaultRolloverStrategy max="${logFileCount}" />
</appender>
<Routing name="contextSpecificAppender">
<Routes pattern="$${ctx:contextId}">
<Route>
<appender name="Rolling-${ctx:contextId}" type="RollingFile" fileName="logs/${ctx:contextId}.log" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true">
<layout type="PatternLayout" pattern="${logPattern}" />
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="${logFileSize}" />
</Policies>
<DefaultRolloverStrategy max="${logFileCount}" />
</appender>
</Route>
</Routes>
</Routing>
</appenders>
<loggers>
<root level="info">
<appender-ref ref="contextSpecificAppender">
<ThreadContextMapFilter onMatch="DENY" onMismatch="ACCEPT">
<KeyValuePair key="contextId" value="" />
</ThreadContextMapFilter>
</appender-ref>
<appender-ref ref="applicationAppender">
<ThreadContextMapFilter onMatch="ACCEPT" onMismatch="DENY">
<KeyValuePair key="contextId" value="" />
</ThreadContextMapFilter>
</appender-ref>
</root>
</loggers>
我做的是调用ThreadContext.put(“contextId”,“”)或ThreadContext.put(“contextId”,“something”),具体取决于我想要记录的appender。 我希望这个狂野的功能很快就会实现,但与此同时,这个解决方案对我来说已经足够了。
谢谢!
答案 3 :(得分:0)
感谢hveiga跟进并发布您的解决方案,这很有帮助。我想说你可以通过添加第二条路线来避免过滤器解决方案。它会路由所有没有路由密钥值的消息,如下所述:http://logging.apache.org/log4j/2.x/faq.html#separate_log_files
所以你更新的log4j配置看起来像这样。
<appenders>
<appender name="applicationAppender" type="RollingFile" fileName="${logFileName}" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true">
<layout type="PatternLayout" pattern="${logPattern}" />
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="${logFileSize}" />
</Policies>
<DefaultRolloverStrategy max="${logFileCount}" />
</appender>
<Routing name="contextSpecificAppender">
<Routes pattern="$${ctx:contextId}">
<Route>
<appender name="Rolling-${ctx:contextId}" type="RollingFile" fileName="logs/${ctx:contextId}.log" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true">
<layout type="PatternLayout" pattern="${logPattern}" />
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="${logFileSize}" />
</Policies>
<DefaultRolloverStrategy max="${logFileCount}" />
</appender>
</Route>
<Route ref="applicationAppender" key="$${ctx:contextId}">
</Route>
</Routes>
</Routing>
</appenders>
<loggers>
<root level="info">
<appender-ref ref="contextSpecificAppender"/>
</root>
</loggers>
在您的应用程序中,您可以通过调用ThreadContext.put(&#34; contextId&#34;,&#34;某些&#34;)来设置ThreadContext,并在完成后通过调用ThreadContext.clear清除它。 ()或ThreadContext.remove(&#34; contextId&#34;)
最后,我使用了
<RollingFile>
元素(如上面链接的示例)而不是
<appender type="RollingFile">
你使用的元素。我相信当你从log4j迁移到log4j2时,这是首选。