Issue
Let's suppose we have a simple Spring-boot app:
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>11</java.version>
<log4j2.version>2.15.0</log4j2.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- other dependencies -->
</dependencies>
log4j2.xml (src/main/resources/)
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout disableAnsi="false">
<pattern>%style{%d{ISO8601}}{black} %highlight{%-5level }[%style{%t}{bright,blue}] %style{%C{3.}}{bright,yellow}: %highlight{[%p] %msg%n%throwable}</pattern>
</PatternLayout>
</Console>
<RollingFile name="RollingFile"
fileName="c:/tmp/sw-b2b-data-service/logs/sw-b2b-data-service.log"
filePattern="c:/tmp/sw-b2b-data-service/logs/$${date:yyyy-MM}/sw-b2b-data-service-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout>
<pattern>%d %p %C{3.} [%t] %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy
size="4 MB" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console" />
<AppenderRef ref="RollingFile" />
</Root>
</Loggers>
</Configuration>
I'm using Windows, so log4j2.xml contains lines like "file...=c:/tmp/...".
I use a relative path for log file location usually, but this time I've decided to move log files out of the project folder to a temporary dir. And now when I deploy the jar it contains log4j2.xml with those "file...=c:/tmp/..." lines in "BOOT-INF/classes".
I thought there'll be no problems with that config, cause we always override the default log4j2.xml using -Dlogging.config=./log4j.xml in the service's start line.
But now every time I start the service it creates a folder structure of "c:/tmp/.../logs/" in the service's working folder with an empty sw-b2b-data-service.log file inside.
Actual logs are going to the log file defined in the overriding log4j2.xml (something like %service's_root%/logs/sw-b2b-data-service.log).
How can I get rid of that folders (and empty file inside) creation?
Solution
When Spring Boot starts Log4j is configured twice:
- as soon as some
LogManager.getLogger
is called, Log4j performs automatic configuration (cf. Log4j documentation), - when Spring has initialized its environment, it configures Log4j again programmatically (see Spring documentation).
In your case log4j2.xml
is used to configure Log4j the first time (and creates the first file), whereas the value of the Spring property logging.config
is taken into account only during the second configuration.
To change this behavior your should:
- rename
log4j2.xml
tolog4j2-spring.xml
so that the file is not used during the first configuration (it will be used by Spring if you don't specifylogging.config
), - or, alternatively, set the system property
log4j2.configurationFile
to the location of the new configuration. This setting will work after the first configuration, but will be overridden as soon as Spring reconfigures the context.
Answered By - Piotr P. Karwasz
Answer Checked By - Marilyn (JavaFixing Volunteer)