Unable to use Spring Property Placeholders in logback.xml
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!
Solution 1:
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.
<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
.........
Solution 2:
${...}
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.
Solution 3:
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
)
Solution 4:
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.