Issue
I have Spring MVC web application deployed on tomcat. (Not Spring Boot)
I want to use external log file to have access to it during runtime. Log4j2 library.
log4j.configurationFile
parameter is used to enable external configuration.
Also I have external .yaml
file that stored on file system of server.
The behaviour now:
If i put the same log4j2.xml to my resources, everything works fine.
With external log4j2 config, the .log
file is created after application is started, and it has some logs about application initialization. But nothing is recorded further.
Also if I create additional appender on runtime - file is not created. So automatic reconfiguration does not work as well.
After some searches I came to this configuration for applying external .yaml
:
@Configuration
public class PropertyConfig {
public static final String ENV_HOME_VARIABLE = "APP_HOME";
public static final String MAIN_CONFIG_FILE_NAME = "app-config.yaml";
@Bean
public static PropertySourcesPlaceholderConfigurer properties(@Autowired ConfigurableEnvironment conf) throws MalformedURLException {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
String configPath = "file:" + System.getenv(ENV_HOME_VARIABLE) + "/" + MAIN_CONFIG_FILE_NAME;
yaml.setResources(new UrlResource(configPath));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
Map map = conf.getSystemProperties();
yaml.getObject().forEach((key, value) -> {
map.put(key, value);
});
return propertySourcesPlaceholderConfigurer;
}
}
Also here is log4j.configurationFile
initialization in app-config.yaml
:
log4j:
configurationFile: file:/home/user/appHome/app-log4j2.xml
And app-log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorinterval="30" status="WARN" >
<Appenders>
<!-- Rolling File Appender -->
<RollingFile name="rollingFileApplication" bufferSize="0" bufferedIO="false" append="true">
<FileName>/home/user/appHome/log/app.log</FileName>
<FilePattern>/home/user/appHome/log/archive/app%d{yyyy-MM-dd}.log.gz</FilePattern>
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss a} [%t] %-5level %logger{36} - %msg%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="/home/user/appHome/log/archive/" maxDepth="1">
<IfAll>
<IfFileName glob="app_*.log*" />
<IfLastModified age="7d" />
</IfAll>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="TRACE">
<AppenderRef ref="rollingFileApplication" level="TRACE"/>
</Root>
<Logger name="ua" additivity="true" level="TRACE">
<appender-ref ref="rollingFileApplication"/>
</Logger>
</Loggers>
</Configuration>
Records in app.log
after start:
2022-07-28 12:53:39 PM [localhost-startStop-1] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
2022-07-28 12:53:40 PM [localhost-startStop-1] TRACE org.springframework.core.io.support.PathMatchingResourcePatternResolver - Found Equinox FileLocator for OSGi bundle URL resolution
2022-07-28 12:54:10 PM [localhost-startStop-1] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
2022-07-28 12:54:10 PM [localhost-startStop-1] TRACE org.springframework.core.io.support.PathMatchingResourcePatternResolver - Found Equinox FileLocator for OSGi bundle URL resolution
2022-07-28 12:54:25 PM [localhost-startStop-1] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
2022-07-28 12:54:25 PM [localhost-startStop-1] TRACE org.springframework.core.io.support.PathMatchingResourcePatternResolver - Found Equinox FileLocator for OSGi bundle URL resolution
So the question is, why do you think it`s not working and how to make it work).
Ready to provide any additional information.
Will appreciate any suggestions or remarks.
Solution
After some searching I found a solution. Looks more like workaround, but it still works:
@Bean
public static PropertySourcesPlaceholderConfigurer properties(@Autowired ConfigurableEnvironment conf) throws MalformedURLException {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
String configPath = "file:" + System.getenv(ENV_HOME_VARIABLE) + "/" + MAIN_CONFIG_FILE_NAME;
yaml.setResources(new UrlResource(configPath));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
Map map = conf.getSystemProperties();
yaml.getObject().forEach((key, value) -> {
map.put(key, value);
});
// solution
LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
File file = new File(System.getenv(ENV_HOME_VARIABLE) + "/app-log4j2.xml");
// this will force a reconfiguration
context.setConfigLocation(file.toURI());
// solution
return propertySourcesPlaceholderConfigurer;
}
Answered By - Olexyi
Answer Checked By - Katrina (JavaFixing Volunteer)