Search code examples
javaspringspring-bootlogbackslf4j

How to select Logback appender based on property file or environment variable


I have configured logback xml for a spring boot project.

I want to configure another appender based on the property configured. We want to create an appender either for JSON logs or for text log, this will be decided either by property file or by environment variable.

So I am thinking about the best approach to do this.

  • Using filters to print logs to 1 of the file (either to JSON or to Txt). But this will create both of the appenders. I want to create only 1 appender.
  • Use "If else" blocks in logback XML file. To put if else around appenders, loggers seems untidy and error prone. So will try to avoid as much as possible.
  • So now exploring options where I can add appender at runtime.

So I want to know if it is possible to add appender at runtime. And will it be added before spring boots up or it could be done anytime in the project.

What could be the best approach to include this scenario.


Solution

  • As you're already using Spring, I suggest using Spring Profiles, lot cleaner than trying to do the same programmatically. This approach is also outlined in Spring Boot docs.

    You can set an active profile from either property file:

    spring.profiles.active=jsonlogs
    

    or from environment value:

    spring_profiles_active=jsonlogs
    

    of from startup parameter:

    -Dspring.profiles.active=jsonlogs
    

    Then have separate configurations per profile:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
      <appender name="stdout-classic" class="ch.qos.logback.core.ConsoleAppender">
          <encoder>
              <pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n</pattern>
          </encoder>
      </appender>
      <appender name="stdout-json" class="ch.qos.logback.core.ConsoleAppender">
          <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
              <layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
                  <timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
                  <timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
                  <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
                      <prettyPrint>true</prettyPrint>
                  </jsonFormatter>
              </layout>
          </encoder>
      </appender>
      <!-- begin profile-specific stuff -->
        <springProfile name="jsonlogs">
            <root level="info">
                <appender-ref ref="stdout-json" />
            </root>
        </springProfile>
        <springProfile name="classiclogs">
            <root level="info">
                <appender-ref ref="stdout-classic" />
            </root>
        </springProfile>
    </configuration>