Wildcard pattern for RoutingAppender of Log4j2

烂漫一生 提交于 2019-11-28 00:50:33

问题


I am trying to use the new RoutingAppender of Log4j2 to route the different logs based on the MDC (ThreadContext in Log4j2). What I want to do is the following:

  • If MDC map has $contextId -> Append to $contextId appender (specific log)
  • If MDC does not have $contextId -> Append to main appender (general log)

I want to achieve this using a wildcard pattern in the tag and then filter using the key parameter in the for contextId (${ctx:contextId}) and using the default (without key paramenter) for the main appender, however I don't know which value is that wildcard.

Any help is appreciated, maybe I am approaching this from the wrong path. I have been reading about Filters but don't seem to work as I want.

Thanks!


回答1:


Does this answer your question? https://issues.apache.org/jira/browse/LOG4J2-326

Remko




回答2:


I was unhappy with the solution to define the fallback route with the trick described in https://issues.apache.org/jira/browse/LOG4J2-326 and http://logging.apache.org/log4j/2.x/faq.html#separate_log_files, because this forces me to duplicate the appender configuration contained in the routes. I do not need different appender configuration for the default route, but just a proper file name for the general log.

Given that the default property map is looked up for an property which is undefined in its context, see https://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution, I think the most straightforward way is just to define the default, e.g.

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

and in case the thread context does not have ${ctx:fruits} the "any_fruit" is taken.




回答3:


Thanks for the link Remko, I have found a temporary solution until that feature gets improved from the guys of Log4j2. The solution is using both RoutingAppender and Filters. This is how my log4j2 config looks like (I have properties defined but I am not showing them here):

<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>

What I do it is calling ThreadContext.put("contextId", "") or ThreadContext.put("contextId", "something") depending on what appender I want to log. I hope the wildward feature gets implemented soon, but for the meantime, this solution is enough for me.

Thanks!




回答4:


Thanks hveiga for following up and posting your solution, it was helpful. I wanted to say you can avoid your filter solution by adding a second 'route' that routes all messages with no value for your routing key as explained here: http://logging.apache.org/log4j/2.x/faq.html#separate_log_files

So your updated log4j config would look like this.

<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>

And in your application, you can just set the ThreadContext by calling ThreadContext.put("contextId", "something") and clear it when you are done by calling ThreadContext.clear() OR ThreadContext.remove("contextId")

Lastly, I used the

<RollingFile>

element (like the examples linked above) instead of

<appender type="RollingFile"> 

element you used. I believe this is preferred when you migrate to log4j2 from log4j.



来源:https://stackoverflow.com/questions/18279656/wildcard-pattern-for-routingappender-of-log4j2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!