如何根据java系统属性有条件地添加log4j2 appender?[英] How do I conditionally add log4j2 appender depending on java system property?

本文是小编为大家收集整理的关于如何根据java系统属性有条件地添加log4j2 appender?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在尝试弄清楚如何将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 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.另一方面,脚本评估可能会对记录性能产生负面影响.

    本文地址:https://www.itbaoku.cn/post/1574889.html

问题描述

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 instead of . 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.