How to inject active spring profile into logback
Asked Answered
S

3

12

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

Suite answered 17/9, 2016 at 11:42 Comment(2)
if PROFILE is a property with key-value for the active profile, it should workWhitish
The PROFILE I'm looking for is the property spring.profiles.active which is defined in application.yml or via command line.Suite
M
23

This is a little late to answer, but I have successfully logged the Spring profile by renaming my "logback.xml" file to "logback-spring.xml", and accessed the profile like this (much) simplified version

<springProperty scope="context" name="ACTIVE_PROFILE" source="spring.profiles.active"/>

<appender name="GRAYLOG" class="com.github.pukkaone.gelf.logback.GelfAppender">

    <additionalField>environment=${ACTIVE_PROFILE}</additionalField>

</appender>

<root level="WARN">
    <appender-ref ref="GRAYLOG" />
</root>

It seems that "logback-spring.xml" can pick up the profile information.

The specific documentation is here.

Musicale answered 18/1, 2017 at 8:8 Comment(1)
It has worked perfectly for me but I didn't need to rename my logback.xml file. Thanks!!Indigo
B
5
  • 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.

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.

Biceps answered 17/9, 2016 at 16:45 Comment(4)
"Profiles is not recommended practice in general since what you test and what works in production is different" In the Caveats section you quote, I don't read anything in this way. It says rather : The set of beans registered between two profiles should probably be more similar than different. And that I agree with. Generally, web applications must move through multiple environments (dev, integration, etc... until production) and each one has specificities (OS, url, database, etc...) , ignoring that is a bad practice.Whitish
@davidhxxx URLs, databases, etc should not be defined in profiles. Those need to be defined as system vars, env vars, in JNDI or in application-specific configuration files. Please also don't take just one piece out of the article, it also says: Do not use profiles if a simpler approach can get the job doneBiceps
I don't take just one piece out of the article. Do not use profiles if a simpler approach can get the job done doesn't convey that URL, database information, etc... should not be in the profile. Besides, you say that these information could be in application-specific configuration files. But with Spring boot, profiles works also with application-specific configuration file than you can load when the server is launched or retrieved at runtime via a Property annotation. Profiles are not only Java code.Whitish
Sorry, I meant external application-specific configuration files. If you want a comprehensive answer on why profiles is a bad choice to configure apps, you could create a question. I won't be able to provide detailed explanation in comments..Biceps
W
3

Here is what I did for my project. Inside your logback.xml

<include resource="org/springframework/boot/logging/logback/defaults.xml"/>

<property resource="application.properties"/>

Then you can use properties which are defined in your application.properties file. ${MY-PROPERTY} In my application.properties I have a property for the logfile's name.

This does not work with application.yml => YAML property file because the yaml file is interpreted after logback init.

Warden answered 17/9, 2016 at 12:23 Comment(2)
In my project I'm using properties with application.yml (application-dev.yml and application-production.yml) ... so do you have other approach?Suite
Well no, I tried and it seems you can't. Maybe switch back to a property file, but watch out if you have special characters (property file is not utf-8 friendly) #29669549Warden

© 2022 - 2024 — McMap. All rights reserved.