Log Management and Analytics

Explore the full capabilities of Log Management and Analytics powered by SolarWinds Loggly

View Product Info

FEATURES

Infrastructure Monitoring Powered by SolarWinds AppOptics

Instant visibility into servers, virtual hosts, and containerized environments

View Infrastructure Monitoring Info

Application Performance Monitoring Powered by SolarWinds AppOptics

Comprehensive, full-stack visibility, and troubleshooting

View Application Performance Monitoring Info

Digital Experience Monitoring Powered by SolarWinds Pingdom

Make your websites faster and more reliable with easy-to-use web performance and digital experience monitoring

View Digital Experience Monitoring Info
Use Cases

Java Log4j 2 Configuration and Log Management

Start Free Trial

Fully Functional for 30 Days

Log4j 2 is one of the most widely used logging libraries for Java. It offers developers impressive performance and unparalleled flexibility, and it integrates with almost all logging platforms. This article discusses Log4j 2 configuration and how to use this logging library to manage log files.

Log4j 2 Configuration

One of the most powerful features of Log4j is its configuration capabilities. You can configure it via several different file formats, or you can let it use its default configuration.

Configuration Files

Log4j supports Java properties, YAML, JSON, and XML configuration files. The same ConfigurationFactory class loads the files, and except for the properties files, the files are structured similarly. The properties files are different because the syntax doesn’t have the same support for structured data.

Configuration Rules

Log4j configuration offers various options, so let’s start by going over the library’s rules to determine which file to use. First, Log4j checks the log4j.configurationFile system property. If it’s set, it will load the specified file and use it. Next, it looks on the classpath for a configuration file. Configuration files are named either log4j2-test or log4j2. Log4j searches for log4j2-test first. The type of file is identified by the extension. Log4j 2 looks for Java properties with the .properties extension first. Next, it looks for YAML with .yaml or .yml, or JSON with .json or .jsn. Finally, it looks for XML with an .xml extension. If no file is found, the default configuration is to log error and fatal messages to the console. These rules seem complicated. But we can condense them.

1. Check for a configuration property. If you want to use a custom configuration file name, this is your best bet.

2. Check for a test configuration file in the classpath. Look for properties, YAML, JSON, or XML, in that order.

3. Check for a production configuration file in the classpath. Look for properties, YAML, JSON, or XML, in that order.

4. Log to the console.

Use the Configuration File Property

If you do the math, Log4j has 12 different default configuration file names. If you don’t use log4j.configurationFile: then your application may load the wrong file. This could lead to surprises. Before you deploy your code, make sure your application is loading the right file. Either scan the classpath and make sure there’s only one Log4j 2 configuration file or, better yet, use the log4j.configurationFile property.

Log4j 2 Configuration Files

When it comes to Log4j 2 configuration, you have multiple options. For the examples, I’ll use YAML. Since Log4j uses a similar model for the other languages, you can still follow along and learn how the configurations work.

Basic Configuration

Let’s start with a configuration file that sets up Log4j with the default config.

Configuration:

  status: warn

  Appenders:

    Console:

      name: Console

      target: SYSTEM_OUT

      PatternLayout:

        Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

  Loggers:

    Root:

      level: error

      AppenderRef:

        ref: Console

From the top of the file, this config tells Log4j to do the following:

– Log internal messages that are WARN level or higher.

– Log them to the console using standard output.

– Format the message with a time stamp, the thread name, the level, the logger name, and then the message.

– Use this logger as the Root logger in the hierarchy.

Let’s cover this configuration in detail.

Log4j 2 Configuration Hierarchy

Log4j places loggers in a hierarchy, similar to class hierarchy in Java. All loggers are descendants of Root. Loggers that aren’t configured inherit the Root config. So, if you don’t specify a Log4j 2 configuration, all messages logged at the error level or higher go to the console. We’ll go over the logging level hierarchy later. Let’s say you want to troubleshoot a problem in your code but don’t want to turn on debug logging for the entire application because it would make the logs hard to manage.

Configuration:

  status: warn

  Appenders:

    Console:

      name: Console

      target: SYSTEM_OUT

      PatternLayout:

        Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

  Loggers:

      logger:

      name: com.company.BuggyClass

      level: debug

      additivity: false

      AppenderRef:

        ref: Console

    Root:

      level: error

      AppenderRef:

        ref: Console

The new Logger adds a new logger to the hierarchy. The logger created by com.company.BuggyClass logs debug messages, while the rest of the app falls through the Root logger and only logs error messages. This is a simple two-level hierarchy, but a logger hierarchy can have multiple levels. We’ll look at how below.

Log4j Levels

Log4j handles log levels, or severity, by priority. Trace is the lowest, and fatal is the highest. Here are the possible levels, in order from lowest to highest priority.

1. Trace

2. Debug

3. Info

4. Warn

5. Error

6. Fatal

If a logger is configured for debug, it will log any message that is debug through fatal. If it’s set for error, it will log only error or fatal messages.

Log4j Appenders

Appenders are what send log messages where they belong. The default configuration supplies a console appender.

Appenders:

  Console:

    name: Console

    target: SYSTEM_OUT

    PatternLayout:

      Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

A file appender puts messages in a file.

Appenders:

  File:

    name: File_Appender

    fileName: buggyclass.log

    PatternLayout:

      Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

Appenders have names for associating them with loggers. They have PatternLayouts that define how the messages are formatted. They also have type-specific values, like target for the console appender and fileName for the file appender. Let’s revisit our earlier config and see how appenders are associated with loggers.

Configuration:

  status: warn

  Appenders:

    Console:

      name: Console

      target: SYSTEM_OUT

      PatternLayout:

        Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

      BuggyFile:

      name: BuggyFile_Appender

      fileName: buggyclass.log

      PatternLayout:

        Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

      CompanyFile:

      name: CompanyFile_Appender

      fileName: company.log

      PatternLayout:

        Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

  Loggers:

    logger:

      -

        name: com.company.BuggyClass

        level: debug

        additivity: false

        AppenderRef:

          ref: BuggyFile_Appender

      -

        name: com.company.Main

        level: info

        additivity: false

        AppenderRef:

          ref: CompanyFile_Appender

    Root:

      level: error

      AppenderRef:

        ref: Console

Now the BuggyClass logger is still associated with its own appender.  But com.company has one too. So, BuggyClass will log debug messages while the rest of the application logs info messages. The rest of the application will print error messages to the console. So, by creating loggers, placing them in the hierarchy, and associating appenders with them, you route log messages to different destinations.

Log4j Formatting

All appenders have a Layout. In this example, we’re using PatternLayout, which is an instance of a Log4j layout class. Log4j has built-in layouts for logging messages in CSV, JSON, and various formats. PatternLayouts use formatting that works like C’s sprintf. The pattern defines how the log messages are assembled before they are logged. Each operator in the log pattern corresponds to a field in a log event. For example, we’re using the default log message. Here’s the pattern layout for it.

"%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"

– %dHH:mm:ss.SSS is the date, formatted as hour:minute:seconds.milliseconds.

– %t is the name of the thread logging the message.

– %level is the log level. The -5 instructs PatternLayout to pad up to five spaces. This is so INFO and WARN align with the other log levels.

– %logger is the logger name. {36}truncates the class name to 36 levels in the hierarchy.

– %msg is the log message.

– %n is a newline. PatternLayouts do not automatically start a new line for every message.

There are many operators for PatternLayout. For an exhaustive list, see the Log4j 2 configuration documentation.

Manage Logs With Different Appenders

Log4j offers a wide variety of logging appenders for managing logs.

Syslog Appender

The Linux syslog system is a log management system. With it, you can manage log files and your Linux system or forward your logs to another server or an aggregator like  SolarWinds® Loggly®. This configuration is more complex than other appenders. For details on this appender, see the documentation.

 Syslog:

      name: syslog

      host: 172.17.0.1

      port: 514

      protocol: UDP

      facility: local6

      connectTimeoutMillis: 10000

      reconnectionDelayMillis: 5000

      mdcId: mdc

      mdcExcludes: "X-B3-SpanId,X-B3-TraceId,X-Span-Export,spanExportable,spanId,traceId"

      messageId: mywebapp

      appName: mywebapp

      charset: UTF-8

      ignoreExceptions: true

      newLine: true

      format: RFC5424

      LoggerFields:

        KeyValuePair: !!pairs

          - key: priority

            value: "%p"

          - key: category

            value: "%c{0}"

          - key: pid

            value: "%pid"

          - key: traceSpanId

            value: "%X{traceId}/%X{spanId}"

          - key: exception

            value: "%ex"

Rolling File Appender

The Log4j RollingFileAppender will rotate  your log files when they reach a certain length, size, or age. This means when your log files reach the size limit or time limit, the current log file is saved, and a new log file is created. This configuration rolls the files at 100 kb and keeps no more than 30 old files in the logging directory. For details on this appender, see the documentation.

 RollingFile:

      - name: RollingFile_Appender

        fileName: ${log-path}/rollingfile.log

        filePattern: "logs/archive/rollingfile.log.%d{yyyy-MM-dd-hh-mm}.gz"

        PatternLayout:

          pattern: "[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"

        Policies:

          SizeBasedTriggeringPolicy:

            size: 100 KB

        DefaultRollOverStrategy:

          max: 30

Master Your Java Logging

With Log4j, you can manage your logging down to the class level, with customized formatting, prioritization, and routing for both your application and specific parts of your code. Then you can take your log management to the next step with SolarWinds Loggly. Sign up for a free trial today!

SolarWinds Loggly

See unified log analysis and monitoring for yourself.
Start FREE Trial

Fully Functional for 30 Days