45

I have a Spring Boot console app using Logback. All of the properties (for the app as well as for Logback) are externalized into a standard application.properties file in the classpath. These properties are picked up just fine in the app itself, but are not picked up in the logback.xml file. It appears as though the logback.xml is processed before Spring Boot fires up, therefore the EL placeholders are not processed.

Using the FileNamePattern as an example, in the application.properties, I have something like this:

log.filePattern=/%d{yyyy/MM-MMMM/dd-EEEE}

and in logback.xml, I'll have this:

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <FileNamePattern>${log.logDirectory}${log.filePattern}.log
    </FileNamePattern>
</rollingPolicy>

When running the app, I'll see errors such as:

ERROR in ch.qos.logback.core.joran.spi.Interpreter@24:25 - 
RuntimeException in Action for tag [rollingPolicy]
java.lang.IllegalStateException: FileNamePattern
[log.logDirectory_IS_UNDEFINEDlog.filePattern_IS_UNDEFINED.log]
does not contain a valid DateToken

Similar code works just fine in other Spring (not Spring Boot) apps, so I'm curious if Spring Boot just behaves a bit differently.

Solution:

Thanks for the reply @Gary! Good to know about the difference between Spring EL and Logback's variables...I had assumed it was Spring that was in charge of parsing those variables for me. I did have the element, but that got me to thinking.

My application.properties file was outside of the jar, so Logback had no idea where to find it. By keeping my Spring-related properties in my external application.properties file, moving the logging-related properties into an application-internal.properties file (located inside the jar), and pointing Logback to that file (<property resource="application-internal.properties" />) got everything working as expected!

Betlista
  • 10,327
  • 13
  • 69
  • 110
brmc72
  • 465
  • 1
  • 4
  • 6

5 Answers5

86

Since Spring Boot 1.3 you have a better way of getting spring properties into your logback-spring.xml configuration:

Now you can just add a "springProperty" element.
The attribute name refers to the logback property and the attribute source refers to the spring property

<springProperty name="destination" source="my.loggger.extradest"/>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${destination}</file>
        ...
    </file>
</appender>

https://github.com/spring-projects/spring-boot/commit/055ace37f006120b0006956b03c7f358d5f3729f

edit: thanks to Anders

.........

Monish Sen
  • 1,773
  • 3
  • 20
  • 32
Lasse L
  • 1,278
  • 1
  • 9
  • 14
  • 1
    is there a logback-spring.groovy equivalent to that ^^? – Matthew Payne Feb 15 '17 at 20:56
  • 1
    where is the DOC for this thing ? – sashok_bg Mar 01 '17 at 13:33
  • 2
    https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html – oborovyk Apr 22 '17 at 15:12
  • @MatthewPayne did you ever find how to do this in groovy – WendyG Oct 31 '18 at 16:43
  • This is not a fool proof solution. If you externalize your logback-spring.xml file by including an external file and then change , sya, "maxSize" to 2KB from 100MB, you will see the files getting created as destination_IS_UNDEFINED.log. That's because as @Gary Russell has explained in his answer. – raikumardipak May 16 '20 at 20:23
45

${...} is not "Spring EL" in Spring; they are property placeholders.

I think you are confusing logback "variables" with Spring "Property Placeholders".

They just happen to use the same syntax ${...}.

logback knows nothing about the Spring property placeholder mechanism and vice-versa. You need to configure your logback variables according to the logback documentation and not in application.properties / application.yml which is strictly a Spring (boot) concept.

EDIT:

After a quick look at the logback docs, adding

<property resource="application.properties" />

to the logback.xml should work.

Betlista
  • 10,327
  • 13
  • 69
  • 110
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • 5
    Here's the link to said "logback docs": http://logback.qos.ch/manual/configuration.html#variableSubstitution – SunshinyDoyle Oct 19 '15 at 20:07
  • @Gary I want configurable file pattern extension. is this possible? or I want to override internal logback.xml with external logback.xml. is this possible? – parita porwal Mar 15 '18 at 09:50
  • For an external file (not in the classpath, but available on the filesystem): – Jean-Christophe May 15 '18 at 09:59
  • THANK YOU for the missing voodoo (the property resource thing). FYI: "application.yml" will also work... as I document here : https://stackoverflow.com/questions/33186668/spring-boot-logback-db-appender-properties/54288986#54288986 – granadaCoder Jan 23 '19 at 00:37
9

As answered above you can access the spring boot properties using the <springProperty> element...but a thing to keep in mind is that the logback configuration file must be named logback-spring.xml, it doesn't work if you name the file logback.xml (I'm using spring-boot 1.3.5.RELEASE)

anders
  • 814
  • 7
  • 12
  • 1
    Works for me using `logback-dev.xml` and `logback-prod.xml` with `spring-boot 1.3.3.RELEASE` – sdl Jul 13 '16 at 12:04
  • If still not work, check app config name it should be application.properties, or whatever name you specified to your app. Additional @PropertySource-es seems to be not working in this case – Daniel Hári Dec 04 '17 at 13:57
  • 1
    One more thing to keep in mind: at least for me, it didn't work until I renamed `application.properties` to `bootstrap.properties` – lubumbax May 07 '20 at 11:07
2

The solutions above work mostly for bootrap.properties. However, the only way to use properties from remote Spring Config Server in logback config I've currently found, is to apply them programatically:

@Component
public class LoggerConfiguration implements ApplicationListener<EnvironmentChangeEvent> {

    @Autowired protected Environment environment;

    @Override
    public void onApplicationEvent(EnvironmentChangeEvent event) {
        // enviroment here has already loaded all properties and you may alter logback config programatically
        ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
    }


}

Here is a good example how to customize logback with new appender this way.

Lukasz Frankowski
  • 2,955
  • 1
  • 31
  • 32
0

There is a way to map Spring properties to Logback properties and use them in the Conditions:

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="ACTIVE_PROFILE" source="spring.profiles.active"/>
<!--   defined in the application-prod.properties/>-->
<springProperty scope="context" name="SPRING_WRITER_DISABLED" source="writer.disabled"/>
<property name="LOGBACK_WRITER_DISABLED" value="${SPRING_WRITER_DISABLED}"/>

<if condition='property("LOGBACK_WRITER_DISABLED").equals("false")'>
    <then>
        <appender name="testappender" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${ACTIVE_PROFILE}/${HOSTNAME}/testappender.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                <fileNamePattern>
                    {ACTIVE_PROFILE}/${HOSTNAME}/testappender-%d{yyyy-MM-dd}.%i.log
                </fileNamePattern>
                <maxFileSize>300MB</maxFileSize>
                <maxHistory>3</maxHistory>
                <totalSizeCap>1GB</totalSizeCap>
            </rollingPolicy>
            <encoder>
                <pattern>%msg%n</pattern>
            </encoder>
        </appender>
        <logger name="testappender" level="INFO" additivity="false">
            <appender-ref ref="testappender"/>
        </logger>
    </then>
</if>
</configuration>
sereja
  • 1,356
  • 1
  • 8
  • 6