Igor Piddubnyi
Igor Piddubnyi

Reputation: 144

Spring boot with log4j2. Configure log4j2 Spring-lookup

According to log4j2 documentation:

The Spring Boot Lookup retrieves the values of Spring properties from the Spring configuration. This Lookup will return null values until Spring Boot initializes application logging.

<File name="Application" fileName="application.log">
  <PatternLayout>
    <pattern>%d %p %c{1.} [%t] $${spring:spring.application.name} %m%n</pattern>
  </PatternLayout>
</File>

This Lookup requires log4j-spring-cloud-config-client be included in the application.

What is the proper way to configure such a lookup?

I tried to assemble the following application:

build.gradle

plugins {
    id 'org.springframework.boot' version '2.2.5.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
}

sourceCompatibility = '13'

repositories{
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-log4j2'
}

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
        exclude group: "ch.qos.logback", module: "logback-classic"
    }
}

main

@SpringBootApplication
public class DemoApplication implements ApplicationRunner {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    private final Logger logger = LogManager.getLogger();

    @Override
    public void run(ApplicationArguments args) throws Exception {
        logger.debug("Debugging log");
        logger.info("Info log");
        logger.warn("Hey, This is a warning!");
        logger.error("Oops! We have an Error. OK");
        logger.fatal("Damn! Fatal error. Please fix me.");
    }
}

application.yml

spring.application.name: Demo

log4j-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT" follow="true">
            <PatternLayout>
                <pattern>%d %p %c{1.} [%t] $${spring:spring.application.name} %m%n</pattern>
            </PatternLayout>
        </Console>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="ConsoleAppender" />
        </Root>
    </Loggers>
</Configuration>

I expect the resolver to properly substitute "Demo" as the application name, however this does not happen. Does spring-boot-starter-log4j2 missing some dependencies for this to work out of the box ?

Edit This is the most simplified case. In reality, I want to pass the application-name to the gelf graylog appender. And I would like to share the same logging configuration within multiple components. So workarounds, like defining a log4j property, or using spring logging configuration, are not suitable.

Upvotes: 2

Views: 9803

Answers (3)

Igor Piddubnyi
Igor Piddubnyi

Reputation: 144

Update 14.05.2021: Starting from log4j 2.14.0 there is a separate module for spring-lookup. Unfortunately, spring-boot still does not have high-enough dependency of log4j. But at least one can avoid using whole cloud-config-dependency.

implementation "org.apache.logging.log4j:log4j-api:${log4j2version}"
implementation "org.apache.logging.log4j:log4j-core:${log4j2version}"
implementation "org.apache.logging.log4j:log4j-spring-boot:${log4j2version}"

+++++++++++++++++++

Based on @rgoers input I was able to assemble minimal configuration to run log4j2 Spring lookup:

build.gradle

plugins {
    id 'org.springframework.boot' version '2.2.5.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
}

sourceCompatibility = '13'

repositories{
    mavenCentral()
}

ext{
    log4j2version = '2.13.1'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-log4j2'
    
    implementation "org.apache.logging.log4j:log4j-spring-cloud-config-client:${log4j2version}"
    implementation "org.apache.logging.log4j:log4j-api:${log4j2version}"
    implementation "org.apache.logging.log4j:log4j-core:${log4j2version}"
}

configurations {
    all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
        exclude group: "ch.qos.logback", module: "logback-classic"
        exclude group: "org.springframework.cloud", module: "spring-cloud-bus"
    }
}

Additionally, to disable cloud-config (which is required for look up, but might not be needed for the application):

bootstrap.yml (separate file additional to application.yml)

spring.cloud.config.enabled: false

Upvotes: 4

Sajeevan mp
Sajeevan mp

Reputation: 51

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-spring-cloud-config-client</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-bus</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

And my log4j2.xml has

<RollingFile name="rollingFile"
             fileName="${logHome}/${spring:spring.application.name}.log">

Upvotes: 4

rgoers
rgoers

Reputation: 9141

Spring boot starter log4j2 is almost certainly a version that doesn't yet support the Spring lookup. Instead of using Spring Boot Starter Log4j2 just directly include the log4j dependencies you need at version 2.13.0 or greater.

I recommend you look at https://github.com/apache/logging-log4j2/tree/log4j-2.13.1/log4j-spring-cloud-config/log4j-spring-cloud-config-samples/log4j-spring-cloud-config-sample-application for an example application. I have personally tested this setup and have a few projects based on it where I work.

Upvotes: 1

Related Questions