Sometimes you might want to include Java collections content in a log message. But standard Java collections do not provide a useful toString() implementation. So developers often use a helper method like this:
/**
* @param collection A collection
* @return A string listing all collection items
*/
public static String toContentString(Collection<?> collection) {
return Arrays.toString(collection.toArray());
}
Then in typical slf4j log output code you might have something like this:
log.debug("Processing list: {}", toContentString(list));
But if list is long, then this code will cause unnecessary overhead in your application whenever it runs at a log level that does not actually log debug messages.
A simple solution for this is to use a wrapper object instead:
log.debug("Processing list: {}", toStringWrapper(list));
A simple toStringWrapper(..) implementation could be this:
/**
* Provides a wrapper object that can be used for logging of
* collection content
*
* @param collection A collection
* @return A wrapper toString() implementation listing all
* collection items
*/
public static Object toStringWrapper(Collection<?> collection) {
return new Object() {
@Override
public String toString() {
return toContentString(collection);
}
};
}
This postpones the String generation until slf4j actually calls toString() on the log message parameter to substitute it for the ‘{}’ placeholder. And this substitution only happens if the log level actually requires it, i.e. less cpu cycles wasted on unused log message parameters.