Logging Anti-Patterns, Part I

Recently I refactored a legacy application which based on a self-implemented logging-framework (I replaced the proprietary logging-code with slf4j). Along that I stumbled over a bunch of anti-patterns I want to discuss further on.

1. Logger-instantiation inside a method

In general there should be only one logger per class. Most of the common logging-frameworks are caching their loggers after instantiation. So calling a LoggerFactory inside a method is simply an unnecessary code and a (slight) performance waste. Just instantiate a static final logger in the class and use that one on every logging event.

Anti-pattern

public void foo() {
	...
	Logger logger = LoggerFactory.getLogger(Foo.class);
	logger.info("bar!");
	...
}

Pattern

private final static Logger LOGGER = LoggerFactory.getLogger(Foo.class);

public void foo() {
	...
	LOGGER.info("Bar");
	...
}

2. Logger-instantiation using the exception message

This is one of my favorites: on each exception a new logger is created using the exception message as logger name. That neither makes sense nor does it help when analyzing the log-files. It also wastes resources: if the exception messages differ, every factory-call will create a new logger instance (instead of returning a cached one) and additionally adds the new logger to the factory’s cache. As a result the cache will be blown up with multiple logger instances—which won’t be used furthermore.

Anti-pattern

public void foo() {
	try {
	...
	} catch (Exception e) {
		Logger logger = LoggerFactory.getLogger(e.getMessage());
		logger.error(e.getMessage(), e);
	}
}

Pattern

private final static Logger LOGGER = LoggerFactory.getLogger(Foo.class);

public void foo() {
	try {
		...
	} catch (Exception e) {
		LOGGER.error(e.getMessage(), e);
	}
}

3. Logger-instantiation using the enclosing class’ name as string

For ordinary loggers the factory-method of LoggerFactory should be called passing the enclosing class. Avoid to pass a class’ name as string. If you use the enclosing class, your favorite IDE will automatically suit that occurrence on a change of the class’ name (if you’re using vi or something similar to scourge yourself—at last your compiler tells you about it). Your logger will always be related to the current class’ name, a string will not give you that guarantee.

Anti-pattern

privat final static Logger LOGGER = LoggerFactory.getLogger("de.bar.Foo");

Pattern

private final static Logger LOGGER = LoggerFactory.getLogger(Foo.class);

4. Logger-instantiation somewhere in between

A specialization of a common basic: define your class constants and attributes at the beginning of a class, not somewhere in between [1]. That significantly increases the readability and maintainability of your code. Apparently that also holds for loggers.

Anti-pattern

public class Foo {
	// ... code ...
	private final static Logger LOGGER = LoggerFactory.getLogger(Foo.class);
	// ... even more code ...
}

Pattern

public class Foo {

	private final static Logger LOGGER = LoggerFactory.getLogger(Foo.class);

	// ... code
}

Reference

  1. [1] Martin, Robert C. 2008. Clean Code. Prentice Hall International

Apology in JavaDoc

Recently I stumbled about a lovely piece of JavaDoc:

/**
  * Because of possible changes of the Jar's name 
  * the actual name has to be determined programmatically.
  *
  * Apology to Baldr, Venus, Aphrodite, Lakshmi, Hathor 
  * and all remaining gods of beauty.
  */
public String getJarName() {
  .... // very ugly code
}

Formatting XML with Notepad++

When there is need for a fast and powerful editor I really like Notepad++ [1]. But it bugged me a bit that there isn’t a function for formatting XML.

Recently I stumbled over the plugin “XML Tools” [2] which added the desired functionality. Like!

Two small drawbacks:

  • the default shortcut for formatting is set to CTRL+ALT+SHIFT+B … seriously ?? Anyone out there who can use that shortcut without a cramp in his fingers ?? Fortunately you can simply change that in the shortcut-dialog…
  • the plugin formats if and only if the XML is syntactical correct

Reference

  1. [1] http://notepad-plus-plus.org
  2. [2] http://sourceforge.net/projects/npp-plugins/files/

Using Checkstyle’s suppression filters on Windows and Linux

I have already shown the usage of Checkstyle’s suppression filters in Eclipse and Maven in [1]. But after switching from Linux to Windows (please no comments on that…) I wondered about occurring Checkstyle rule violations I actually had excluded in my checkstyle-suppressions.xml. Those rules were mainly simple exclusions of all files within a certain package:

<suppress checks="[a-zA-Z0-9]*" files="src/main/java/de/foo/bar" />

After searching around, I realized that this was an issue with the given regex in the files-attribute [2]. The simple slash was correctly interpreted on Linux, but didn’t work on Windows. So to make the rules work on both operation systems I replaced the path separator with “[/\\]”:

<suppress checks="[a-zA-Z0-9]*" files="src[/\\]main[/\\]java[/\\]de[/\\]foo[/\\]bar" />

Reference

  1. [1] https://rolf-engelhard.de/?p=46
  2. [2] http://checkstyle.2069334.n4.nabble.com/suppression-filter-regex-td2070198.html

Clearing Checkstyle’s Cache in Eclipse

First of all please notice the nice alliteration in the headline.

A little problem which bugged me while searching the solution for [1] was that I had to change my checkstyle.xml and checkstyle-suppression.xml for several times. Unfortunately Eclipse-CS never noticed these modifications. So I restarted Eclipse every time to make the changes apply.

Then I stumbled by chance on an entry in Eclipse-CS’s bug tracker [2]:

“Alternatively to touching the Checkstyle configuration file you can clear the plugin’s caches by clicking the little yellow refresh button on the Checkstyle preferences page.”

And hey—after putting on my glasses and lowering the nose-screen-distance to “way to near”—there it was: a little yellow button on the preference page!

The little yellow checkstyle refresh button.

The little yellow checkstyle refresh button.

Reference

  1. [1] https://rolf-engelhard.de/?p=239
  2. [2] http://sourceforge.net/tracker/?func=detail&aid=1752586&group_id=80344&atid=559497