ypanag
ypanag

Reputation: 301

Use Environment Variables With Conditional Logic on Log4j2.properties

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 ?

Upvotes: 0

Views: 40

Answers (1)

Piotr P. Karwasz
Piotr P. Karwasz

Reputation: 16165

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.

Upvotes: 1

Related Questions