繁体   English   中英

Log4j2 的 RoutingAppender 的通配符模式

[英]Wildcard pattern for RoutingAppender of Log4j2

我正在尝试使用 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 参数),但是我没有知道那个通配符是哪个值。

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

谢谢!

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

雷姆科

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

谢谢!

感谢 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 时,这是首选。

我对使用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”。

使用 lo4j2.properties 中的 RoutingAppender 创建动态多个日志文件

status=debug
name=PropertiesConfig

filter.threshold.type=ThresholdFilter
filter.threshold.level=debug

appenders=routing
appender.routing.type=Routing
appender.routing.name=Routing
appender.routing.routes.type=Routes
appender.routing.routes.pattern=$${ctx:keyname}

appender.routing.routes.route.type=Route

appender.routing.routes.route.rolling.type=RollingFile
appender.routing.routes.route.rolling.name=RollingFile
appender.routing.routes.route.rolling.fileName=${ctx:keyname}.log
appender.routing.routes.route.rolling.filePattern=${ctx:keyname}-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz
appender.routing.routes.route.rolling.layout.type=PatternLayout
appender.routing.routes.route.rolling.layout.pattern=%m%n
appender.routing.routes.route.rolling.policies.type=Policies
appender.routing.routes.route.rolling.policies.time.type=TimeBasedTriggeringPolicy
appender.routing.routes.route.rolling.policies.time.interval=2
appender.routing.routes.route.rolling.policies.time.modulate=true
appender.routing.routes.route.rolling.policies.size.type=SizeBasedTriggeringPolicy
appender.routing.routes.route.rolling.policies.size.size=1KB
appender.routing.routes.route.rolling.strategy.type=DefaultRolloverStrategy
appender.routing.routes.route.rolling.strategy.max=5

appender.routing.routes.route2.type=Route

appender.routing.routes.route2.key=P:/TestLogging/specialspecial
#appender.routing.routes.route.ref=Routes

appender.routing.routes.route2.rolling.type=RollingFile
appender.routing.routes.route2.rolling.name=RollingFile
appender.routing.routes.route2.rolling.fileName=${ctx:keyname}.log
appender.routing.routes.route2.rolling.filePattern=${ctx:keyname}-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz
appender.routing.routes.route2.rolling.layout.type=PatternLayout
appender.routing.routes.route2.rolling.layout.pattern=%d %p %C{1.} [%t] %m%n
appender.routing.routes.route2.rolling.policies.type=Policies
appender.routing.routes.route2.rolling.policies.time.type=TimeBasedTriggeringPolicy
appender.routing.routes.route2.rolling.policies.time.interval=2
appender.routing.routes.route2.rolling.policies.time.modulate=true
appender.routing.routes.route2.rolling.policies.size.type=SizeBasedTriggeringPolicy
appender.routing.routes.route2.rolling.policies.size.size=1KB
appender.routing.routes.route2.rolling.strategy.type=DefaultRolloverStrategy
appender.routing.routes.route2.rolling.strategy.max = 5
loggers=routing
logger.routing.level=debug
logger.routing.name=com.infy.demo
logger.routing.additivity=false
logger.routing.appenderRef.routing.ref=Routing
rootLogger.level=debug





public class TestLog4j2Logging {

private static final Logger log = LogManager.getLogger(TestLog4j2Logging.class);


public static void testMsg()
{
    
    String[] arr = {"Msg1111111111111","Msg222222222222222","Msg3333333333333","Msg44444444444"};
    for (String string : arr) {
        log.info(string);
        log.error(string);
        ThreadContext.remove("keyname");
        ThreadContext.put("keyname", "P:/TestLogging/specialspecial");
        log.debug(string);
    }
}


public static void main(String[] args) throws FileNotFoundException, IOException
{
    TestLog4j2Logging testLog4j2Logging = new TestLog4j2Logging();

    ThreadContext.put("keyname","P:/TestLogging/rollingtest");
    Configurator.initialize(null, "./properties/log4j2.properties");
    
    
    TestLog4j2Logging.testMsg();
    System.out.println("Messages are getting Logged");
}

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM