I am implementing logging in a spring boot project with logback library. I want to load different logging configuration files according to my spring profiles (property 'spring.pofiles.active'). I have 3 files : logback-dev.xml, logback-inte.xml and logback-prod.xml. I am using spring boot version 1.2.2.RELEASE.
As you can read in spring boot documentation:
The various logging systems can be activated by including the appropriate libraries on the classpath, and further customized by providing a suitable configuration file in the root of the classpath, or in a location specified by the Spring Environment property logging.config. (Note however that since logging is initialized before the ApplicationContext is created, it isn’t possible to control logging from @PropertySources in Spring @Configuration files. System properties and the conventional Spring Boot external configuration files work just fine.)
So I tried to set 'logging.config' property in my application.properties file:
logging.config=classpath:/logback-${spring.profiles.active}.xml
But when i start my application, my logback-{profile}.xml is not loaded...
I think logging is a common problem that all projects using spring boot have encountered. Am I on the right track with the above approach? I have other solutions that work, but I find them not as elegant (conditional parsing with Janino in logback.xml file or command line property).
By default, Spring Boot picks up the native configuration from its default location for the system (such as classpath:logback. xml for Logback), but you can set the location of the config file by using the "logging. config" property.
If you name your configuration file logback-spring. xml , rather than logback. xml , you can use <springProperty> to access properties from Spring's environment including those configured in application.
Spring Boot has a LoggingSystem abstraction that attempts to configure logging based on the content of the classpath. If Logback is available, it is the first choice. You can also set the location of a file to which to write the log (in addition to the console) by using "logging. file".
Spring Boot supports Log4j 2 for logging configuration if it is on the classpath. If you are using the starters for assembling dependencies that means you have to exclude Logback and then include log4j 2 instead. If you aren't using the starters then you need to provide jcl-over-slf4j (at least) in addition to Log4j 2.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With