How to make Log4j2 configurable by environment using Spring Boot 1.3.6.RELEASE
Asked Answered
A

5

8

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>
Aftersensation answered 9/8, 2016 at 20:5 Comment(0)
D
15

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.

Derryberry answered 15/8, 2016 at 20:50 Comment(5)
Thanks for your response, it's working now. I still have other question, how about if I have multiple property files (depending on the environement for example application.properties, application-dev. properties, etc), is there are way to swtich between files? Seems that log4j2 only picks the default application.propertiesAftersensation
You can create a dedicated log4j2 configuration for each environment/property file: log4j2-env-dev.xml with env-dev.properties, log4j2-env-test.xml with env-test.properties etc. You can provide the name of log4j2 configuration file as a jvm argument -Dlog4j.configurationFile=<config.filename>.Derryberry
if use env.yml, how to do?Abduct
@Abduct I have never used yml for log4j2. Try to look in the documentation.Derryberry
Hey Asch, using your solution I am able to get the property file but i still get the below error. Is there any way using which i can directly use to pass level to logger - WARN Error while converting string ["info"] to type [class org.apache.logging.log4j.Level]. Using default value [null]. java.lang.IllegalArgumentException: Unknown level constant ["INFO"]. at org.apache.logging.log4j.Level.valueOf(Level.java:320)Hellenistic
S
2

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.

Spiritual answered 12/2, 2020 at 20:48 Comment(1)
Nice! Had a look at logging.apache.org/log4j/2.x/changes-report.html. Any more documentation?Hamelin
C
2

Since log4j 2.14.0, you can now use Spring Boot environment variables without Spring Cloud and without doing direct reference to the properties file. You'll need at least Spring Boot 2.0.3

<property name="applicationName">${spring:spring.application.name}</property>

Documentation: https://logging.apache.org/log4j/2.x/log4j-spring-boot/index.html

Maven repository: https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-spring-boot

Control answered 12/1, 2022 at 1:6 Comment(2)
That is actually available since Log4j 2.13.0: see Ralph's answer.Thermoelectricity
No, Ralph's answer is about Spring Cloud Config support, I clarified that since 2.14.0 you don't need to import Spring Cloud If you search in mvn repository (mvnrepository.com/artifact/org.apache.logging.log4j/…) The Spring Cloud Config Client needs Spring Cloud to work, and that's a heavy dependence In the other hand, the Spring Boot support for Lo4j2, only needs Spring Context and Spring Boot (mvnrepository.com/artifact/org.apache.logging.log4j/…)Control
K
0

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>
Kiyokokiyoshi answered 9/8, 2016 at 20:8 Comment(2)
Thanks for the quick response but the application is loading fine the log4j2.xml; but is not replacing the variables with the values that I have in the property fileAftersensation
Here is the documentation of the string substitutor that log4j2 uses: logging.apache.org/log4j/log4j-2.2/log4j-core/apidocs/org/… , make sure the values you are using are not defined in spring. becasue spring boot has intelligent way to load the valuesKiyokokiyoshi
Q
0

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.

Quadruplet answered 24/12, 2021 at 10:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.