Leonel Leonel - 2 months ago 177
Java Question

How to inject active spring profile into logback

I'm using a spring boot project.

Environment:

ch.qos.logback:logback-core:jar:1.1.5
ch.qos.logback:logback-classic:jar:1.1.5
org.springframework.boot:spring-boot-starter-logging:jar:1.3.3.RELEASE


In my project I'm using properties with application.yml (application-dev.yml and application-production.yml)

Since the Logback Spring extension starts before Spring I'm not able to inject the spring.profiles.active into the logback.xml file.

This is a simpler version of my logback.xml file:

<configuration scan="true">

<property name="LOG_PATH" value="/var/log/" />
<property name="APP_NAME" value="xyz" />
<property name="PROFILE" value="-${spring.profiles.active}" />
<property name="CHARSET" value="utf-8" />
<property name="PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />

<appender name="APP-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}${APP_NAME}${PROFILE}.log</file>
<encoder>
<charset>${CHARSET}</charset>
<Pattern>${PATTERN}</Pattern>
</encoder>
</appender>

<logger name="a.b.c" level="INFO">
<appender-ref ref="APP-FILE" />
</logger>

<root level="INFO">
<appender-ref ref="APP-FILE"/>
</root>




The PROFILE I'm looking for is the property spring.profiles.active.

My goal is to have a log file on directory /var/log the files xyz-dev or xyz-production but I getting xyz-spring.profiles.active_IS_UNDEFINED.log instead of course.

Approaches:

1 - Using a component like:

@Component
public class InitializationService implements ApplicationListener<ContextRefreshedEvent> {

// inject spring profile active into logback.xml

}


is not working of course because the logback Spring extension starts before Spring Boot application.

2 - Using a property on the logback.xml like this

<file>${LOG_PATH}${APP_NAME}${PROFILE}.log</file>


The result is xyz-spring.profiles.active_IS_UNDEFINED.log

Answer
  • Since you're using Spring Boot you can define logging.file=blah.log. See official docs.
  • Or you can use vanilla Logback and pass a system variable: -DLOG_FILE=blah.log. For logback this variable means

Why you shouldn't use profiles:

What you're trying to do is not what spring profiles were created for. They are needed to switch on/off beans to activate/deactivate behaviour during startup. Profiles is not recommended practice in general since what you test and what works in production is different (though sometimes there is no other choice). See Caveats section of the original announcement.

Another problem with your usage of profiles is that multiple profiles can be activated at the same time. Profiles were created to switch on/off small unrelated parts. E.g. spring.profiles.active=cache-off,perf-monitoring-on or something of that kind.

Having all that said you can still define a profile and set logging.file=prod.log property within that profile. That's still very bad and not how profiles should be used, but that's better.