Small question regarding how to achieve structured logging with a SpringBoot app, but using log4j2 (working with logback, but not log4j).
I have a super simple SpringBoot app:
@RestController
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@RequestMapping("/")
public String index(@RequestHeader("accept") String acceptHeader) {
MDC.put("acceptHeader", acceptHeader);
LoggerFactory.getLogger(getClass()).info("Hello");
return "Greetings from Spring Boot!";
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> function(ctx);
}
private void function(ApplicationContext ctx) {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
}
with a simple pom:
<properties>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.5.5</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.6</version>
</dependency>
</dependencies>
with a logback.xml (not log4j2.xml)
<configuration>
<appender name="jsonConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="jsonConsoleAppender"/>
</root>
</configuration>
And this is working fine, very happy, I am seeing the logs in JSON format, structured, very happy.
I am trying to get the same result, using log4j2. I thought it will "work out of the box" but when switching to log4j2.xml, the logs are back to non JSON.
Please note, in the pom.xml I have:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.5.5</version>
</dependency>
And the log4j2.xml with I am trying:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<JsonTemplateLayout>
<EventTemplateAdditionalField key="HOME_DIR" value="${env:HOME}"/>
</JsonTemplateLayout>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
I am very puzzled why this would not yield a structured JSON logging, but lost the structured JSON.
What went wrong please?