Skip to content

Lab 4: Log4j Logging

Goals

  • Convert printlns to use logging via the SLF4J logging facade
  • Configure and use the Log4J 2 logging framework instead of the default Logback logger

a. Replace System.out.println with Logger

  1. Add the following imports:

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
  2. Create the LOGGER

    private final static Logger LOGGER = LoggerFactory.getLogger(ClassName.class);
    

    Replace ClassName with the class containing the logger.

  3. Find all of the System.out.println statements and replace them with a mix of LOGGER.info and LOGGER.debug statements. Be sure to use the correct logging syntax, e.g.:

    LOGGER.info("{} has been instantiated.", this.getClass().getName());
    

b. Switch to Log4J 2

Since Logback is the default logger for Spring Boot, to use Log4J 2 instead, the Maven POM file needs to exclude Logback and add in Log4J 2. Modify the pom.xml file by adding the following two sections to the <dependencies> section. The first one excludes the Logback logger, the second one adds the Log4J 2 logger:

<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>

Try running the application again to see how things change. (The changes are slight, e.g., the class name for Log4J 2 displays as c.t.c.CoffeeOrderComponent instead of c.t.coffeekiosk.CoffeeOrderComponent, though this can be configured by the log4j2.xml file mentioned later.)

c. Use Log4J 2 Directly

If there are features from Log4J 2 that you need that aren't supported by the SLF4J facade, you can replace the slf4j imports with:

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

Then create the logger this way:

private static final Logger LOGGER = LogManager.getLogger(ClassName.class);

Try changing one of the classes to use the log4j-specific logger.

d. Change Logging Level

With Spring Boot, one way to change the logging level is to specify it in the application.properties file, e.g.:

logging.level.org.springframework.web=DEBUG
logging.level.com.tedmyoung=WARN

Now when you run the application, you won't see any logging output from our classes as its level was set to WARN. You can comment out (add a # at the beginning of a line) or remove the lines to restore the default level.


Custom Log4J 2 Configuration File

You can also use a log4j2.xml configuration file for more complex needs as shown below. This file would be placed in the /src/main/resources directory.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout
                pattern="%style{%d{ISO8601}}{black} %highlight{%-5level }[%style{%t}{bright,blue}] %style{%C{1.}}{bright,yellow}: %msg%n%throwable" />
        </Console>

        <RollingFile name="RollingFile"
            fileName="./logs/spring-boot-logger-log4j2.log"
            filePattern="./logs/$${date:yyyy-MM}/spring-boot-logger-log4j2-%d{-dd-MMMM-yyyy}-%i.log.gz">
            <PatternLayout>
                <pattern>%d %p %C{1.} [%t] %m%n</pattern>
            </PatternLayout>
            <Policies>
                <!-- rollover policies -->
                <OnStartupTriggeringPolicy /> <!-- rollover upon startup -->
                <SizeBasedTriggeringPolicy size="10 MB" /> <!-- rollover at 100MB file size -->
                <TimeBasedTriggeringPolicy /> <!-- rollover on a daily basis -->
            </Policies>
        </RollingFile>
    </Appenders>

    <Loggers>
        <!-- Default logging at INFO level -->
        <Root level="info">
            <AppenderRef ref="Console" />
            <AppenderRef ref="RollingFile" />
        </Root>

        <!-- LOG "com.tedmyoung.**" at WARN level -->
        <Logger name="com.tedmyoung" level="warn"></Logger>
    </Loggers>

</Configuration>