问题描述
我正在尝试弄清楚如何将appender添加到logger上,取决于是否给出了Java System属性/设置.
所以,假设我有这样的基本配置:
<Logger name="myLogger" level="info" additivity="false"> <AppenderRef ref="myAppender1" /> <AppenderRef ref="myAppender2" /> </Logger>
因此,现在我想找出一种有条件的方法,仅在提供参数-paddappender2时才添加第二名.这样的东西:
<Logger name="myLogger" level="info" additivity="false"> <AppenderRef ref="myAppender1" /> <?if (${sys:enableAppender2:-false) == "true"}> <AppenderRef ref="myAppender2" /> </?if> </Logger>
我该怎么做?
我知道我可以在给定属性(" loglevel")上(如果未给出属性)上的给定属性(" infevel")上的级别动态.
<Logger name="test" level="${sys:logLevel:-info}" additivity="false">
我看着 for for for forters ,我可以' t弄清楚.当然,如果过滤器甚至是正确的方法.
推荐答案
解决方案没有任何脚本:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error" strict="true"> <Properties> <Property name="appenderToUse">stdout_${sys:LOG4J_LAYOUT:-plain}</Property> </Properties> <Appenders> <Appender type="Console" name="stdout_plain"> <Layout type="PatternLayout" pattern="%d [%t] %-5p %c - %m%n"/> </Appender> <Appender type="Console" name="stdout_json"> <Layout type="JSONLayout" compact="true" eventEol="true" stacktraceAsString="true" properties="true"/> </Appender> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="${appenderToUse}"/> </Root> </Loggers> </Configuration>
其他推荐答案
Robert Works提供的解决方案,但它并不有效,因为每对日志记录一次都会评估脚本.
更有效的解决方案,仅评估脚本一次是使用 ScriptAppenderSelector 与 NullAppender :
根据文档:
scriptAppenderSelector
构建配置时,ScriptAppenderselector Appender调用脚本来计算Appender名称.然后,Log4J使用ScriptAppenderSector的名称创建了一个名为AppenderSet下列出的appender.配置后,log4j忽略scriptAppenderSelector.
nullappender
一个忽略日志事件的附录.用于与1.2版和 方便的兼容性,用于构成脚本AppenDerselector .
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="ScriptAppenderSelectorExample"> <Appenders> <ScriptAppenderSelector name="SelectConsole"> <Script language="groovy"><![CDATA[ if (System.getProperty("CONSOLE_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) { return "Console" } else { return "Null" } ]]></Script> <AppenderSet> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <Null name="Null" /> </AppenderSet> </ScriptAppenderSelector> <ScriptAppenderSelector name="SelectFile"> <Script language="groovy"><![CDATA[ if (System.getProperty("FILE_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) { return "File" } else { return "Null" } ]]></Script> <AppenderSet> <File name="File" fileName="application.log"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </File> <Null name="Null" /> </AppenderSet> </ScriptAppenderSelector> <ScriptAppenderSelector name="SelectSMTP"> <Script language="groovy"><![CDATA[ if (System.getProperty("SMTP_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) { return "SMTP" } else { return "Null" } ]]></Script> <AppenderSet> <SMTP name="SMTP" subject="App: Error" from="log4j@example.com" to="support@example.com" smtpHost="smtp.example.com" smtpPort="25" bufferSize="5"> </SMTP> <Null name="Null" /> </AppenderSet> </ScriptAppenderSelector> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="SelectConsole"/> <AppenderRef ref="SelectFile"/> <AppenderRef ref="SelectSMTP"/> </Root> </Loggers> </Configuration>
参考
- 其他推荐答案
类似于 rgoers "> rgoers 解决方案,但使用 nashorn 而不是 groovy 的问题.该解决方案受益于Nashorn Engine是一部分的事实 Java 8因此不需要其他依赖项.
<Scripts> <Script name="isAppender2Enabled" language="nashorn"><![CDATA[ var System = Java.type('java.lang.System'), Boolean = Java.type('java.lang.Boolean'); Boolean.parseBoolean(System.getProperty('enableAppender2', 'false')); ]]></Script> </Scripts> <Loggers> <Logger name="myLogger" level="info" additivity="false"> <AppenderRef ref="myAppender1" /> <AppenderRef ref="myAppender2"> <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY"> <ScriptRef ref="isAppender2Enabled" /> </ScriptFilter> </AppenderRef> </Logger> </Loggers>
请注意,ScriptFilter每次发生log4j事件时都在评估脚本.因此,有可能在运行时间(通过更改系统属性的值)立即启用/禁用Appender.另一方面,脚本评估可能会对记录性能产生负面影响.
问题描述
I'm trying to figure out how I can add an appender to a logger dependent on whether a java system property is given / set.
So let's say I have a basic configuration like this:
<Logger name="myLogger" level="info" additivity="false"> <AppenderRef ref="myAppender1" /> <AppenderRef ref="myAppender2" /> </Logger>
So now I'd like to figure out a way to conditionally only add the 2nd appender if I provide a parameter -PaddAppender2. Something like this:
<Logger name="myLogger" level="info" additivity="false"> <AppenderRef ref="myAppender1" /> <?if (${sys:enableAppender2:-false) == "true"}> <AppenderRef ref="myAppender2" /> </?if> </Logger>
How do I do that?
I know I can for example make the level dynamic on a given property ("logLevel") like that (where "info" is the default if the property is not given):
<Logger name="test" level="${sys:logLevel:-info}" additivity="false">
I looked at the documentation for filters, and I can't figure it out. That is of course if filters are even the right way to go here.
推荐答案
Solution without any scripting:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error" strict="true"> <Properties> <Property name="appenderToUse">stdout_${sys:LOG4J_LAYOUT:-plain}</Property> </Properties> <Appenders> <Appender type="Console" name="stdout_plain"> <Layout type="PatternLayout" pattern="%d [%t] %-5p %c - %m%n"/> </Appender> <Appender type="Console" name="stdout_json"> <Layout type="JSONLayout" compact="true" eventEol="true" stacktraceAsString="true" properties="true"/> </Appender> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="${appenderToUse}"/> </Root> </Loggers> </Configuration>
其他推荐答案
The solution provided by Robert works, but it is not efficient as the script will be evaluated once per log record.
A more efficient solution that evaluates the script only once is to use ScriptAppenderSelector together with the NullAppender:
According to the docs:
ScriptAppenderSelector
When the configuration is built, the ScriptAppenderSelector appender calls a Script to compute an appender name. Log4j then creates one of the appender named listed under AppenderSet using the name of the ScriptAppenderSelector. After configuration, Log4j ignores the ScriptAppenderSelector.
NullAppender
An Appender that ignores log events. Use for compatibility with version 1.2 and handy for composing a ScriptAppenderSelector.
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="ScriptAppenderSelectorExample"> <Appenders> <ScriptAppenderSelector name="SelectConsole"> <Script language="groovy"><![CDATA[ if (System.getProperty("CONSOLE_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) { return "Console" } else { return "Null" } ]]></Script> <AppenderSet> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <Null name="Null" /> </AppenderSet> </ScriptAppenderSelector> <ScriptAppenderSelector name="SelectFile"> <Script language="groovy"><![CDATA[ if (System.getProperty("FILE_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) { return "File" } else { return "Null" } ]]></Script> <AppenderSet> <File name="File" fileName="application.log"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </File> <Null name="Null" /> </AppenderSet> </ScriptAppenderSelector> <ScriptAppenderSelector name="SelectSMTP"> <Script language="groovy"><![CDATA[ if (System.getProperty("SMTP_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) { return "SMTP" } else { return "Null" } ]]></Script> <AppenderSet> <SMTP name="SMTP" subject="App: Error" from="log4j@example.com" to="support@example.com" smtpHost="smtp.example.com" smtpPort="25" bufferSize="5"> </SMTP> <Null name="Null" /> </AppenderSet> </ScriptAppenderSelector> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="SelectConsole"/> <AppenderRef ref="SelectFile"/> <AppenderRef ref="SelectSMTP"/> </Root> </Loggers> </Configuration>
References
其他推荐答案
Similar to rgoers solution but using nashorn instead of groovy. This solution benefits from fact that Nashorn engine is part of Java 8 so there is no additional dependencies needed.
<Scripts> <Script name="isAppender2Enabled" language="nashorn"><![CDATA[ var System = Java.type('java.lang.System'), Boolean = Java.type('java.lang.Boolean'); Boolean.parseBoolean(System.getProperty('enableAppender2', 'false')); ]]></Script> </Scripts> <Loggers> <Logger name="myLogger" level="info" additivity="false"> <AppenderRef ref="myAppender1" /> <AppenderRef ref="myAppender2"> <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY"> <ScriptRef ref="isAppender2Enabled" /> </ScriptFilter> </AppenderRef> </Logger> </Loggers>
Note that ScriptFilter is evaluating the script every time when Log4j event occurs. Therefore it is possible to enable/disable the appender on the run time (by changing the value of the system property) with immediate effect. On the other hand, script evaluation can have negative impact on logging performance.