JavaTip: Lazy Loading for Efficient Java Logging

Tip: Lazy Loading for Efficient Java Logging

It is always a good Java programming practice to prefix log statements with a check for “loggability” by testing Logger.isLoggable(Level) prior to logging. However, this practice presents Java developers with a dilemma: Failing to do so results in slower performance, but following it contributes to more total lines of code. Often, developers opt to just bypass it.

In this intermediate Java tip, Jason Weinstein offers a solution: lazy loading. By wrapping Java logging in your own class (as shown below), you can ensure the isLoggable() test is always made, while at the same time lazily binding the message creation so that it occurs only when the message is going to be logged.

Logger logger = Logger.getLogger("your class name");

Here’s an example of bad logging practice:

    logger.log(Level.FINE, "your message " + foo + " " + bar);

Note the string concatenation and toString() calls made regardless of whether the message is logged or not.

Here’s an example of good logging practice:

if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "your message " + foo + " " + bar);
}

Here’s an example of how lazy logging can simplify the good practice above:

LazyLogger logger = LazyLogger.getLogger("your class name");

// avoids string concatenation and toString() method calls

logger.log(Level.FINE, "your message ", foo, " ", bar);

Here’s a full example class:

public class LazyLogger {
private final Logger logger;

public LazyLogger(Logger logger) {
if (logger == null) {
throw new IllegalArgumentException("logger cannot be null");
}
this.logger = logger;
}

public static LazyLogger getLogger(String name) {
Logger logger = Logger.getLogger(name);
return new LazyLogger(logger);
}

public void finest(Object... params) {
log(Level.FINEST, params);
}

public void finer(Object... params) {
log(Level.FINER, params);
}

public void fine(Object... params) {
log(Level.FINE, params);
}

public void config(Object... params) {
log(Level.CONFIG, params);
}

public void info(Object... params) {
log(Level.INFO, params);
}

public void warning(Object... params) {
log(Level.WARNING, params);
}

public void severe(Object... params) {
log(Level.SEVERE, params);
}

public void log(Level level, Object... params) {
// Check logging level before continuing
if (logger.isLoggable(level)) {
String message;
if (params != null) {
if (params.length == 1) {
message = String.valueOf(params[0]);
} else {
StringBuilder buf = new StringBuilder();
for (Object param : params) {
buf.append(param);
}
message = buf.toString();
}
} else {
message = "null";
}
logger.log(level, message);
}
}

public static void main(String[] args) {
LazyLogger logger = LazyLogger.getLogger("main");
logger.log(Level.FINE, "Hello", " ", "World");
}
}

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories