Is there a low overhead way to enable/disable a given appender based on the value of an environment variable or system property?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Is there a low overhead way to enable/disable a given appender based on the value of an environment variable or system property?

Behrang Saeedzadeh
Let’s say I have three appenders:

<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
%logger{36} - %msg%n"/>
        </Console>

        <File name="File" fileName="application.log">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
%logger{36} - %msg%n" />
        </File>

        <SMTP name="SMTP"
              subject="App: Error"
              from="[hidden email]"
              to="[hidden email]"
              smtpHost="mailserver"
              smtpPort="25"
              bufferSize="100">
        </SMTP>
    </Appenders></Configuration>

I want to enable/disable these appenders using system properties in
different environments.

One option is to control this using scripts:

<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
    <Scripts>
        <Script name="isConsoleAppenderEnabled" language="groovy"><![CDATA[
            return System.getProperty("CONSOLE_APPENDER_ENABLED",
'true').equalsIgnoreCase('true');
        ]]></Script>

        <Script name="isFileAppenderEnabled" language="groovy"><![CDATA[
            return System.getProperty("FILE_APPENDER_ENABLED",
'true').equalsIgnoreCase('true');
        ]]></Script>

        <Script name="isSmtpAppenderEnabled" language="groovy"><![CDATA[
            return System.getProperty("SMTP_APPENDER_ENABLED",
'true').equalsIgnoreCase('true');
        ]]></Script>
    </Scripts>

    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
%logger{36} - %msg%n"/>
        </Console>

        <File name="File" fileName="application.log">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
%logger{36} - %msg%n" />
        </File>

        <SMTP name="SMTP"
              subject="App: Error"
              from="[hidden email]"
              to="[hidden email]"
              smtpHost="smtp.example.com"
              smtpPort="25"
              bufferSize="5">
        </SMTP>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console">
                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
                    <ScriptRef ref="isConsoleAppenderEnabled"/>
                </ScriptFilter>
            </AppenderRef>

            <AppenderRef ref="File">
                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
                    <ScriptRef ref="isFileAppenderEnabled"/>
                </ScriptFilter>
            </AppenderRef>

            <AppenderRef ref="SMTP">
                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
                    <ScriptRef ref="isSmtpAppenderEnabled"/>
                </ScriptFilter>
            </AppenderRef>
        </Root>
    </Loggers></Configuration>

However, this doesn’t really disable the appender, but computes the value
of the script for each log event and based on that suppresses the event
from being sent to the appender.

Another option is to write a custom appender that implements this logic and
that can decorate other appenders to achieve this behavior.

But I was wondering if there’s already a built-in feature available that
can enable/disable appenders based on environment variables and/or system
properties?


Best regards,
Behrang Saeedzadeh
blog.behrang.org
Reply | Threaded
Open this post in threaded view
|

Re: Is there a low overhead way to enable/disable a given appender based on the value of an environment variable or system property?

Ralph Goers
Take a look at the ScriptAppenderSelector - http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptAppenderSelector <http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptAppenderSelector> - and see if that does what you want. If not, please let us know.

Ralph

> On Oct 26, 2019, at 5:26 AM, Behrang Saeedzadeh <[hidden email]> wrote:
>
> Let’s say I have three appenders:
>
> <?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
>    <Appenders>
>        <Console name="Console" target="SYSTEM_OUT">
>            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
> %logger{36} - %msg%n"/>
>        </Console>
>
>        <File name="File" fileName="application.log">
>            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
> %logger{36} - %msg%n" />
>        </File>
>
>        <SMTP name="SMTP"
>              subject="App: Error"
>              from="[hidden email]"
>              to="[hidden email]"
>              smtpHost="mailserver"
>              smtpPort="25"
>              bufferSize="100">
>        </SMTP>
>    </Appenders></Configuration>
>
> I want to enable/disable these appenders using system properties in
> different environments.
>
> One option is to control this using scripts:
>
> <?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
>    <Scripts>
>        <Script name="isConsoleAppenderEnabled" language="groovy"><![CDATA[
>            return System.getProperty("CONSOLE_APPENDER_ENABLED",
> 'true').equalsIgnoreCase('true');
>        ]]></Script>
>
>        <Script name="isFileAppenderEnabled" language="groovy"><![CDATA[
>            return System.getProperty("FILE_APPENDER_ENABLED",
> 'true').equalsIgnoreCase('true');
>        ]]></Script>
>
>        <Script name="isSmtpAppenderEnabled" language="groovy"><![CDATA[
>            return System.getProperty("SMTP_APPENDER_ENABLED",
> 'true').equalsIgnoreCase('true');
>        ]]></Script>
>    </Scripts>
>
>    <Appenders>
>        <Console name="Console" target="SYSTEM_OUT">
>            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
> %logger{36} - %msg%n"/>
>        </Console>
>
>        <File name="File" fileName="application.log">
>            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
> %logger{36} - %msg%n" />
>        </File>
>
>        <SMTP name="SMTP"
>              subject="App: Error"
>              from="[hidden email]"
>              to="[hidden email]"
>              smtpHost="smtp.example.com"
>              smtpPort="25"
>              bufferSize="5">
>        </SMTP>
>    </Appenders>
>
>    <Loggers>
>        <Root level="info">
>            <AppenderRef ref="Console">
>                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>                    <ScriptRef ref="isConsoleAppenderEnabled"/>
>                </ScriptFilter>
>            </AppenderRef>
>
>            <AppenderRef ref="File">
>                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>                    <ScriptRef ref="isFileAppenderEnabled"/>
>                </ScriptFilter>
>            </AppenderRef>
>
>            <AppenderRef ref="SMTP">
>                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>                    <ScriptRef ref="isSmtpAppenderEnabled"/>
>                </ScriptFilter>
>            </AppenderRef>
>        </Root>
>    </Loggers></Configuration>
>
> However, this doesn’t really disable the appender, but computes the value
> of the script for each log event and based on that suppresses the event
> from being sent to the appender.
>
> Another option is to write a custom appender that implements this logic and
> that can decorate other appenders to achieve this behavior.
>
> But I was wondering if there’s already a built-in feature available that
> can enable/disable appenders based on environment variables and/or system
> properties?
>
>
> Best regards,
> Behrang Saeedzadeh
> blog.behrang.org

Reply | Threaded
Open this post in threaded view
|

Re: Is there a low overhead way to enable/disable a given appender based on the value of an environment variable or system property?

Behrang Saeedzadeh
Hi Ralph,

Thanks for the reply. That worked for me, but I have a couple of
suggestions:

   1.

   In the documentation, it is not mentioned that the script can return null
   to signal that none of the appenders in that block’s AppenderSet should be
   selected. It is worthwhile to mention that in the docs.
   2.

   With how ScriptAppenderSelector is working now, the log configuration
   becomes quite verbose:

<?xml version="1.0" encoding="UTF-8"?><Configuration status="debug"
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>
            </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>
            </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="[hidden email]"
                      to="[hidden email]"
                      smtpHost="smtp.example.com"
                      smtpPort="25"
                      bufferSize="5">
                </SMTP>
            </AppenderSet>
        </ScriptAppenderSelector>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="SelectConsole"/>
        </Root>
    </Loggers></Configuration>

If the script could return a list of appenders to be selected instead of
just one appender, the configuration would become more concise:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" name="ScriptAppenderSelectorExample">
    <Appenders>
        <ScriptAppenderSelector name="SelectMultiple">
            <Script language="groovy"><![CDATA[
                def selected = []

                if (System.getProperty("CONSOLE_APPENDER_ENABLED",
'true').equalsIgnoreCase('true')) {
                    selected.add("Console")
                }

                if (System.getProperty("FILE_APPENDER_ENABLED",
'true').equalsIgnoreCase('true')) {
                    selected.add("File")
                }

                if (System.getProperty("SMTP_APPENDER_ENABLED",
'true').equalsIgnoreCase('true')) {
                    selected.add("SMTP")
                }

                return selected
            ]]></Script>
            <AppenderSet>
                <Console name="Console" target="SYSTEM_OUT">
                    <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t]
%-5level %logger{36} - %msg%n"/>
                </Console>
                <File name="File" fileName="application.log">
                    <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t]
%-5level %logger{36} - %msg%n" />
                </File>
                <SMTP name="SMTP"
                      subject="App: Error"
                      from="[hidden email]"
                      to="[hidden email]"
                      smtpHost="smtp.example.com"
                      smtpPort="25"
                      bufferSize="5">
                </SMTP>
            </AppenderSet>
        </ScriptAppenderSelector>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="SelectMultiple"/>
        </Root>
    </Loggers>
</Configuration>

If that makes sense, I can work on a PR.
Best regards,
Behrang Saeedzadeh
blog.behrang.org


On Sun, Oct 27, 2019 at 3:21 AM Ralph Goers <[hidden email]>
wrote:

> Take a look at the ScriptAppenderSelector -
> http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptAppenderSelector
> <
> http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptAppenderSelector>
> - and see if that does what you want. If not, please let us know.
>
> Ralph
>
> > On Oct 26, 2019, at 5:26 AM, Behrang Saeedzadeh <[hidden email]>
> wrote:
> >
> > Let’s say I have three appenders:
> >
> > <?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
> >    <Appenders>
> >        <Console name="Console" target="SYSTEM_OUT">
> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
> > %logger{36} - %msg%n"/>
> >        </Console>
> >
> >        <File name="File" fileName="application.log">
> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
> > %logger{36} - %msg%n" />
> >        </File>
> >
> >        <SMTP name="SMTP"
> >              subject="App: Error"
> >              from="[hidden email]"
> >              to="[hidden email]"
> >              smtpHost="mailserver"
> >              smtpPort="25"
> >              bufferSize="100">
> >        </SMTP>
> >    </Appenders></Configuration>
> >
> > I want to enable/disable these appenders using system properties in
> > different environments.
> >
> > One option is to control this using scripts:
> >
> > <?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
> >    <Scripts>
> >        <Script name="isConsoleAppenderEnabled"
> language="groovy"><![CDATA[
> >            return System.getProperty("CONSOLE_APPENDER_ENABLED",
> > 'true').equalsIgnoreCase('true');
> >        ]]></Script>
> >
> >        <Script name="isFileAppenderEnabled" language="groovy"><![CDATA[
> >            return System.getProperty("FILE_APPENDER_ENABLED",
> > 'true').equalsIgnoreCase('true');
> >        ]]></Script>
> >
> >        <Script name="isSmtpAppenderEnabled" language="groovy"><![CDATA[
> >            return System.getProperty("SMTP_APPENDER_ENABLED",
> > 'true').equalsIgnoreCase('true');
> >        ]]></Script>
> >    </Scripts>
> >
> >    <Appenders>
> >        <Console name="Console" target="SYSTEM_OUT">
> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
> > %logger{36} - %msg%n"/>
> >        </Console>
> >
> >        <File name="File" fileName="application.log">
> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
> > %logger{36} - %msg%n" />
> >        </File>
> >
> >        <SMTP name="SMTP"
> >              subject="App: Error"
> >              from="[hidden email]"
> >              to="[hidden email]"
> >              smtpHost="smtp.example.com"
> >              smtpPort="25"
> >              bufferSize="5">
> >        </SMTP>
> >    </Appenders>
> >
> >    <Loggers>
> >        <Root level="info">
> >            <AppenderRef ref="Console">
> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
> >                    <ScriptRef ref="isConsoleAppenderEnabled"/>
> >                </ScriptFilter>
> >            </AppenderRef>
> >
> >            <AppenderRef ref="File">
> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
> >                    <ScriptRef ref="isFileAppenderEnabled"/>
> >                </ScriptFilter>
> >            </AppenderRef>
> >
> >            <AppenderRef ref="SMTP">
> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
> >                    <ScriptRef ref="isSmtpAppenderEnabled"/>
> >                </ScriptFilter>
> >            </AppenderRef>
> >        </Root>
> >    </Loggers></Configuration>
> >
> > However, this doesn’t really disable the appender, but computes the value
> > of the script for each log event and based on that suppresses the event
> > from being sent to the appender.
> >
> > Another option is to write a custom appender that implements this logic
> and
> > that can decorate other appenders to achieve this behavior.
> >
> > But I was wondering if there’s already a built-in feature available that
> > can enable/disable appenders based on environment variables and/or system
> > properties?
> >
> >
> > Best regards,
> > Behrang Saeedzadeh
> > blog.behrang.org
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Is there a low overhead way to enable/disable a given appender based on the value of an environment variable or system property?

Behrang Saeedzadeh
On a closer look, it seems that returning null causes a non-fatal error:

2019-10-27 11:26:36,898 main ERROR No node named null in
org.apache.logging.log4j.core.appender.AppenderSet@71f67a79
2019-10-27 11:26:36,900 main ERROR Null object returned for
ScriptAppenderSelector in Appenders.
2019-10-27 11:26:36,902 main ERROR Unable to locate appender
"SelectSMTP" for logger config "root"
2019-10-27 11:26:37,057 main ERROR No node named null in
org.apache.logging.log4j.core.appender.AppenderSet@48bfb884
2019-10-27 11:26:37,058 main ERROR Null object returned for
ScriptAppenderSelector in Appenders.
2019-10-27 11:26:37,059 main ERROR Unable to locate appender
"SelectSMTP" for logger config "root"


Best regards,
Behrang Saeedzadeh
blog.behrang.org


On Sun, Oct 27, 2019 at 11:02 AM Behrang Saeedzadeh <[hidden email]>
wrote:

> Hi Ralph,
>
> Thanks for the reply. That worked for me, but I have a couple of
> suggestions:
>
>    1.
>
>    In the documentation, it is not mentioned that the script can return
>    null to signal that none of the appenders in that block’s AppenderSet
>    should be selected. It is worthwhile to mention that in the docs.
>    2.
>
>    With how ScriptAppenderSelector is working now, the log configuration
>    becomes quite verbose:
>
> <?xml version="1.0" encoding="UTF-8"?><Configuration status="debug" 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>
>             </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>
>             </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="[hidden email]"
>                       to="[hidden email]"
>                       smtpHost="smtp.example.com"
>                       smtpPort="25"
>                       bufferSize="5">
>                 </SMTP>
>             </AppenderSet>
>         </ScriptAppenderSelector>
>     </Appenders>
>     <Loggers>
>         <Root level="info">
>             <AppenderRef ref="SelectConsole"/>
>         </Root>
>     </Loggers></Configuration>
>
> If the script could return a list of appenders to be selected instead of
> just one appender, the configuration would become more concise:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <Configuration status="debug" name="ScriptAppenderSelectorExample">
>     <Appenders>
>         <ScriptAppenderSelector name="SelectMultiple">
>             <Script language="groovy"><![CDATA[
>                 def selected = []
>
>                 if (System.getProperty("CONSOLE_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) {
>                     selected.add("Console")
>                 }
>
>                 if (System.getProperty("FILE_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) {
>                     selected.add("File")
>                 }
>
>                 if (System.getProperty("SMTP_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) {
>                     selected.add("SMTP")
>                 }
>
>                 return selected
>             ]]></Script>
>             <AppenderSet>
>                 <Console name="Console" target="SYSTEM_OUT">
>                     <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
>                 </Console>
>                 <File name="File" fileName="application.log">
>                     <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
>                 </File>
>                 <SMTP name="SMTP"
>                       subject="App: Error"
>                       from="[hidden email]"
>                       to="[hidden email]"
>                       smtpHost="smtp.example.com"
>                       smtpPort="25"
>                       bufferSize="5">
>                 </SMTP>
>             </AppenderSet>
>         </ScriptAppenderSelector>
>     </Appenders>
>     <Loggers>
>         <Root level="info">
>             <AppenderRef ref="SelectMultiple"/>
>         </Root>
>     </Loggers>
> </Configuration>
>
> If that makes sense, I can work on a PR.
> Best regards,
> Behrang Saeedzadeh
> blog.behrang.org
>
>
> On Sun, Oct 27, 2019 at 3:21 AM Ralph Goers <[hidden email]>
> wrote:
>
>> Take a look at the ScriptAppenderSelector -
>> http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptAppenderSelector
>> <
>> http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptAppenderSelector>
>> - and see if that does what you want. If not, please let us know.
>>
>> Ralph
>>
>> > On Oct 26, 2019, at 5:26 AM, Behrang Saeedzadeh <[hidden email]>
>> wrote:
>> >
>> > Let’s say I have three appenders:
>> >
>> > <?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
>> >    <Appenders>
>> >        <Console name="Console" target="SYSTEM_OUT">
>> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
>> > %logger{36} - %msg%n"/>
>> >        </Console>
>> >
>> >        <File name="File" fileName="application.log">
>> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
>> > %logger{36} - %msg%n" />
>> >        </File>
>> >
>> >        <SMTP name="SMTP"
>> >              subject="App: Error"
>> >              from="[hidden email]"
>> >              to="[hidden email]"
>> >              smtpHost="mailserver"
>> >              smtpPort="25"
>> >              bufferSize="100">
>> >        </SMTP>
>> >    </Appenders></Configuration>
>> >
>> > I want to enable/disable these appenders using system properties in
>> > different environments.
>> >
>> > One option is to control this using scripts:
>> >
>> > <?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
>> >    <Scripts>
>> >        <Script name="isConsoleAppenderEnabled"
>> language="groovy"><![CDATA[
>> >            return System.getProperty("CONSOLE_APPENDER_ENABLED",
>> > 'true').equalsIgnoreCase('true');
>> >        ]]></Script>
>> >
>> >        <Script name="isFileAppenderEnabled" language="groovy"><![CDATA[
>> >            return System.getProperty("FILE_APPENDER_ENABLED",
>> > 'true').equalsIgnoreCase('true');
>> >        ]]></Script>
>> >
>> >        <Script name="isSmtpAppenderEnabled" language="groovy"><![CDATA[
>> >            return System.getProperty("SMTP_APPENDER_ENABLED",
>> > 'true').equalsIgnoreCase('true');
>> >        ]]></Script>
>> >    </Scripts>
>> >
>> >    <Appenders>
>> >        <Console name="Console" target="SYSTEM_OUT">
>> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
>> > %logger{36} - %msg%n"/>
>> >        </Console>
>> >
>> >        <File name="File" fileName="application.log">
>> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
>> > %logger{36} - %msg%n" />
>> >        </File>
>> >
>> >        <SMTP name="SMTP"
>> >              subject="App: Error"
>> >              from="[hidden email]"
>> >              to="[hidden email]"
>> >              smtpHost="smtp.example.com"
>> >              smtpPort="25"
>> >              bufferSize="5">
>> >        </SMTP>
>> >    </Appenders>
>> >
>> >    <Loggers>
>> >        <Root level="info">
>> >            <AppenderRef ref="Console">
>> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>> >                    <ScriptRef ref="isConsoleAppenderEnabled"/>
>> >                </ScriptFilter>
>> >            </AppenderRef>
>> >
>> >            <AppenderRef ref="File">
>> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>> >                    <ScriptRef ref="isFileAppenderEnabled"/>
>> >                </ScriptFilter>
>> >            </AppenderRef>
>> >
>> >            <AppenderRef ref="SMTP">
>> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>> >                    <ScriptRef ref="isSmtpAppenderEnabled"/>
>> >                </ScriptFilter>
>> >            </AppenderRef>
>> >        </Root>
>> >    </Loggers></Configuration>
>> >
>> > However, this doesn’t really disable the appender, but computes the
>> value
>> > of the script for each log event and based on that suppresses the event
>> > from being sent to the appender.
>> >
>> > Another option is to write a custom appender that implements this logic
>> and
>> > that can decorate other appenders to achieve this behavior.
>> >
>> > But I was wondering if there’s already a built-in feature available that
>> > can enable/disable appenders based on environment variables and/or
>> system
>> > properties?
>> >
>> >
>> > Best regards,
>> > Behrang Saeedzadeh
>> > blog.behrang.org
>>
>>
Reply | Threaded
Open this post in threaded view
|

Re: Is there a low overhead way to enable/disable a given appender based on the value of an environment variable or system property?

Behrang Saeedzadeh
Which can be prevented using the Null appender ;)


<?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="[hidden email]"
                      to="[hidden email]"
                      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>




Best regards,
Behrang Saeedzadeh
blog.behrang.org


On Sun, Oct 27, 2019 at 11:28 AM Behrang Saeedzadeh <[hidden email]>
wrote:

> On a closer look, it seems that returning null causes a non-fatal error:
>
> 2019-10-27 11:26:36,898 main ERROR No node named null in org.apache.logging.log4j.core.appender.AppenderSet@71f67a79
> 2019-10-27 11:26:36,900 main ERROR Null object returned for ScriptAppenderSelector in Appenders.
> 2019-10-27 11:26:36,902 main ERROR Unable to locate appender "SelectSMTP" for logger config "root"
> 2019-10-27 11:26:37,057 main ERROR No node named null in org.apache.logging.log4j.core.appender.AppenderSet@48bfb884
> 2019-10-27 11:26:37,058 main ERROR Null object returned for ScriptAppenderSelector in Appenders.
> 2019-10-27 11:26:37,059 main ERROR Unable to locate appender "SelectSMTP" for logger config "root"
>
>
> Best regards,
> Behrang Saeedzadeh
> blog.behrang.org
>
>
> On Sun, Oct 27, 2019 at 11:02 AM Behrang Saeedzadeh <[hidden email]>
> wrote:
>
>> Hi Ralph,
>>
>> Thanks for the reply. That worked for me, but I have a couple of
>> suggestions:
>>
>>    1.
>>
>>    In the documentation, it is not mentioned that the script can return
>>    null to signal that none of the appenders in that block’s AppenderSet
>>    should be selected. It is worthwhile to mention that in the docs.
>>    2.
>>
>>    With how ScriptAppenderSelector is working now, the log configuration
>>    becomes quite verbose:
>>
>> <?xml version="1.0" encoding="UTF-8"?><Configuration status="debug" 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>
>>             </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>
>>             </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="[hidden email]"
>>                       to="[hidden email]"
>>                       smtpHost="smtp.example.com"
>>                       smtpPort="25"
>>                       bufferSize="5">
>>                 </SMTP>
>>             </AppenderSet>
>>         </ScriptAppenderSelector>
>>     </Appenders>
>>     <Loggers>
>>         <Root level="info">
>>             <AppenderRef ref="SelectConsole"/>
>>         </Root>
>>     </Loggers></Configuration>
>>
>> If the script could return a list of appenders to be selected instead of
>> just one appender, the configuration would become more concise:
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <Configuration status="debug" name="ScriptAppenderSelectorExample">
>>     <Appenders>
>>         <ScriptAppenderSelector name="SelectMultiple">
>>             <Script language="groovy"><![CDATA[
>>                 def selected = []
>>
>>                 if (System.getProperty("CONSOLE_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) {
>>                     selected.add("Console")
>>                 }
>>
>>                 if (System.getProperty("FILE_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) {
>>                     selected.add("File")
>>                 }
>>
>>                 if (System.getProperty("SMTP_APPENDER_ENABLED", 'true').equalsIgnoreCase('true')) {
>>                     selected.add("SMTP")
>>                 }
>>
>>                 return selected
>>             ]]></Script>
>>             <AppenderSet>
>>                 <Console name="Console" target="SYSTEM_OUT">
>>                     <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
>>                 </Console>
>>                 <File name="File" fileName="application.log">
>>                     <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
>>                 </File>
>>                 <SMTP name="SMTP"
>>                       subject="App: Error"
>>                       from="[hidden email]"
>>                       to="[hidden email]"
>>                       smtpHost="smtp.example.com"
>>                       smtpPort="25"
>>                       bufferSize="5">
>>                 </SMTP>
>>             </AppenderSet>
>>         </ScriptAppenderSelector>
>>     </Appenders>
>>     <Loggers>
>>         <Root level="info">
>>             <AppenderRef ref="SelectMultiple"/>
>>         </Root>
>>     </Loggers>
>> </Configuration>
>>
>> If that makes sense, I can work on a PR.
>> Best regards,
>> Behrang Saeedzadeh
>> blog.behrang.org
>>
>>
>> On Sun, Oct 27, 2019 at 3:21 AM Ralph Goers <[hidden email]>
>> wrote:
>>
>>> Take a look at the ScriptAppenderSelector -
>>> http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptAppenderSelector
>>> <
>>> http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptAppenderSelector>
>>> - and see if that does what you want. If not, please let us know.
>>>
>>> Ralph
>>>
>>> > On Oct 26, 2019, at 5:26 AM, Behrang Saeedzadeh <[hidden email]>
>>> wrote:
>>> >
>>> > Let’s say I have three appenders:
>>> >
>>> > <?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
>>> >    <Appenders>
>>> >        <Console name="Console" target="SYSTEM_OUT">
>>> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
>>> > %logger{36} - %msg%n"/>
>>> >        </Console>
>>> >
>>> >        <File name="File" fileName="application.log">
>>> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
>>> > %logger{36} - %msg%n" />
>>> >        </File>
>>> >
>>> >        <SMTP name="SMTP"
>>> >              subject="App: Error"
>>> >              from="[hidden email]"
>>> >              to="[hidden email]"
>>> >              smtpHost="mailserver"
>>> >              smtpPort="25"
>>> >              bufferSize="100">
>>> >        </SMTP>
>>> >    </Appenders></Configuration>
>>> >
>>> > I want to enable/disable these appenders using system properties in
>>> > different environments.
>>> >
>>> > One option is to control this using scripts:
>>> >
>>> > <?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN">
>>> >    <Scripts>
>>> >        <Script name="isConsoleAppenderEnabled"
>>> language="groovy"><![CDATA[
>>> >            return System.getProperty("CONSOLE_APPENDER_ENABLED",
>>> > 'true').equalsIgnoreCase('true');
>>> >        ]]></Script>
>>> >
>>> >        <Script name="isFileAppenderEnabled" language="groovy"><![CDATA[
>>> >            return System.getProperty("FILE_APPENDER_ENABLED",
>>> > 'true').equalsIgnoreCase('true');
>>> >        ]]></Script>
>>> >
>>> >        <Script name="isSmtpAppenderEnabled" language="groovy"><![CDATA[
>>> >            return System.getProperty("SMTP_APPENDER_ENABLED",
>>> > 'true').equalsIgnoreCase('true');
>>> >        ]]></Script>
>>> >    </Scripts>
>>> >
>>> >    <Appenders>
>>> >        <Console name="Console" target="SYSTEM_OUT">
>>> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
>>> > %logger{36} - %msg%n"/>
>>> >        </Console>
>>> >
>>> >        <File name="File" fileName="application.log">
>>> >            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level
>>> > %logger{36} - %msg%n" />
>>> >        </File>
>>> >
>>> >        <SMTP name="SMTP"
>>> >              subject="App: Error"
>>> >              from="[hidden email]"
>>> >              to="[hidden email]"
>>> >              smtpHost="smtp.example.com"
>>> >              smtpPort="25"
>>> >              bufferSize="5">
>>> >        </SMTP>
>>> >    </Appenders>
>>> >
>>> >    <Loggers>
>>> >        <Root level="info">
>>> >            <AppenderRef ref="Console">
>>> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>>> >                    <ScriptRef ref="isConsoleAppenderEnabled"/>
>>> >                </ScriptFilter>
>>> >            </AppenderRef>
>>> >
>>> >            <AppenderRef ref="File">
>>> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>>> >                    <ScriptRef ref="isFileAppenderEnabled"/>
>>> >                </ScriptFilter>
>>> >            </AppenderRef>
>>> >
>>> >            <AppenderRef ref="SMTP">
>>> >                <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
>>> >                    <ScriptRef ref="isSmtpAppenderEnabled"/>
>>> >                </ScriptFilter>
>>> >            </AppenderRef>
>>> >        </Root>
>>> >    </Loggers></Configuration>
>>> >
>>> > However, this doesn’t really disable the appender, but computes the
>>> value
>>> > of the script for each log event and based on that suppresses the event
>>> > from being sent to the appender.
>>> >
>>> > Another option is to write a custom appender that implements this
>>> logic and
>>> > that can decorate other appenders to achieve this behavior.
>>> >
>>> > But I was wondering if there’s already a built-in feature available
>>> that
>>> > can enable/disable appenders based on environment variables and/or
>>> system
>>> > properties?
>>> >
>>> >
>>> > Best regards,
>>> > Behrang Saeedzadeh
>>> > blog.behrang.org
>>>
>>>