spring boot, logback and logging.config property spring boot, logback and logging.config property spring spring

spring boot, logback and logging.config property


I found a solution and I understood why spring doesn't use my 'logging.config' property defined in the application.properties file.

Solution and explanation :

When initializing logging, spring Boot only looks in classpath or environment variables.

The solution I used was to include a parent logback.xml file that included the right logging config file according to the spring profile.

logback.xml :

<configuration>    <include resource="logback-${spring.profiles.active}.xml"/></configuration>

logback-[profile].xml (in this case, logback-dev.xml) :

<included>    <!-- put your appenders -->    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">    <!-- encoders are assigned the type     ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->       <encoder>           <pattern>%d{ISO8601} %p %t %c{0}.%M - %m%n</pattern>           <charset>utf8</charset>        </encoder>    </appender>    <!-- put your loggers here -->    <logger name="org.springframework.web" additivity="false" level="INFO">        <appender-ref ref="CONSOLE" />    </logger>    <!-- put your root here -->    <root level="warn">        <appender-ref ref="CONSOLE" />    </root></included>

Note : 'spring.profiles.active' has to be set in command line arguments when starting the app. E.G for JVM properties : -Dspring.profiles.active=dev

Ref docs :

Edit (multiple active profiles) :In order to avoid multiple files, we could use conditional processing which requires Janino dependency (setup here), see conditional documentation.With this method, we can also check for multiple active profiles at the same time. E.G (I did not test this solution, so please comment if it does not work):

<configuration>    <if condition='"${spring.profiles.active}".contains("profile1")'>        <then>         <!-- do whatever you want for profile1 -->        </then>    </if>    <if condition='"${spring.profiles.active}".contains("profile2")'>        <then>         <!-- do whatever you want for profile2 -->        </then>    </if>    <!-- common config --></configuration>

See javasenior answer for another example of a conditional processing.


Another approach that could handle multiple profiles is to create a separate properties file for each environment.

application-prod.properties

logging.config=classpath:logback-prod.xml

application-dev.properties

logging.config=classpath:logback-dev.xml

application-local.properties

logging.config=classpath:logback-local.xml

BE AWARE

If you aren't careful you could end up logging somewhere unexpected

-Dspring.profiles.active=local,dev //will use logback-dev.xml-Dspring.profiles.active=dev,local //will use logback-local.xml


Instead of adding separate logback xmls for each profile or having the IF condition , I would suggest the following (If you have less difference in the xmls') for easy conditional processing :

<springProfile name="dev"><logger name="org.sample" level="DEBUG" /></springProfile><springProfile name="prod"><logger name="org.sample" level="TRACE" /></springProfile>