9
votes

I would like to change some properties from the log4j2.xml file depending on the my application.properties, for example define some properties and then substitute in the log4j2 those properties that are parameters.

I ran different approaches but I still did not get the right thing. I would like to have different configs depending on the environment (DEV, QA or PROD). How to accomplish this?

I'm trying to have this in my properties

#Place holders for log4j2.xml file
log.file.path=/opt/tomcat/logs
log.file.name=dummydummy
log.file.size=100 MB
log.level=DEBUG

My log4j2 below.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
    <Properties>
        <Property name="PID">????</Property>
        <property name="name">my-log</property>
    </Properties>
    <Appenders>
        <RollingFile name="file" fileName="${log.file.path}${log.file}.log"
            filePattern="${log.file.path}${log.file}-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout
                pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${sys:PID} --- [%t] %c{1}(%M:%L) : %m%n%wEx" />
            <Policies>
                <TimeBasedTriggeringPolicy /><!-- Rotated everyday -->
                <SizeBasedTriggeringPolicy size="${log.file.size}" /> <!-- Or every 100 MB -->
            </Policies>
        </RollingFile>
        <Console name="Console" target="SYSTEM_OUT" follow="true">
            <PatternLayout
                pattern="%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%t]}{faint} %clr{%c{1}(%M:%L)}{cyan} %clr{:}{faint} %m%n%wEx" />
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="org.hibernate.validator.internal.util.Version"
            level="warn" />
        <Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
        <Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
        <Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
        <Logger name="org.springframework.web" level="error" />

        <Root level="${log.level}">
            <AppenderRef ref="Console" />
            <AppenderRef ref="file" />
        </Root>
    </Loggers>
</Configuration>
4

4 Answers

14
votes

The properties lookup element allows to refer properties from an external properties file in the log4j configuration. For your example it should be something like this:

  1. A file env.properties contains the following properties:

    log.file.path=/opt/tomcat/logs
    log.file.name=dummydummy
    log.file.size=100 MB
    log.level=DEBUG
    

The properties lookup should be defined as properties of the log4j2.xml:

<Configuration>  
  <Properties>  
      <property name="log.file.path">${bundle:env:log.file.path}</property>  
      <property name="log.file.name">${bundle:env:log.file.name}</property>  
      <property name="log.file.size">${bundle:env:log.file.size}</property>  
      <property name="log.level">${bundle:env:log.level}</property>   
  </Properties>  

Now the properties may be referred in appenders with ${property_name} notation. Each property reference will be interpolated with the real value from the env.properties.

You can find another example of properties lookup here.

1
votes

As of Log4j 2.13.0 Log4j 2 now provides a Spring Lookup as part of its Spring Cloud Config support. It will allow you to reference properties defined in your application.properties or application.yml file of your Spring Boot application in the log4j2.xml.

0
votes

Ensure that log4j2 starter is added in the classpath and then remove logging related properties in application.properties then spring will load your log4j2.xml from resources folder. This way you can have full control over logging. If you want to substitute values then refer this link

Note:: If you have actuator in your project then remove spring boot logger starter

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
0
votes

Workaround in case you need just different property values in log4j2.xml config for different spring profiles (dev, test, prod, etc.). You could access spring profile files like: ${bundle:application-${sys:spring.profiles.active}:log.file.name}

application-dev.properties file:

log.file.name=dev_log

application-prod.properties file:

log.file.name=app_name

log4j2.xml config:

<Configuration>
    <Properties>
        <Property name="file_name">${bundle:application-${sys:spring.profiles.active}:log.file.name}</Property>
    </Properties>
    <Appenders>
        <RollingFile name="RollingFile"
                     fileName="/logs/${file_name}.log"
...
                 

NOTE: You have to add log.file.name property to each spring profile, log4j2 sees it just as separate text files and will not resolve default values from application.properties file and etc.