Monday, October 02, 2006

Log4j done programmatically

Have you ever wanted to create a simple log file inside your program but not have to fill the application code with System.out.println statements. Well if so, then this might be the solution that you have been seeking.

I recently created a Java program that processed several input files into one large output. The processing was very intense and required several displays to allow for debugging.Once I had the program running I removed the displays in order to cut down on all of the noise being displayed to the user at the command console . It became apparent that in order to debug this down the road, a developer would have to recompile the code again to add those displays back in order to allow for fast troubleshooting in the future. This was unacceptable to me. There has to be a way to allow for both regular running of the code and debugging as well.Then I realized that a command-line switch would be just the thing to solve the problem.

My switch was called "-debug". You can call it whatever you would like: "-verbose", "-Helpmefixthisstupidprogram", "-icantbelievethisthingbrokeagain" "-helpmeIvefallenandicantgetbackup". Whatever floats your boat!Then I began searching for a way to easily turn on logging to a file based on the presence of this switch. One of my requirements was that this log file also allow for regular displays that where a regular occurrence, even when not in debug mode.

Log4j, a part of the apache project was a great fit (http://logging.apache.org). This project has a wealth of capabilities. My usage on scratches the surface of the myriad of possibilities.Now I can accommodate both the users, administrators, and developers needs by having various logging levels for each type of user. My users run the program without declaring the -debug argument at the command line. The administrators and developers can add the -debug argument and understand in great detail al of the inner going workings of the program during run-time.

I hope this helps in your development efforts and keeps others from having to re-create the wheel so to speak. Send me your suggestions and enhancements to improve upon this process. I will keep this working example out there for others to reference. - Ray

Here is an example of how Log4j can be used programmatically to control logging levels...


import java.io.IOException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;


public class LoggingExample {

static boolean bDebugSwitch = false;
static Logger logger = Logger.getLogger(LoggingExample.class);
static String sProgramVersionNumber = "1.0.0";
static int iReturnCode = 0;

private static int parseCommandLineArguments(String[] args) {

int iReturnCode=0;


for (int i=0; i < args.length; i++) {
if (args[i].indexOf("-debug") == 0) {
bDebugSwitch = true;
}
else {
System.out.println("Bad argument passed from the command line: " + args[i]);
}
}

return iReturnCode;
}


public static void main(String[] args) {

iReturnCode = parseCommandLineArguments(args);

try {
// Layout layout = new PatternLayout("%d [%-5p] %c - %m%n");
Layout layout = new PatternLayout("%m%n");
Date today = new Date(System.currentTimeMillis());
Format formatter = new SimpleDateFormat("yyyyMMddkkmmss");
FileAppender appender= new FileAppender(layout, "LoggingExample-"+ formatter.format(today) + ".log");
Logger logger = Logger.getRootLogger();
logger.addAppender(appender);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}

if (bDebugSwitch == true){
logger.setLevel(Level.DEBUG);
}
else {
logger.setLevel(Level.INFO);
}

logger.debug("-debug command line argument detected... debug logging enabled");
logger.info("LoggingExample version " +sProgramVersionNumber );

Date today = new Date(System.currentTimeMillis());
Format formatter = new SimpleDateFormat("MM/dd/yyyy kk:mm:ss");
logger.info("Program Start Time: " + formatter.format(today));

// Insert your application code here...

today = new Date(System.currentTimeMillis());
formatter = new SimpleDateFormat("MM/dd/yyyy kk:mm:ss");

logger.info("Program End Time: " + formatter.format(today));

System.exit(iReturnCode);

}

}