Spring Profile Specific Logging Behavior with Spring Boot

Technology: Spring Profiles provides conditional approach to load the parts of the application only in certain environments. It is used to load one of the same types of available beans based on environment configuration.

Using this approach without modifying the source code/configuration it will work for all three environments.

When starting our application we can define spring.profiles.active environment variable or we can pass –spring.profiles.active=<profile> to command when we can starting the application using Jar file.

Depending on profile also we can change the logging behavior.

Logback Configuration for Spring Boot Applications:

Spring Boot by default will check for logback-spring.xml in classpath for application logging configuration.

Some of the default configurations comes out of box with Spring-boot jar file in org/springframework/boot/logging/logback folder, we can re-use these things using include tag by providing the file path.


<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/> <logger name="org.springframework.controllers" level="WARN" additivity="false"> <appender-ref ref="CONSOLE"/> <appender-ref ref="FILE"/> </logger> <logger name="org.springframework.services" level="WARN" additivity="false"> <appender-ref ref="CONSOLE"/> <appender-ref ref="FILE"/> </logger> </configuration>

appenders we used here defined in base.xml which comes spring-boot jar file.

Logback Named Hierarchy:

In general logger name will be packaging structure of application, by default one logger will be present will the name root. Every logger will be child of the root logger.

Logger name will be case-sensitive, and they follow hierarchical naming rules. A logger will be parent to another logger if the name is followed by dot(.) is a prefix of the child name.

Example: if the logger named “org” is the parent of the logger named “org.springframework”, and “root” is the logger resides at the top of the logger hierarchy.

Logback Additivity:

Appenders are attached to the loggers. One logger may connect more than one appenders. The log messages are written to more than one appenders, to restriction this we will use extra attribute.

I.e., the result of a log declaration of logger A will move to all the appenders in A and its predecessor.

<?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <appender name="A" class="ch.qos.logback.core.FileAppender"> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <file>/logs/server.log</file> </appender> <appender name="B" class="ch.qos.logback.core.FileAppender"> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <file>/logs/server-test.log</file> </appender> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="A" /> <appender-ref ref="C" /> </root> <logger name="org" level="INFO"> <appender-ref ref="A" /> </logger> <logger name="org.springframework" level="INFO" > <appender-ref ref="B" /> </logger> <logger name="org.springframework.boot" level="INFO" additivity="false"> <appender-ref ref="C" /> </logger> <logger name="employee.director.manager.engineer.intern" level="INFO" additivity="false"> <appender-ref ref="FILE5" /> </logger> </configuration>

If the loggers statement is present in inside org package then A,C appenders will be invoked.

If the logger statement is present in org.springframework.boot then it will only append to C as its additivity is false, means it will propagate to its ancestor B and A.

Loggers have their Extra flag set to true by default.

Spring Boot Profile based Logging:

While we develop the application in our Java development company, we used to put the log level as DEBUG to log the detailed information, but in production if keep the same log level size of the log will become huge, and, we don’t need the detailed messages, so generally we will keep WARN as log level in production. So, it’s every time while releasing the build we need to modify the log level if don`t implement profile-based logging.

Spring boot is addressing this using tag in logback xml file which is available from 1.3 version.

Example configuration using springProfile xml tag:

<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <springProfile name="dev "> <logger name="org.springframework.controllers" level="DEBUG" additivity="false"> <appender-ref ref="CONSOLE" /> </logger>> </springProfile> <springProfile name="production"> <logger name="org.springframework.controllers" level="WARN" additivity="false"> <appender-ref ref="FILE" /> </logger> </springProfile> </configuration>

For dev profile, log messages are appending to the console and for production profile messages are appending the to file.

There are other ways to do profile based using Janino library and profile prefixed property file loading in spring boot.

Using Janino Library:

Logback is supporting conditional processing of configuration using this library.

We can use , xml tags in log-back xml file.

Maven Dependency:

<dependency> <groupId>org.codehaus.janino</groupId> <artifactId>janino</artifactId> <version>2.7.8</version> </dependency>

Using Janino library the above xml file looks like below:

<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <if condition='property("spring.profiles.active").contains("dev")'> <then> <logger name="org.springframework.controllers" level="DEBUG" additivity="false"> <appender-ref ref="CONSOLE" /> </logger> </then> <else> <logger name="org.springframework.controllers" level="WARN" additivity="false"> <appender-ref ref="FILE" /> </logger> </else> </if> </configuration>


Spring Boot provides out of the box integration with logback logging framework, and also spring boot is added more feature on top it, for example springProfile is the one of the example for profile-based logging, and logback is also integrating with Janino library to provide the conditional based configuration.