Log4j2的RoutingAppender的通配符模式

时间:2013-08-16 18:12:58

标签: java logging log4j log4j2

我正在尝试使用Log4j2的新RoutingAppender来根据MDC(Log4j2中的ThreadContext)路由不同的日志。我想做的是以下几点:

  • 如果MDC地图有$ contextId - >附加到$ contextId appender(特定日志)
  • 如果MDC没有$ contextId - >附加到主appender(通用日志)

我想在标记中使用通配符模式实现此目的,然后使用for contextId($ {ctx:contextId})中的key参数进行过滤,并使用默认(不带键参数)作为主appender,但是我不知道那个通配符是哪个值。

任何帮助都表示赞赏,也许我正在走错路。我一直在阅读有关过滤器的内容,但似乎没有按照我的意愿工作。

谢谢!

4 个答案:

答案 0 :(得分:2)

这是否回答了你的问题? https://issues.apache.org/jira/browse/LOG4J2-326

的Remko

答案 1 :(得分:2)

我对使用https://issues.apache.org/jira/browse/LOG4J2-326http://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时,这是首选。