I'm using Log4j2 with a log4j2.properties configuration file, and I rely on environment variables for some settings. Here's a sample of my configuration:
rootLogger.level = INFO
rootLogger.appenderRefs = console
rootLogger.appenderRef.console.ref = ConsoleAppender
logger.customlog.name = my.custompackage
logger.customlog.level = ${env:APP_LOG_LEVEL:-INFO}
logger.customlog.appenderRefs = console${env:ENABLE_FLUENTD:true:-,fluentd}
logger.customlog.appenderRef.fluentd.ref = ${env:ENABLE_FLUENTD:true:-FluentdAppender}
appender.console.name = ConsoleAppender
appender.console.type = CONSOLE
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{HH:mm:ss,SSS} %-5p %-60c - %m%n
appender.fluentd.name = FluentdAppender
appender.fluentd.type = ${env:ENABLE_FLUENTD:-Socket}
appender.fluentd.host = ${env:FLUENTD_HOST:-127.0.0.1}
appender.fluentd.port = ${env:FLUENTD_PORT:-24224}
appender.fluentd.layout.type = PatternLayout
appender.fluentd.layout.pattern = ["logs", {"timestamp":"%d{ISO8601}", "level":"%p", "message":"%m"}
I would like a way to enable/disable appenders based on environmental variables. Specifically I would like to disable FluentdAppender when ENABLE_FLUENTD environmental variable is not set to true.
Is there a way to achieve this ?
There is a feature called "Arbiters" that allows you to conditionally insert configuration elements (see documentation). Using the default XML configuration file format, you can use it as follows:
<EnvironmentArbiter propertyName="ENABLE_FLUENTD" propertyValue="true">
<Socket name="FluentdAppender"
host="${env:FLUENTD_HOST:-127.0.0.1}"
port="${env:FLUENTD_PORT:-24224">
<JsonTemplateLayout/>
</Socket>
</EnvironmentArbiter>
The Java System Properties Configuration file format, which I really don't recommend, has a lot of quirks (see documentation) that render the usage of arbiters hard or impossible. With Java System Properties it should be possible to use:
appender.fluentd.type = EnvironmentArbiter
appender.fluentd.propertyName = ENABLE_FLUENTD
appender.fluentd.propertyValue = true
appender.fluentd.name = Dummy name required by Properties format
appender.fluentd.0.type = Socket
appender.fluentd.0.name = FluentdAppender
appender.fluentd.0.host = ${env:FLUENTD_HOST:-127.0.0.1}
appender.fluentd.0.port = ${env:FLUENTD_PORT:-24224}
appender.fluentd.0.layout.type = JsonTemplateLayout
Remark: If you want to output JSON, use a layout that outputs JSON like JSON Template Layout. Pattern layout should be used to output simple text. The pattern ["logs", {"timestamp":"%d{ISO8601}", "level":"%p", "message":"%m"}]
you are using does not escape JSON string values correctly. Moreover, if an exception is logged, its stack trace will be appended to this pattern.