Skip to content

Apache Log4j 2

Log4j quick guide

Key Components

  • loggers: Responsible for capturing logging information.
  • appenders: Responsible for publishing logging information to various preferred destinations.
  • layouts: Responsible for formatting logging information in different styles.

There are seven levels of logging defined within the API: OFF, DEBUG, INFO, ERROR, WARN, FATAL, and ALL.

Install

Download Log4j

$ gunzip apache-log4j-1.2.15.tar.gz
$ tar -xvf apache-log4j-1.2.15.tar
$ pwd
/usr/local/apache-log4j-1.2.15
$ export CLASSPATH=$CLASSPATH:/usr/local/apache-log4j-1.2.15/log4j-1.2.15.jar
$ export PATH=$PATH:/usr/local/apache-log4j-1.2.15/

Maven Snippet

<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>

log4j.properties

All the libraries should be available in CLASSPATH and yourlog4j.properties file should be available in PATH.

# Define the root logger with appender file
log = /usr/home/log4j
log4j.rootLogger = WARN, FILE

# Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=${log}/log.out

# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n

Snippets

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class MyTest {

 private static final Logger logger = LogManager.getLogger(); // equiv to  LogManager.getLogger(MyTest.class);
 private static final Logger logger = LogManager.getLogger("HelloWorld");

 public static void main(String[] args) {
      logger.setLevel(Level.WARN);
      logger.info("Hello, World!");
      // string interpolation
      logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());

      // pre-Java 8 style optimization: explicitly check the log level
      // to make sure the expensiveOperation() method is only called if necessary
      if (logger.isTraceEnabled()) {
  logger.trace("Some long-running operation returned {}", expensiveOperation());
      }

      // Java-8 style optimization: no need to explicitly check the log level:
      // the lambda expression is not evaluated if the TRACE level is not enabledlogger.trace("Some long-running operation returned {}", () -> expensiveOperation());
      }
}

// FORMATTER LOGGER
public static Logger logger = LogManager.getFormatterLogger("Foo");

logger.debug("Logging in user %s with birthday %s", user.getName(), user.getBirthdayCalendar());
logger.debug("Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());
//
logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());

Log4Shell Mitigation Context

Important: Versions of Log4j2 between 2.0-beta9 and 2.14.1 are vulnerable to Log4Shell (CVE-2021-44228). Fix: Always ensure you are using Log4j2 version 2.17.1 or newer.

Modern Dependencies

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.20.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.20.0</version>
</dependency>

Modern log4j2.xml Configuration

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>