HowToDoInJava

  • Java 8
  • Regex
  • Concurrency
  • Best Practices
  • Spring Boot
  • JUnit5
  • Interview Questions
  • Dark Mode

Log4j – Reload Logging Levels on Runtime

By Lokesh Gupta | Filed Under: Log4j

Excessive logging is a common cause of performance degrade of application. It is one of best practices to ensure proper logging within your Java EE application implementation. However, be careful with the logging level that you enable in your production environment. Excessive logging will trigger high IO on your server and increase CPU utilization. This can especially be a problem for older environments using older hardware or environments dealing with very heavy concurrent volumes.

A balanced approach is to implement a "reloadable logging level" facility to turn extra logging ON / OFF 
when required in your day to day production support.

Lets see how this can be done using WatchService provided by Java 7.

Log4j reload

Step 1) Implements a WatchService which will listen for changes in given log4j file

Below given code initializes a thread which continuously watch for modifications in given log4j file [StandardWatchEventKinds.ENTRY_MODIFY]. As soon as a file change is observed, configurationChanged() method is invoked and DOMConfigurator.configure() method is used to again reload the log4j configuration.

Log4jChangeWatcherService.java

package com.howtodoinjava.demo;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

import org.apache.log4j.xml.DOMConfigurator;

public class Log4jChangeWatcherService implements Runnable
{
	private String configFileName = null;
	private String fullFilePath = null;

	public Log4jChangeWatcherService(final String filePath) {
		this.fullFilePath = filePath;
	}
	
	//This method will be called each time the log4j configuration is changed
	public void configurationChanged(final String file)
	{
		System.out.println("Log4j configuration file changed. Reloading logging levels !!");
		DOMConfigurator.configure(file);
	}

	public void run() {
		try {
			register(this.fullFilePath);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void register(final String file) throws IOException {
		final int lastIndex = file.lastIndexOf("/");
		String dirPath = file.substring(0, lastIndex + 1);
		String fileName = file.substring(lastIndex + 1, file.length());
		this.configFileName = fileName;

		configurationChanged(file);
		startWatcher(dirPath, fileName);
	}

	private void startWatcher(String dirPath, String file) throws IOException {
		final WatchService watchService = FileSystems.getDefault().newWatchService();
		
		//Define the file and type of events which the watch service should handle
		Path path = Paths.get(dirPath);
		path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);

		Runtime.getRuntime().addShutdownHook(new Thread() {
			public void run() {
				try {
					watchService.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});

		WatchKey key = null;
		while (true) {
			try {
				key = watchService.take();
				for (WatchEvent< ?> event : key.pollEvents()) {
					if (event.context().toString().equals(configFileName)) {
						
						//From here the configuration change callback is triggered
						configurationChanged(dirPath + file);
					}
				}
				boolean reset = key.reset();
				if (!reset) {
					System.out.println("Could not reset the watch key.");
					break;
				}
			} catch (Exception e) {
				System.out.println("InterruptedException: " + e.getMessage());
			}
		}
	}
}

2) Add Log4jConfigurator, an interface for your application to work with log4j

This class is a utility class which separates the log4j initialization code and reloading strategy from application code.

Log4jConfigurator.java

package com.howtodoinjava.demo;

public class Log4jConfigurator 
{
	//This ensures singleton instance of configurator
	private final static Log4jConfigurator INSTANCE = new Log4jConfigurator();

	public static Log4jConfigurator getInstance()
	{
		return INSTANCE;
	}

	//This method will start the watcher service of log4j.xml file and also configure the loggers
	public void initilize(final String file) {
		try 
		{
			//Create the watch service thread and start it.
			//I will suggest to use some logic here which will check if this thread is still alive;
			//If thread is killed then restart the thread
			Log4jChangeWatcherService listner = new Log4jChangeWatcherService(file);
			
			//Start the thread
			new Thread(listner).start();
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}
}

3) Test the log4j reload events

To test the code, I am logging two two statements: one debug level and one info level. Both statements are logged after 2 seconds in a loop. I will change the logging level after few log statements and the log4j should be reloaded.

log4j-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

  <appender name="console" class="org.apache.log4j.ConsoleAppender"> 
    <param name="Target" value="System.out"/> 
    <layout class="org.apache.log4j.PatternLayout"> 
      <param name="ConversionPattern" value="[%t] %-5p %c %x - %m%n"/> 
    </layout> 
  </appender> 

  <root> 
    <priority value ="info" />  
    <appender-ref ref="console" /> 
  </root>
  
</log4j:configuration>

Log4jConfigReloadExample.java

package com.howtodoinjava.demo;

import org.apache.log4j.Logger;

public class Log4jConfigReloadExample 
{
	private static final String LOG_FILE_PATH = "C:/Lokesh/Setup/workspace/Log4jReloadExample/log4j-config.xml";
	
	public static void main(String[] args) throws InterruptedException 
	{
		//Configure logger service
		Log4jConfigurator.getInstance().initilize(LOG_FILE_PATH);
		
		//Get logger instance
		Logger LOGGER = Logger.getLogger(Log4jConfigReloadExample.class);
		
		//Print the log messages and wait for log4j changes
		while(true)
		{
			//Debug level log message
			LOGGER.debug("A debug message !!");
			//Info level log message
			LOGGER.info("A info message !!");
			
			//Wait between log messages
			Thread.sleep(2000);
		}
	}
}

Output:

[main] INFO  com.howtodoinjava.demo.Log4jConfigReloadExample  - A info message !!
[main] INFO  com.howtodoinjava.demo.Log4jConfigReloadExample  - A info message !!
[main] INFO  com.howtodoinjava.demo.Log4jConfigReloadExample  - A info message !!
[main] INFO  com.howtodoinjava.demo.Log4jConfigReloadExample  - A info message !!
[main] INFO  com.howtodoinjava.demo.Log4jConfigReloadExample  - A info message !!
Log4j configuration file changed. Reloading logging levels !!
[main] DEBUG com.howtodoinjava.demo.Log4jConfigReloadExample  - A debug message !!
[main] INFO  com.howtodoinjava.demo.Log4jConfigReloadExample  - A info message !!
[main] DEBUG com.howtodoinjava.demo.Log4jConfigReloadExample  - A debug message !!
[main] INFO  com.howtodoinjava.demo.Log4jConfigReloadExample  - A info message !!

 

Sourcecode Download

Happy Learning !!

TwitterFacebookLinkedinRedditPocket

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

13
Leave a Reply

This comment form is under antispam protection
7 Comment threads
6 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
9 Comment authors
This comment form is under antispam protection
  Subscribe  
newest oldest most voted
Notify of
prasad sarang

how to implement run time log mode change in log4j2

Vote Up0Vote Down  Reply
2 months ago
Mike

Can this be done with a log4j.properties file instead of the xml file?

Vote Up0Vote Down  Reply
2 years ago
Lokesh Gupta

Yes, In case of properties file use PropertyConfigurator.configure() methods, in place of DOMConfigurator.configure() method in above example.

Vote Up0Vote Down  Reply
2 years ago
prasad

How to use same for mutliple log files.

Vote Up0Vote Down  Reply
2 months ago
Rampal

Hi Lokesh,
Excellent article. It was really helpful. Won’t there be any performance impact because of one thread (Log4jChangeWatcherService in this case) running continuously ??

Vote Up0Vote Down  Reply
5 years ago
Lokesh Gupta

Not really. They are very light weight threads.

Vote Up0Vote Down  Reply
5 years ago
Joby Markose

Suil…you are correct..I had tested with

PropertyConfigurator.configureAndWatch and is working lie a gem…:)…Thank you Lokesh and Sunil…

Vote Up0Vote Down  Reply
5 years ago
Sunil

Why not DOMConfigurator.configureAndWatch()?

Vote Up0Vote Down  Reply
5 years ago
Lokesh Gupta

It’s for MS .net framework. Not sure, if it will work in java. Need to check. Can you please post a sample code here?

Vote Up0Vote Down  Reply
5 years ago
Sunil

Here is the javadoc

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/DOMConfigurator.html#configureAndWatch(java.lang.String, long)

Vote Up0Vote Down  Reply
5 years ago
pathakanshulshul

Nice explanation & very usable

Vote Up0Vote Down  Reply
5 years ago
ashish

enable sharing via linkedin

Vote Up0Vote Down  Reply
6 years ago
Lokesh Gupta

No clue what you are asking for? Floating sidebar has share button for linkedIn. right?? Am i missing anything?

Vote Up0Vote Down  Reply
6 years ago

Search Tutorials

Log4j2 Tutorial

  • Log4j2 – Introduction
  • Log4j2 – JSON Config
  • Log4j2 – Properties Config
  • Log4j2 – XML Config
  • Log4j2 – RollingFileAppender
  • Log4j2 – Multiple appenders
  • Log4j2 – LevelRangeFilter
  • Log4j2 – HTMLLayout
  • Log4j2 – Fish Tagging
  • Log4j2 – Conversion Patterns
  • Log4j2 – JUnit

Log4j Tutorial

  • Log4j – Introduction
  • Log4j – Properties Config
  • Log4j – XML Config
  • Log4j – Maven Config
  • Log4j – Logging Levels
  • Log4j – ConsoleAppender
  • Log4j – RollingFileAppender
  • Log4j – SocketAppender
  • Log4j – JDBCAppender
  • Log4j – XMLLayout
  • Log4j – HTMLLayout
  • Log4j – Runtime Reload
  • Log4j vs. SLF4j
  • Log4j – RESTEasy + Tomcat 7

Popular Tutorials

  • Java 8 Tutorial
  • Core Java Tutorial
  • Collections in Java
  • Java Concurrency
  • Spring Boot Tutorial
  • Spring AOP Tutorial
  • Spring MVC Tutorial
  • Spring Security Tutorial
  • Hibernate Tutorial
  • Python Tutorial
  • Jersey Tutorial
  • Maven Tutorial
  • Log4j Tutorial
  • Regex Tutorial

Meta Links

  • Advertise
  • Contact Us
  • Privacy policy
  • About Me

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2016 · HowToDoInjava.com · All Rights Reserved. | Sitemap

wpDiscuz