Spring Boot logging : use of system variables in log4j2.xml - spring-boot

I am running spring boot application as jar.
java -Dlogs.location=<path/to/my/logs> -jar my-app.jar
or
java -Dlogs.location=<path/to/my/logs> -jar my-app.jar --logs.location=<path/to/my/logs>
Here is a sample log4j2.xml configuration file
<?xml version="1.0" encoding="UTF-8"?>
<Configuration >
<Properties>
<Property name="base.log.dir">${sys:logs.location}</Property>
</Properties>
....
</Configuration>
Spring boot app is creating ${sys:logs.location} folder instead of correctly resolving system properties from jvm args.
Same configuration file working fine with Spring application.
I am unable to make logs.location configurable with my custom log4j2.xml file. Any help or suggestion is appreciated.
Please refer this sample project on github
I am using log4j2-spring.xml to configure log4j2.
I have looked at the StackOverflow q's. This answer reads properties bundle. But I want to read sys properties

Define a property like
<Properties>
<Property name="filePathVar"> ${sys:filepath:-/logs/app.log} </Property>
</Properties>
and use filePathVar like "${filePathVar}" in your xml file
and refer this for runtime args - https://stackoverflow.com/a/37439625/5055762
Note - /logs/app.log will be the default value if none is passed as a runtime arg

Related

Unable to write application logs using externalized Log4j2 XML configuration using Red Hat EAP 7.1.5

I have an application made of Spring Boot WAR packages that need to be migrated to Red Hat EAP 7.1.5.
In my current setup I do the following:
Each WAR has a dedicated log4j2 XML per environment.
This XML file name is defined in the web.xml
The folder containing the log4j2_xxxx.xml is added to the classpath in the JVM startup script.
The WARs are distributed across multiple run-time instances, with a possibility of one run-time hosting more than one WAR.
I would like to replicate the same using EAP. I do see the external log4j2 XML configuration being successfully loaded, however do not see any log statements being written at all.
I am using the following dependencies for packaging log4j2
org.springframework.boot.spring-boot-starter-log4j2 (version 1.5.7)
org.apache.logging.log4j.log4j-web (version 2.10.0)
I have tried the following:
Define a custom module under $JBOSS_HOME/modules/
Add the log4j2 XML in the same folder.
Refer this as global-module in standalone.xml
When I deploy a WAR I can see that the expected log file is created, which means the log4j2 XML configuration is being read successfully. However no logs get written at all in the application log file.
I have tried to get past this by defining a jboss-deployment-structure XML as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.apache.log4j" />
<module name="org.jboss.log4j.logmanager" />
<module name="org.jboss.logging" />
<module name="org.jboss.logging.commons.logging" />
<module name="org.jboss.logging.jul-to-slf4j-stub" />
</exclusions>
<exclude-subsystems>
<subsystem name="logging"/>
</exclude-subsystems>
</deployment>
</jboss-deployment-structure>
This results in the application logging being removed from the default JBOSS log (server.log) altogether but it does not write the logs to the designated log as well.
I would expect all the logging being done within the application to be written into the file defined by the external log4j2 XML configuration. Any idea what I am missing?

logback.xml change configuration at runtime

is it possible to change the configuration of the logback.xml at runtime with an external file? I dont want to change it programatically. I am using spring boot 1.5
Thanks in advance!
Use logging.config property. Can be a file relative to current working directory or an absolute path.
Option can be passed as argument when running a fat jar (with --logging.config=) or as environment variable (i.e. LOGGING_CONFIG=).
Logging levels can be set dynamically during runtime with actuator, see: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/actuator-api/html/#loggers.
For a logback config file to get you started, see:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.web" level="DEBUG"/>
</configuration>
From Configure Logback for Logging.

Access spring profile in log4j2 for spring boot application

How can i access the ${spring.profiles.active} value in log4j2 so that i can append the logfile name based on the profile?
log4j2.xml
<Properties>
<Property name="log-path">c:/logs</Property>
<Property name="targetEnv">${spring.profiles.active}</Property>
</Properties>
I tried with the following configuration and it worked
<Property name="targetEnv">${sys:spring.profiles.active}</Property>
This might help someone who is facing the same problem

JBoss 7 EAP Application Specific Logging with Shared Modules

Maybe I am just completely missing something but I am trying to configure log4j in JBoss 7 EAP with the main goal of isloating application ( WAR ) log messages to unique files.
Our environment has Spring ( 3.X ) configured as a module, and each WAR ( let's call them WAR A and WAR B ) has its own jboss deployment descriptor for Spring as well as a log4j.xml.
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<dependencies>
<module name="org.springframework.spring" slot="3.2" meta-inf="export" export="true" />
</dependencies>
</deployment>
</jboss-deployment-structure>
log4j.rootLogger = INFO, FILE
log4j.category.org.springframework=DEBUG
log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.FILE.File=${jboss.server.log.dir}/webapp_a.log
log4j.appender.FILE.ImmediateFlush=true
log4j.appender.FILE.Threshold=debug
log4j.appender.FILE.Append=true
log4j.appender.FILE.DatePattern='.' yyyy-MM-dd-a
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%d %-5p (%-6t) [%X{IP}] [%c] %m%n
Each application creates its own log files, however all the Spring logs are written to the JBoss server.log, and not the application specific log as I would expect. The idea is I would like to see only the spring logs that are relevant to the application in its log file
Am I missing something completely obvious, or really just not understanding how the classloading is working in JBoss 7 where this isn't even possible. Thanks
This is because you have Spring installed as a module. Modules log via the system log context which is configured via the logging subsystem.
Since the org.springframework.spring uses it's own class loader you really wouldn't want the org.springframework.spring module to log with an applications log context. The reason is any static loggers would be configured on whichever application configures the logger first.

Setting Spring applicationContext properties from POM file

I have the following configurations in my applicationContext.xml file:
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
<value>classpath:database.properties</value>
</list>
</property>
</bean>
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${smtp.host}" />
</bean>
with smtp.host being set in my POM file like so:
<build>
<defaultGoal>install</defaultGoal>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<application.env>local</application.env>
<profile.scope>compile</profile.scope>
<skip.test>true</skip.test>
<smtp.host>my.smtp.server</smtp.host>
</properties>
</profile>
Upon deploying my application, I ran into an error message saying that Spring was not able to resolve smtp.host. I added the following mapping to my application.properties file:
smtp.host=${smtp.host}
But Spring started to complain that I had a circular placeholder reference on the property. Is there anything I am missing?
Thanks!
You mix here two things up. The pom.xml is for building the application. Properties you define there has normally nothing to do with your application properties. And Maven profiles has nothing to do with Spring profiles. They are only named equaly.
You should configure your Spring Application as you can read here. You could -- what I would not suggest -- use your pom as property source.
The normal way would be to read it from a externalized configuration. As I do not know if you use Spring Boot, you can have a look at the Spring Boot Way and adapt it, if you use Spring without Boot.
So add a apllication.properties file into src/mein/resources like
smtp.host=my.smtp.server
If you use boot, you are done, else you have to add a
#PropertySource("classpath:/application.properties")
to your #Configuration
Here you are mixing the build and runtime phase of application which are mutually exclusive.
Mavens' role end once the build is complete thus any properties used perishes with it. Moreover application start up is agnostic to the tool / process used to build it and thus there isn't any information shared between them. Thus the idea to use properties specified in pom.xml is not feasible.
Regarding the circular reference the statement smtp.host=${smtp.host} is loosely similar to java code int i = i; which essentially has no effect because i is defined and assigned to itself.

Resources