JavaEnterprise JavaDynamically Configure Log4j Properties in a Clustered Environment

Dynamically Configure Log4j Properties in a Clustered Environment

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Log4j and the Apache Commons Logging API provide features for recording Java application logs. But suppose the applications are deployed in a clustered environment (a logical grouping of servers) for high availability and you want to create application logs by application server.

In this advanced Java tip, Suneel Gupta explains how to configure the log4j-related properties of a Java application deployed in a clustered environment. This technique allows log files to be generated dynamically on the server side.

The scenario could goes something like this:

  1. You have deployed application X in a clustered environment with two servers (s1 and s2).
  2. You want the application logs (x.log) to be created inside the server name directory (s1 and s2).

So for X application running in the s1 server, its log should be created inside the s1 directory. Conversely, for the same X application running in the s2 server, its log should be created inside the s2 directory. The s1 and s2 directories can be in the same machine or in different machines.

Below is a sample Log4j.properties file for this scenario. It will be common inside the X application.

log4j.rootLogger=DEBUG, A3
########## Appender A3
log4j.appender.A3=org.apache.log4j.RollingFileAppender
log4j.appender.A3.File=C:x.log
# Set the maximum log file size (use KB, MB or GB)
log4j.appender.A3.MaxFileSize=25MB
# Set the number of log files (0 means no backup files at all)
log4j.appender.A3.MaxBackupIndex=100
# Append to the end of the file or overwrites the file at start.
log4j.appender.A3.Append=false
log4j.appender.A3.layout=org.apache.log4j.PatternLayout
log4j.appender.A3.layout.ConversionPattern=%d [%c{1}] %p - %m%n

If you look closer at the log4j.appender.A3.File= C:x.log line, you’ll notice a problem with this log4j.properties file. It is dictating that when applications run on servers, their log files will generate at the C: directory. In our scenario, however, X application is running on two servers (s1 and s2), which are on either the same or different machines.

Now, how can you generate the log file dynamically inside the C:s1x.log and C:s2x.log? If you don’t use a directory structure, then X application running on server s1 and s2 will overwrite the log on the C:x.log file. In this case, you will not able to determine which server created which line of the log because it’s the same file.

Enter dynamic log4j configuration. The overwrite problem can be resolved by dynamically configuring the log when application X loads log4j.properties. In WebSphere Application Server, there is an API ServerName.getDisplayName() method that you can use to get the name of the application server. The same type of API should be available in other Java applications and Web servers. Read the server name using the server API inside the application, and set the log file path dynamically for the application.

For example, in the following line of code, the RollingFileAppender object will give the properties of the log4j.properties-related configuration, which has been loaded in the application.

RollingFileAppender r =(RollingFileAppender) Logger.getRootLogger().getAppender("A3");

You can then read the filename and its already configured properties, such as log file path and log file size, from the log4j.properties file. If the log path configured is C:x.log, you can update this file path so that the log file will be generated at the desired path by using the API call below.

String filename = "C:" + ServerName.getDisplayName() + "x.log"

Below is a code snippet to load or dynamically configure log path.

public class LoadLogger {
public static Logger rLogger = Logger.getRootLogger();

public static void setLogger1(String fileName,String level,String pattern)
{
try {
System.out.println("setlogger1(fileName,level,pattern) in LoadLogger.java ---> Called");

if(level != null){
System.out.println("setting level");
if(level.trim().equalsIgnoreCase("info"))
Logger.getRootLogger().setLevel(Level.INFO );
else if(level.trim().equalsIgnoreCase("DEBUG"))
Logger.getRootLogger().setLevel(Level.DEBUG );
else if(level.trim().equalsIgnoreCase("ERROR"))
Logger.getRootLogger().setLevel(Level.ERROR );
else if(level.trim().equalsIgnoreCase("WARN"))
Logger.getRootLogger().setLevel(Level.WARN );
else if(level.trim().equalsIgnoreCase("FATAL"))
Logger.getRootLogger().setLevel(Level.FATAL);
else if(level.trim().equalsIgnoreCase("ALL"))
Logger.getRootLogger().setLevel(Level.ALL);
else if(level.trim().equalsIgnoreCase("OFF"))
Logger.getRootLogger().setLevel(Level.OFF);

}

if(Logger.getRootLogger().getAppender("myAppender") != null)
{
RollingFileAppender r = new RollingFileAppender();
r=(RollingFileAppender)Logger.getRootLogger().getAppender("myAppender");
System.out.println(" Appender Name = " + r.getName());
if(r.getFile()!=null)
{
System.out.println(" File = " + r.getFile());
}
else
{
System.out.println(" File = NULL");
}
System.out.println(" Layout = " + r.getLayout().getClass().getName());
PatternLayout p=new PatternLayout();
p=(PatternLayout)r.getLayout();
System.out.println(" ConversionPattern = " + p.getConversionPattern());
System.out.println(" Threshold = " + r.getThreshold());
Logger.getRootLogger().removeAppender(Logger.getRootLogger().getAppender("myAppender"));

PatternLayout p1=new PatternLayout();

if(pattern!=null)
{
p1.setConversionPattern(pattern);
r.setLayout(p1);
}

if(fileName!=null)
{
r.setFile(fileName);
System.out.println(" setting fileName = " + r.getFile());
}
r.activateOptions();
Logger.getRootLogger().addAppender(r);
}

System.out.println("setlogger1(fileName,level,pattern) in LoadLogger.java ---> Exited");
LoadLogger.debug("Load log4j successfully................");
}
catch(Exception e)
{
System.out.println(" exception in setlogger1() in LoadLogger.java " + e);
}


}
}

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories