6

我正在尝试使用 Log4j2 的新 RoutingAppender 基于 MDC(Log4j2 中的 ThreadContext)路由不同的日志。我想要做的是以下内容:

  • 如果 MDC 映射有 $contextId -> Append to $contextId appender(特定日志)
  • 如果 MDC 没有 $contextId -> Append to main appender (general log)

我想在标签中使用通配符模式来实现这一点,然后使用 for contextId (${ctx:contextId}) 中的 key 参数进行过滤,并对主 appender 使用默认值(没有 key 参数),但是我没有知道那个通配符是哪个值。

任何帮助表示赞赏,也许我是从错误的道路上解决这个问题的。我一直在阅读有关过滤器的信息,但似乎没有按我的意愿工作。

谢谢!

4

4 回答 4

2

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

雷姆科

于 2013-08-17T23:11:09.150 回答
2

感谢 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") 。我希望wildward特性能尽快实现,但同时,这个解决方案对我来说已经足够了。

谢谢!

于 2013-08-19T18:11:57.530 回答
2

感谢 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("contextId", "something") 设置 ThreadContext 并在完成后通过调用 ThreadContext.clear() 或 ThreadContext.remove("contextId") 清除它

最后,我使用了

<RollingFile>

元素(如上面链接的示例)而不是

<appender type="RollingFile"> 

你使用的元素。我相信当您从 log4j 迁移到 log4j2 时,这是首选。

于 2014-06-13T23:26:43.807 回答
1

我对使用https://issues.apache.org/jira/browse/LOG4J2-326http://logging.apache.org/log4j/2.x/中描述的技巧定义后备路由的解决方案不满意faq.html#separate_log_files,因为这迫使我复制路由中包含的附加程序配置。我不需要为默认路由设置不同的附加程序配置,而只需要为通用日志提供一个正确的文件名。

鉴于默认属性映射是在其上下文中查找未定义的属性,请参阅https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution,我认为最直接的方法只是定义默认值,例如

<Properties>
    <Property name="fruits">any_fruit</Property>
</Properties>

如果线程上下文没有 ${ctx:fruits} ,则采用“any_fruit”。

于 2016-09-14T09:23:30.807 回答