Simple Logger

Hi

A while back I got frustrated with the Java logging library and started looking at alternatives. Sure there are lots of options out there for logging and I could have used them with a little modification but in the end decided to knock together a simple class to do the job for me.

While doing some code clean up it occurred to me that someone might find a simple logger useful. I have taken out my application specific functionality and posted the result below.

[java]

public class Log {

public static final int LEVEL_OFF = 5;
public static final int LEVEL_ERROR = 4;
public static final int LEVEL_WARN = 3;
public static final int LEVEL_INFO = 2;
public static final int LEVEL_DEBUG = 1;
// Modify LOG_LEVEL to the required level
private static final int LOG_LEVEL = LEVEL_INFO;
//
private static final String ERROR_PREFIX = "ERROR: ";
private static final String WARN_PREFIX = "WARN: ";
private static final String INFO_PREFIX = "INFO: ";
private static final String DEBUG_PREFIX = "DEBUG: ";

public static final boolean ERROR = LOG_LEVEL <= LEVEL_ERROR;
public static final boolean WARN = LOG_LEVEL <= LEVEL_WARN;
public static final boolean INFO = LOG_LEVEL <= LEVEL_INFO;
public static final boolean DEBUG = LOG_LEVEL <= LEVEL_DEBUG;

public static Logger logger = new Logger();
private final static StopWatch stopWatch = new StopWatch();

protected Log() {

}

public static final void error(String message) {
    if (ERROR) {
        logger.log(LEVEL_ERROR, ERROR_PREFIX, message, null);
    }
}

public static final void error(String message, Throwable ex) {
    if (ERROR) {
        logger.log(LEVEL_ERROR, ERROR_PREFIX, message, ex);
    }
}

public static final void warn(String message, Throwable ex) {
    if (WARN) {
        logger.log(LEVEL_WARN, WARN_PREFIX, message, ex);
    }
}

public static final void warn(String message) {
    if (WARN) {
        logger.log(LEVEL_WARN, WARN_PREFIX, message, null);
    }
}

public static final void info(String message, Throwable ex) {
    if (INFO) {
        logger.log(LEVEL_INFO, INFO_PREFIX, message, ex);
    }
}

public static final void info(String message) {
    if (INFO) {
        logger.log(LEVEL_INFO, INFO_PREFIX, message, null);
    }
}

public static final void debug(String message, Throwable ex) {
    if (DEBUG) {
        logger.log(LEVEL_DEBUG, DEBUG_PREFIX, message, ex);
    }
}

public static final void debug(String message) {
    if (DEBUG) {
        logger.log(LEVEL_DEBUG, DEBUG_PREFIX, message, null);
    }
}

public final static class Logger {

    public void log(int level, String logLevel, String message) {
        final String result
                = buildLogMessage(level, logLevel, message).toString();
        print(result);
    }

    public void log(int level, String logLevel, String message, Throwable ex) {
        final StringBuilder sb
                = buildLogMessage(level, logLevel, message);
        if (ex != null) {
            StringWriter writer = new StringWriter(256);
            ex.printStackTrace(new PrintWriter(writer));
            sb.append('\n');
            sb.append(writer.toString().trim());
        }
        print(sb.toString());
    }

    public StringBuilder buildLogMessage(int level, String logLevel, String message) {
        StringBuilder sb = new StringBuilder(256);
        sb.append(logLevel);
        sb.append(stopWatch.getElapsedTime());
        sb.append(message);
        return sb;
    }

    public void print(String message) {
        System.out.println(message);
    }
}

private static final class StopWatch {

    private static long startTime;

    public StopWatch() {
        startTime = getCurrentTime();
    }

    public long getStartTime() {
        return startTime;
    }

    public long getCurrentTime() {
        return System.currentTimeMillis();
    }

    public long getElapsedTime() {
        return getCurrentTime() - startTime;
    }
}

}
[/java]

Before using:
1.) Set the LOG_LEVEL field to the logging level you required. (I usually have the level defined in a Globals class somewhere else in the application)
2.) Modify the Logger class to suit your needs. The example I provided just prints to screen but you can write to file or whatever you required.

To Use:
Log.info(“blah blah”);
Log.error(“Something bad happened!”, exception);

Notes:
1.) Using a final field for the LogLevel allows the compiler to remove and all the if checks so there is no time wasted checking the log level at runtime it just either happens or not. In the above example the compiler will change the debug methods to be blank because it is impossible for DEBUG to be true and therefore the if statement contents can never be run.
2.) Stopwatch uses millisecond precision. If for some reason you want higher resolution you can change it to nanoseconds by changing the getCurrentTIme() method to use System.nanoTime();

Hope someone finds it useful.

Kylar