Learn to configure log4j2.yaml file to output the log statements to the console, rolling files, etc. Also, learn to configure log4j2 appenders, levels, and patterns.
Please note it is recommended to use Log4j2 with SLF4J.
1. Log4j2 Dependencies
To include Log4j2, include the latest version of log4j-core and log4j-api dependencies. The Log4j2 uses Jackson to parse the JSON files – so let’s add its dependencies as well.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.31.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.31.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.15.0</version>
</dependency>
If you are using Gradle, include this:
dependencies {
implementation 'org.apache.logging.log4j:log4j-api:2.31.1'
implementation 'org.apache.logging.log4j:log4j-core:2.31.1'
implementation 'com.fasterxml.jackson.core:jackson-core:2.15.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.0'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.15.0'
}
If we want to use Log4j2 in a Spring Boot project, we must exclude the default Logback dependency and include Log4j2. This will ensure that Log4j2 is included and Spring Boot uses it as the default logging framework.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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>
</dependencies>
2. The Default Logging Behavior
The default behavior in Log4j2 is to log messages at INFO level and higher (e.g., WARN, ERROR, FATAL), and logs are sent to the console. DEBUG and TRACE messages are not shown unless explicitly configured.
By default, Log4j2 uses the console appender to send logs to the system’s standard output (usually the terminal). Log messages will appear in the console in a simple, human-readable format as follows:
%date{ISO8601} %-5level [%t] %logger{36} - %msg%n
The generated output will look like this:
2024-09-19 10:21:45,123 INFO [main] com.example.MyApp - Application started successfully
To change this behavior, we must provide a custom configuration using log4j2.yaml (or XML, properties or JSON configuration). Log4j2 will automatically detect configuration files if they are placed in the classpath.
In the case of Spring Boot, the framework automatically looks for a ‘log4j2.xml‘, ‘log4j2.yaml‘, or ‘log4j2.properties‘ file in the ‘src/main/resources’ folder.
The basic structure of a YAML configuration file is:
Configuration:
Properties:
Appenders:
Loggers:
3. Configuring log4j2.yaml for Console Logging
To configure Log4j2 to log to the console, create a log4j2.yaml file in the src/main/resources
directory or the application classpath:
Configuration:
status: error
Appenders:
Console:
name: ConsoleAppender
target: SYSTEM_OUT
PatternLayout:
pattern: "%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n"
Loggers:
Root:
level: info
AppenderRef:
- ref: ConsoleAppender
4. Configuring log4j2.yaml for Rolling Files
To log to files with automatic file rotation, modify the log4j2.yaml file. In the following configuration:
- FileAppender writes logs to a file named /logs/application.log. Log rotation is handled based on time and file size.
- TimeBasedTriggeringPolicy: This policy triggers a new log file every day.
- SizeBasedTriggeringPolicy: This policy triggers log file rotation when the file exceeds 10MB.
Logs will be written to both the console and a rolling file.
Configuration:
status: error
Appenders:
Console:
name: ConsoleAppender
target: SYSTEM_OUT
PatternLayout:
pattern: "%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n"
File:
name: FileAppender
fileName: logs/application.log
filePattern: logs/application-%d{yyyy-MM-dd}.log.gz
PatternLayout:
pattern: "%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n"
Policies:
TimeBasedTriggeringPolicy:
interval: 1
modulate: true
SizeBasedTriggeringPolicy:
size: 10MB
Loggers:
Root:
level: info
AppenderRef:
- ref: ConsoleAppender
- ref: FileAppender
5. Writing Log Statements
In Log4j2, we use LogManager.getLogger() to get a Logger instance with a specific name or class. Then use the logger instance to write the log messages at various log levels.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
public static void main(final String[] args) {
private static final Logger logger = LogManager.getLogger(Main.class);
logger.debug("Debug Message Logged !!!");
logger.info("Info Message Logged !!!");
logger.error("Error Message Logged !!!", new NullPointerException("NullError"));
}
}
When using Log4j2 with SLF4J, to log the statements, we get the Logger instance by using the SLF4J LoggerFactory class and its getLogger() method. Then we use log methods, such as info(), error(), and debug(), to write the log statements.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(final String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.debug("Debug Message Logged !!!");
logger.info("Info Message Logged !!!");
logger.error("Error Message Logged !!!", new NullPointerException("NullError"));
}
}
When you run the above program, we will get the below log statements in the console.
Happy Learning !!
Comments