Category Archives: LOG4J2

Log4j2: How to Mask Logs Personal/Confidential/SPI Information

You can configure Log4j2 LogEventConverter plugin for masking personal/confidential/SPI data. For example here we are masking credit card number, SSN and CVV of log statements.

Below Log4j2 dependencies you need to add with your application.

Pre-Requisite

Log4j2 Dependency

pom.xml entry


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

Log4j2.xml Configuration File

Below is basic console based configuration for masking where packages used for where loggers need to apply and masking plugin annotation as in below program. In PatternLayout used key as spi which is map with plugin which will mask log text and print as message.


<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://logging.apache.org/log4j/2.0/config"
       status="OFF" packages="com.mask.logs">
       <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT">
     <PatternLayout pattern="%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %spi%n"/>
   
    </Console>
  </Appenders>
  <loggers>
              <Logger name="org.apache.log4j.xml" level="all" />
              <root level="all">
                     <appender-ref ref="STDOUT" level="TRACE" />
                     </root>
  </loggers>
</configuration>

To know more about log4j2 configuration follow below link:

Log4j2 Java Logging Example Tutorial – XML Configuration, Severity Levels, Formatting and Appenders

Log4j2 Plugin Code for Masking

Created this LogMakingConverter Plug in for masking logs statement
Here masking for Credit card number, CVV and SSN . You can also implement for password and rest depend on your application needs. Here we have used Java regular expression Mater and Pattern apis for maskin and also different character as +++ for CVV,********* for SSN and **************** for credit card by matching number of digits in log lines.

package com.mask.logs;
/**
 * Created this LogMakingConverter Plug in for masking logs statement
 * Here masking for Credit card number, CVV and SSN .
 * You can also implement for password and rest depend on your application needs.
 */
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;

@Plugin(name="LogMaskingConverter", category = "Converter")
@ConverterKeys({"spi","trscId"})
public class LogMaskingConverter extends LogEventPatternConverter{
	private static final String CREDIT_CARD_REGEX = "([0-9]{16})";;
	private static final Pattern CREDIT_CARD_PATTERN = Pattern.compile(CREDIT_CARD_REGEX);
	private static final String CAREDIT_CARD_REPLACEMENT_REGEX = "XXXXXXXXXXXXXXXX";

	private static final String CVV_REGEX = "([0-9]{3})";
	private static final Pattern CVV_PATTERN = Pattern.compile(CVV_REGEX);
	private static final String CVV_REPLACEMENT_REGEX = "+++";

	private static final String SSN_REGEX = "([0-9]{9})";
	private static final Pattern SSN_PATTERN = Pattern.compile(SSN_REGEX);
	private static final String SSN_REPLACEMENT_REGEX = "*********";

    protected LogMaskingConverter(String name, String style) {
        super(name, style);
    }

    public static LogMaskingConverter newInstance(String[] options) {
        return new LogMaskingConverter("spi",Thread.currentThread().getName());
    }

    @Override
    public void format(LogEvent event, StringBuilder outputMessage) {
    	String message = event.getMessage().getFormattedMessage();
		String maskedMessage = message;
		try {
			maskedMessage = mask(message);
		} catch (Exception e) {
			System.out.println("Failed While Masking");
			maskedMessage = message;
		}
		outputMessage.append(maskedMessage);	

    }

    private String mask(String message) {
    	Matcher matcher =null;
		StringBuffer buffer = new StringBuffer();

		matcher = CREDIT_CARD_PATTERN.matcher(message);
		maskMatcher(matcher, buffer,CAREDIT_CARD_REPLACEMENT_REGEX);
		message=buffer.toString();
		buffer.setLength(0);

		matcher = SSN_PATTERN.matcher(message);
		maskMatcher(matcher, buffer,SSN_REPLACEMENT_REGEX);
		message=buffer.toString();
		buffer.setLength(0);

		matcher = CVV_PATTERN.matcher(message);
		maskMatcher(matcher, buffer,CVV_REPLACEMENT_REGEX);

		return buffer.toString();
	}

    private StringBuffer maskMatcher(Matcher matcher, StringBuffer buffer, String maskStr)
    {
    	while (matcher.find()) {
			matcher.appendReplacement(buffer,maskStr);
		}
		matcher.appendTail(buffer);
    	return buffer;
    }

}

Masking Test Program

Below is test program to print some log statements which are converting by Log4j2.

package com.mask.logs;

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

public class MaskingTest {
	  private static final Logger logger = LogManager.getLogger(MaskingTest.class);
      public static void myTest(){
             logger.info("this is my info message");
             logger.debug("This is debug message");
             logger.debug("Passed to server::0084USER:17603,IP:0:0:0:0:0:0:0:1,3425,Credit Card 1:1000002367844224,3425,Credit Card2:1000002367844224 , CVV:234,SSN:123456789");

      }
      public static void main(String[] args) {
             myTest();
      }
}

Output

Below is mask logs by log4j2 for confidential/personal/spi data.

20180607 11:20:43.558 [main] INFO  com.mask.logs.MaskingTest - this is my info message
20180607 11:20:43.559 [main] DEBUG com.mask.logs.MaskingTest - This is debug message
20180607 11:20:43.560 [main] DEBUG com.mask.logs.MaskingTest - Passed to server::+++4USER:+++03,IP:0:0:0:0:0:0:0:1,+++5,Credit Card 1:XXXXXXXXXXXXXXXX,+++5,Credit Card2:XXXXXXXXXXXXXXXX , CVV:+++,SSN:
*********

Summary

  • Step by step program for masking sensitive information in logs.
  • Log4j2 XML Configuration for loggers and appenders for masking.
  • LogMaskingConverter Log4j2 plugin for masking log statements.
  • Regular expression for Creditcard, SSN and CVV.
  • Test program to write logs  by java logging api to write in logs file.

More 

Below are some more masking ways for different type of data like XML, JSON and printing objects before logging , sending to page or transferring over network.

How to MASK XML Confidential/Personal Data : JAVA

How to Mask JSON Confidential/Personal Information in logs :JAVA

How to mask JAVA Object confidential/personal information in logs while Printing

Advertisements

Log4j2 JSON Configuration for Java Logging Severity Levels, Formatting and Appenders

In below previous post you read about Log4j2 XML configuration for Appenders, formatters and Loggers for Console and File Logging. I have also explained about RollingFile appeneders and there management.

Below is Log4j2 JSON configuration equivalent to XML configuration and dependency required for JSON. For more info in detail and configuration steps follow previous post for Log4J2 XML configuration.

You have to add below JSON dependency in your class path or pom.xml

POM.XML

&lt;!-- basic Log4j2 dependency --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
    &lt;artifactId&gt;log4j-api&lt;/artifactId&gt;
    &lt;version&gt;2.6.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
    &lt;artifactId&gt;log4j-core&lt;/artifactId&gt;
    &lt;version&gt;2.6.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- Asynchronous logging for multithreaded env --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.lmax&lt;/groupId&gt;
    &lt;artifactId&gt;disruptor&lt;/artifactId&gt;
    &lt;version&gt;3.3.4&lt;/version&gt;
&lt;/dependency&gt;

&lt;!-- Jackson JSON Processor --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.fasterxml.jackson.core&lt;/groupId&gt;
        &lt;artifactId&gt;jackson-databind&lt;/artifactId&gt;
        &lt;version&gt;2.4.1&lt;/version&gt;
    &lt;/dependency&gt;

create file log4j2.json in your root folder or resource folder.

{
   &quot;configuration&quot;: {
       &quot;status&quot;: &quot;info&quot;,
       &quot;monitorInterval&quot;: &quot;60&quot;,
       &quot;name&quot;: &quot;FacingIssuesOnIT&quot;,
      &quot;properties&quot;: {
         &quot;property&quot;: [
            {
               &quot;name&quot;: &quot;filename&quot;,
               &quot;value&quot;: &quot;target/FacingIssueOnIT.log&quot;
            },
            {
               &quot;name&quot;: &quot;log-path&quot;,
               &quot;value&quot;: &quot;C:/logs/&quot;
            }
         ]
      },
      &quot;appenders&quot;: {
         &quot;Console&quot;: {
            &quot;PatternLayout&quot;: {
               &quot;pattern&quot;: &quot;%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n&quot;
            },
            &quot;name&quot;: &quot;STDOUT&quot;,
            &quot;target&quot;: &quot;SYSTEM_OUT&quot;
         },
         &quot;File&quot;: {
            &quot;PatternLayout&quot;: {
               &quot;pattern&quot;: &quot;%d %p %c{1.} [%t] %m%n&quot;
            },
            &quot;name&quot;: &quot;file&quot;,
            &quot;fileName&quot;: &quot;${filename}&quot;
         },
         &quot;RollingFile&quot;: {
            &quot;PatternLayout&quot;: {
               &quot;pattern&quot;: &quot;%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n&quot;
            },

                &quot;Policies&quot;: {
               &quot;SizeBasedTriggeringPolicy&quot;: {
                  &quot;size&quot;: &quot;100 MB&quot;
               },
               &quot;TimeBasedTriggeringPolicy&quot;: {
                  &quot;interval&quot;: &quot;1&quot;,
                  &quot;modulate&quot;: &quot;true&quot;
               }
            },
            &quot;DefaultRolloverStrategy&quot;: {
               &quot;Delete&quot;: {
                  &quot;IfFileName&quot;: {
                     &quot;glob&quot;: &quot;*/FacingIssueOnIT-*.log.gz&quot;
                  },
                  &quot;IfLastModified&quot;: {
                     &quot;age&quot;: &quot;1h&quot;
                  },
                  &quot;basePath&quot;: &quot;${log-path}&quot;,
                  &quot;maxDepth&quot;: &quot;2&quot;
               }
            },
            &quot;name&quot;: &quot;RollingFile&quot;,
            &quot;fileName&quot;: &quot;${log-path}/FacingIssueOnIT.log&quot;,
            &quot;filePattern&quot;: &quot;${log-path}/$${date:yyyy-MM-dd}/FacingIssueOnIT-%d{yyyy-MM-dd}-%i.log.gz&quot;
         }
      },
      &quot;Loggers&quot;: {
         &quot;Logger&quot;: [
            {
               &quot;name&quot;: &quot;com.logging&quot;,
               &quot;level&quot;: &quot;debug&quot;
            },
            {
               &quot;appender-ref&quot;: {
                  &quot;ref&quot;: &quot;RollingFile&quot;,
                  &quot;level&quot;: &quot;debug&quot;
               },
               &quot;name&quot;: &quot;root&quot;,
               &quot;level&quot;: &quot;debug&quot;,
               &quot;additivity&quot;: &quot;false&quot;
            }
         ],
         &quot;Root&quot;: {
            &quot;AppenderRef&quot;: [
               {
                  &quot;ref&quot;: &quot;file&quot;,
                  &quot;level&quot;: &quot;error&quot;
               },
               {
                  &quot;ref&quot;: &quot;STDOUT&quot;,
                  &quot;level&quot;: &quot;debug&quot;
               },
               {
                  &quot;ref&quot;: &quot;RollingFile&quot;
               }
            ],
            &quot;level&quot;: &quot;trace&quot;
         }
      }

   }
}

Log4j2 New Features,Compare with Log4j and other Logging Framework

Log4j2 New Features

  • Java 8-style lambda support for lazy logging.
  • Log4j2 is garbage-free or least low-garbage since version 2.6
  • Log4j2 support configuration via XML, JSON, YAML, properties configuration files or programmatically.
  • Async Loggers – performance similar to logging switched off on multithreaded.
  • Concurrency improvements: log4j2 uses java.util.concurrent libraries to perform locking at the lowest level possible. Log4j-1.x has known deadlock issues.
  • Filtering: filtering based on context data,  regular expressions, markers and other components in the Log event. Filters can be associated with Loggers. You can use a common Filter class in any of these circumstances.
  • Custom Log Level
  • Plugin Architecture – easy to extend by building custom components
    Supported APIs: SLF4J, Commons Logging, Log4j-1.x and java.util.logging.

Why people are moving?

  • Community support: Log4j2 has an active community where question, answered, features are added and bugs are fixed.
  • Automatically reload it’s configuration upon modification without losing log events while reconfiguring.

Drawback

  • log4j 2.0 is very different than log4j 1.x, and the API is mostly incompatible.
  • Java 6 required for version 2.0 to 2.3. Java 7 is required for Log4j 2.4 and later.

Steps to upgrade Log4j1 to Log4j2

  1. add log4j2 dependency  log4j-api-2.6.2.jar and log4j-core-2.6.2.jar in your class path or pom.xml .
  2. Log4j2 looks for file log4j2.xml in config file. Add log4j2.xml file either in the class path or specify path with log4j configuration file system properties.
  3. To debug the log4j.xml configuration use in the beginning of configuration file.
  4. To add more configuration for Console, File and RollingFile appenders follow Log4j2 Tutorial and Configuration.

Comparison with other Logging Framework

Follow the below link to compare different logging framework on benchmark.

https://www.loggly.com/blog/benchmarking-java-logging-frameworks/

Log4j2 Java Logging Example Tutorial – XML Configuration, Severity Levels, Formatting and Appenders

Why Logging?

Logging information refers to the recording of your application activity that help in analyzing runtime behavior of application especially when encounters unexpected scenarios, errors or tracking steps executed by any request. As much as logging is done will easy to analyze any issues and bugs in the code.

Now a days more companies are moving to cloud and focusing on monitor logs and log analysis. There are some tools for centralize log management such as Logstash, Loggy, Graylog etc.

Follow link to know more about How to do centralize logging by Logstash when logs scattered on multiple servers.

There are so many JAVA logging frameworks and tools such as log4j, log4j2, slf4j, tinylog, logback etc. But here we mainly focus on Apache Log4j2 severity level, configuration file ways and java logging.

Log4j2 New Features,Compare with Log4j and other Logging Framework

How to do Logging?

Java provides standard Logging API to work as wrapper over different Logging framework. Compatible frameworks can be loaded into JVM and accessed via the API. There is also a default logging framework implementation provided by the Sun JVM which accessed by the API. Many developers confuse this implementation with the Java Logging API.

Logging is broken into three major parts:

  • Logger : The Logger is responsible for capturing the message to be logged along with certain metadata and passing it to the logging framework. These messages can be  an object, debug text or exceptions with an optional severity level.
  • Formatter: After receiving the message formatter do formatting with output.
  • Appender :Formatted message output will go to appender for disposition. Appenders might include console display, appending to database, log file or email etc.

Severity Level :

In logging framework always maintain the current configured logging level for each logger. That configured severity level can be set more or less restrictive.

For example : As we know each log message will logged at certain level. suppose the logging level is set to “WARNING”, then all messages of that level or higher are logged, ERROR and FATAL.

Below is list of all severity level from top to bottom. If any lower severity level configured all severity level above of it will by default consider.

  1. FATAL: Severe errors that cause premature termination. Expect these to be immediately visible on a status console.
  2. ERROR: Other runtime errors or unexpected conditions. Expect these to be immediately visible on a status console.
  3. WARNING: Message that can cause issue in future.
  4. INFO: Interesting runtime events (startup/shutdown). Expect these to be immediately visible on a console, so be conservative and keep to a minimum.
  5. DEBUG: detailed information on the flow through the system. Expect these to be written to logs only.
  6. TRACE: more detailed information. Expect these to be written to logs only.

Why Severity Level ?

Correct severity level is required while logging object, messages or errors so that easily track/debug issues and also analyze the behavior and failure cases of application while doing centralize logging.

Formatters or renderers

A Formatter is an object that that takes log line or object or exceptions from loggers and convert in formatted string representation. Below is technique to define your customize log format.

TTCC (Time Thread Category Component) is message format pattern representation used by log4j2.

For example : %r [%t] %-5p %c %x – %m%n  will print log line as below

567 [main] INFO org.apache.log4j.examples.FacingIssuesOnIT- Exiting main method.

Where

  • %r Used to output the number of milliseconds elapsed from the construction of the layout until the creation of the logging event.
  • %t Used to output the name of the thread that generated the logging event.
  • %p Used to output the priority of the logging event.
  • %c Used to output the category of the logging event.
  • %x Used to output the NDC (nested diagnostic context) associated with the thread that generated the logging event.
  • %X{key} Used to output the MDC (mapped diagnostic context) associated with the thread that generated the logging event for specified key.
  • %m Used to output the application supplied message associated with the logging event.
  • %n Used to output the platform-specific newline character or characters.

Appenders or handlers

Appenders takes message at or above a specified minimum severity level and passed and posts to appropriate message dispositions. Log4j2 supports below disposition of appenders.

  • ConsoleAppender
  • FileAppender
  • JDBCAppender
  • AsyncAppender
  • CassandraAppender
  • FailoverAppender
  • FlumeAppender
  • JMS Appender
  • JPAAppender
  • HttpAppender
  • KafkaAppender
  • MemoryMappedFileAppender
  • NoSQLAppender
  • OutputStreamAppender
  • RandomAccessFileAppender
  • RewriteAppender
  • RollingFileAppender
  • RollingRandomAccessFileAppender
  • RoutingAppender
  • SMTPAppender
  • ScriptAppenderSelector
  • SocketAppender
  • SyslogAppender
  • ZeroMQ/JeroMQ Appender

Log4j2 Configuration Support:

Log4j2 configuration can be accomplished 1 to 4 ways.

  • Through a configuration file written in XML, JSON, YAML, or properties format.
  • Programmatically, by creating a ConfigurationFactory and Configuration implementation.
  • Programmatically, by calling the APIs exposed in the Configuration interface to add components to the default configuration.
  • Programmatically, by calling methods on the internal Logger class.

Log4j2 Automatic Configuration:

Log4j2 has the ability to automatically configure itself during initialization. When Log4j starts it will look all the ConfigurationFactory plugins and arrange them in weighted order from highest to lowest. As above, Log4j contains four ConfigurationFactory implementations: one for JSON, one for YAML, one for properties, and one for XML.

  1. Log4j will inspect the “log4j.configurationFile” system property and, if set, will attempt to load the configuration using the ConfigurationFactory that matches the file extension.
  2. If no system property is set the properties ConfigurationFactory will look for log4j2-test.properties in the classpath.
  3. If no such file is found the YAML ConfigurationFactory will look for log4j2-test.yaml or log4j2-test.yml in the classpath.
  4. If no such file is found the JSON ConfigurationFactory will look for log4j2-test.json or log4j2-test.jsn in the classpath.
  5. If no such file is found the XML ConfigurationFactory will look for log4j2-test.xml in the class path.
  6. If a test file cannot be located the properties ConfigurationFactory will look for log4j2.properties on the classpath.
  7. If a properties file cannot be located the YAML ConfigurationFactory will look for log4j2.yaml or log4j2.yml on the classpath.
  8. If a YAML file cannot be located the JSON ConfigurationFactory will look for log4j2.json or log4j2.jsn on the classpath.
  9. If a JSON file cannot be located the XML ConfigurationFactory will try to locate log4j2.xml on the classpath.
  10. If no configuration file could be located the DefaultConfiguration will be used. This will cause logging output to go to the console.

Here we mainly focus on log4j2 XML configuration for ConsoleAppenderFileAppender and RollingFileAppender and will see how to apply filters for loggers on default, package level  and root level with different scenarios. also see how same java program logging work on different configuration.

Steps to configuration of log4j2 with any java application:

  • Create any console based Java application or Maven JAVA Console Application or Maven Web Application.
  • Add below dependency/jars on your application.
  • Add below log4j2.xml file in your application root folder or for maven in resource folder as below.
  • Add below JAVA program in any package of your application.

Configure as below :

log4jConfiguration

Dependencies : 

&lt;!-- basic Log4j2 dependency --&gt;
&lt;dependency&gt;
	&lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
	&lt;artifactId&gt;log4j-api&lt;/artifactId&gt;
	&lt;version&gt;2.6.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
	&lt;groupId&gt;org.apache.logging.log4j&lt;/groupId&gt;
	&lt;artifactId&gt;log4j-core&lt;/artifactId&gt;
	&lt;version&gt;2.6.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;!-- Asynchronous logging for multithreaded env --&gt;
&lt;dependency&gt;
	&lt;groupId&gt;com.lmax&lt;/groupId&gt;
	&lt;artifactId&gt;disruptor&lt;/artifactId&gt;
	&lt;version&gt;3.3.4&lt;/version&gt;
&lt;/dependency&gt;

log4j2.xml configuration Here

&lt;Configuration status=&quot;info&quot; monitorInterval=&quot;60&quot; name=&quot;FacingIssuesOnIT&quot;&gt;
&lt;!-- Log File Name and Location --&gt;
	&lt;Properties&gt;
		&lt;Property name=&quot;filename&quot;&gt;target/FacingIssueOnIT.log&lt;/Property&gt;
		&lt;Property name=&quot;log-path&quot;&gt;C:/logs/&lt;/Property&gt;
	&lt;/Properties&gt;
	&lt;Appenders&gt;
		&lt;!-- Console Logging --&gt;
		&lt;Console name=&quot;STDOUT&quot; target=&quot;SYSTEM_OUT&quot;&gt;
			&lt;PatternLayout pattern=&quot;%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n&quot; /&gt;
		&lt;/Console&gt;
		&lt;!-- File Logging --&gt;
		&lt;File name=&quot;file&quot; fileName=&quot;${filename}&quot;&gt;
			&lt;PatternLayout&gt;
				&lt;pattern&gt;%d %p %c{1.} [%t] %m%n&lt;/pattern&gt;
			&lt;/PatternLayout&gt;
		&lt;/File&gt;
	&lt;/Appenders&gt;
	&lt;Loggers&gt;
		&lt;!-- ByDefault, all log messages of level &quot;trace&quot; or higher will be logged.Log messages are sent to the &quot;file&quot; appender are severity level error or higher while  for console appender and log messages of level &quot;error&quot; and higher will be sent to the &quot;STDOUT&quot; appender. --&gt;
		&lt;Root level=&quot;trace&quot;&gt;
			&lt;AppenderRef ref=&quot;file&quot; level=&quot;error&quot; /&gt;
			&lt;AppenderRef ref=&quot;STDOUT&quot; level=&quot;debug&quot; /&gt;
		&lt;/Root&gt;
	&lt;/Loggers&gt;
&lt;/Configuration&gt;

JAVA Program Here

package com.logging;

import org.apache.logging.log4j.Logger;

import java.time.LocalDateTime;

import org.apache.logging.&lt;span 				data-mce-type=&quot;bookmark&quot; 				id=&quot;mce_SELREST_start&quot; 				data-mce-style=&quot;overflow:hidden;line-height:0&quot; 				style=&quot;overflow:hidden;line-height:0&quot; 			&gt;&#65279;&lt;/span&gt;log4j.LogManager;

public class Log4jExample {

    private static Logger logger = LogManager.getLogger(Log4jExample.class);

    public static void main(String[] args) {

    	  logger.fatal(&quot;Fatal log message :FacingIssuesOnIT&quot;);

    	  logger.error(&quot;Error log message :FacingIssuesOnIT&quot;);

    	  logger.warn(&quot;Warn log message :FacingIssuesOnIT&quot;);

    	  logger.info(&quot;Info log message :FacingIssuesOnIT&quot;);

          logger.debug(&quot;Debug log message :FacingIssuesOnIT&quot;);

          logger.trace(&quot;Trace log message :FacingIssuesOnIT&quot;);
    }
}

As below for console and file output are different because of logging configuration for STDOUT and file. If you noticed STDOUT is configured for severity level as debug that’s why in console printing all log lines for debug and above severity level except Trace. Same way for file output on location /target/FacingIssuesonIT.log are having logs for FATAL and ERROR only because file is configured for severity level as ERROR.

Console Output :

20171220 10:19:12.640 [main] FATAL com.logging.Log4jExample - Fatal log message :FacingIssuesOnIT
20171220 10:19:12.642 [main] ERROR com.logging.Log4jExample - Error log message
:FacingIssuesOnIT
20171220 10:19:12.642 [main] WARN  com.logging.Log4jExample - Warn log message :
FacingIssuesOnIT
20171220 10:19:12.642 [main] INFO  com.logging.Log4jExample - Info log message :
FacingIssuesOnIT
20171220 10:19:12.642 [main] DEBUG com.logging.Log4jExample - Debug log message
:FacingIssuesOnIT

File Output:

2017-12-20 10:19:12,640 FATAL c.l.Log4jExample [main] Fatal log message :FacingIssuesOnIT
2017-12-20 10:19:12,642 ERROR c.l.Log4jExample [main] Error log message :FacingIssuesOnIT

RollingFileAppender Configuration

The above was basic configuration and design for implement log4j2 logging so that easily understand. Now we will go in more detail for configuration  so that understand  how to log rolling and archieve logs and maintain easily by date and size of log file by implement FileAppender. We will also know about to implement logger filter on package level so that you can easily main logs for specific module or functionality.

Now making some changes in configuration file as well as in JAVA program to testing FileAppender.

log4j2.xml configuration

&lt;Configuration status=&quot;info&quot; monitorInterval=&quot;60&quot; 	name=&quot;FacingIssuesOnIT&quot;&gt;
	&lt;!-- Log File Name and Location --&gt;
	&lt;Properties&gt;
		&lt;Property name=&quot;filename&quot;&gt;target/FacingIssueOnIT.log&lt;/Property&gt;
		&lt;Property name=&quot;log-path&quot;&gt;C:/logs/&lt;/Property&gt;
	&lt;/Properties&gt;
	&lt;Appenders&gt;
		&lt;!-- Console Logging --&gt;
		&lt;Console name=&quot;STDOUT&quot; target=&quot;SYSTEM_OUT&quot;&gt;
			&lt;PatternLayout pattern=&quot;%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n&quot; /&gt;
		&lt;/Console&gt;
		&lt;!-- File Logging --&gt;
		&lt;File name=&quot;file&quot; fileName=&quot;${filename}&quot;&gt;
			&lt;PatternLayout&gt;
				&lt;pattern&gt;%d %p %c{1.} [%t] %m%n&lt;/pattern&gt;
			&lt;/PatternLayout&gt;
		&lt;/File&gt;
		&lt;!-- Rolling File --&gt;
		&lt;RollingFile name=&quot;RollingFile&quot; fileName=&quot;${log-path}/FacingIssueOnIT.log&quot; 			filePattern=&quot;${log-path}/$${date:yyyy-MM-dd}/myexample-%d{yyyy-MM-dd}-%i.log.gz&quot;&gt;
			&lt;PatternLayout&gt;
				&lt;pattern&gt;%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n&lt;/pattern&gt;
			&lt;/PatternLayout&gt;
			&lt;Policies&gt;
				&lt;SizeBasedTriggeringPolicy size=&quot;100 MB&quot; /&gt;
				&lt;TimeBasedTriggeringPolicy interval=&quot;1&quot; modulate=&quot;true&quot;/&gt;
			&lt;/Policies&gt;
			&lt;DefaultRolloverStrategy  &gt;
			&lt;Delete basePath=&quot;${log-path}&quot; maxDepth=&quot;2&quot;&gt;
          &lt;IfFileName glob=&quot;*/FacingIssueOnIT-*.log.gz&quot; /&gt;
          &lt;IfLastModified age=&quot;1h&quot; /&gt;
        &lt;/Delete&gt;
			&lt;/DefaultRolloverStrategy&gt;
		&lt;/RollingFile&gt;
	&lt;/Appenders&gt;
	&lt;Loggers&gt;

	&lt;!-- package level logger --&gt;
		&lt;!-- Loggers classes whose package name start with com.logging will log message of level  			&quot;debug&quot; or higher --&gt;
		&lt;Logger name=&quot;com.logging&quot; level=&quot;debug&quot; /&gt;

		&lt;Logger name=&quot;root&quot; level=&quot;debug&quot; additivity=&quot;false&quot;&gt;
			&lt;appender-ref ref=&quot;RollingFile&quot; level=&quot;debug&quot; /&gt;
		&lt;/Logger&gt;

		&lt;!-- ByDefault, all log messages of level &quot;trace&quot; or higher will be logged.  			Log messages are sent to the &quot;file&quot; appender are severity level error or higher while  for console appender 			and log messages of level &quot;error&quot;  			and higher will be sent to the &quot;STDOUT&quot; appender. and rolling file for all level as configure for root --&gt;
		&lt;Root level=&quot;trace&quot;&gt;
			&lt;AppenderRef ref=&quot;file&quot; level=&quot;error&quot; /&gt;
			&lt;AppenderRef ref=&quot;STDOUT&quot; level=&quot;debug&quot; /&gt;
			&lt;AppenderRef ref=&quot;RollingFile&quot; /&gt;
		&lt;/Root&gt;
	&lt;/Loggers&lt;/Configuration&gt;

In above log4j2.xml configuration having additional changes for appender RollingFile. Let me explain about it in more detail:

%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} – %msg%n : This pattern shows how your logs will format  in logs file.

filename=”${log-path}/FacingIssueOnIT.log :  Current logs will write on this file.

configurefilePattern=”${log-path}/$${date:yyyy-MM-dd}/myexample-%d{yyyy-MM-dd}-%i.log.gz : As configured for triggering policy will check in every second (interval=1) if current file size reach to 100MB (size=100MB) will create rolling file on current date folder as in below screen.

Archieve Delete Policy: represent how old logs you want to keep as backup as of now configured for last one hour. As per you application need change it to days and change path of delete achieve logs files as per your logs directory.

Here I have added RollingFile appenders in loggers as root with out any specified level so that we can do logging for all log line. If you want to filter logs and behave differently for different package you can use loggers with different severity levels as I have used for package com.logging.

JAVA Code :

Here I have added infinite loop for testing RollingFileAppender so that logs continuously added to log file. Additionally for big application prospects added condition for checking what level severity is configured in logs so that if not satisfy condition then save operation processing time of logger for logging, formatting and appending checking. In this way we can increase application performance for logging.

package com.logging;

import org.apache.logging.log4j.Logger;
import java.time.LocalDateTime;
import org.apache.logging.log4j.LogManager;

public class Log4jExample {
    private static Logger logger = LogManager.getLogger(Log4jExample.class);

    public static void main(String[] args) {

    	 do
     	{
     	 if(logger.isFatalEnabled())
    	  logger.fatal(&quot;Fatal log message :FacingIssuesOnIT&quot;);
     	if(logger.isErrorEnabled())
    	  logger.error(&quot;Error log message :FacingIssuesOnIT&quot;);
     	if(logger.isWarnEnabled())
    	  logger.warn(&quot;Warn log message :FacingIssuesOnIT&quot;);
     	if(logger.isInfoEnabled())
    	  logger.info(&quot;Info log message :FacingIssuesOnIT&quot;);
     	if(logger.isDebugEnabled())
          logger.debug(&quot;Debug log message :FacingIssuesOnIT&quot;);
     	if(logger.isTraceEnabled())
          logger.trace(&quot;Trace log message :FacingIssuesOnIT&quot;);
     	}
    }
while(1&gt;0);
}

File output: For current log file will have log formatted as below.

20171220 10:49:55.226 [main] FATAL com.logging.Log4jExample - Fatal log message :FacingIssuesOnIT
20171220 10:49:55.227 [main] ERROR com.logging.Log4jExample - Error log message :FacingIssuesOnIT
20171220 10:49:55.228 [main] WARN  com.logging.Log4jExample - Warn log message :FacingIssuesOnIT
20171220 10:49:55.228 [main] INFO  com.logging.Log4jExample - Info log message :FacingIssuesOnIT
20171220 10:49:55.228 [main] DEBUG com.logging.Log4jExample - Debug log message :FacingIssuesOnIT

Archive Log Files:  Rolling and archive file will create as below on directory C:\logs\2017-12-20

log4j RollingFile

Summary 

In this tutorial, I have considered logging importance, ways of centralize logging, log4j2 configuration for console, file and rolling file appenders. Also explained about rolling, archive management of logs  and bit idea to increase you application performance with minor change for logging.

References :

https://logging.apache.org/log4j