Loggable: a simple log4j meta-library – Part 2

In a recent post I described the goal of my Loggable meta-library. If you haven’t read it yet, I suggest you to do it now.

What we are going to do now is analysing the second main component of the meta-library, the centralized controller Log.

How does it work

The main responsibility of the Log class is handling the logic behind the creation and returning of the Logger instance that the caller class should use. This logic, as we’ve already seen, is driven by the @Loggable annotation.

The Log class will have a single point of access: the public static method get(). Let’s look at if, briefly:

[java highlight=”9″][RAW]
public static Logger get() {
// Retrieve the StacKTraceElement of the caller method
StackTraceElement caller = getCaller();
// Retrieve the caller class
Class<?> clazz = getClass(caller);
// and its Loggable annotation instance
Loggable annotation = getAnnotation(clazz);

logger.debug("Returning a Logger for " + clazz.getSimpleName());

// Retrieve the suitable logger for the caller class and returns it
Logger suitableLogger = getLogger(annotation, clazz);
return suitableLogger;
}
[/RAW][/java]

This method does a precise series of things:

  1. Retrieves the stack trace element related to the caller method
  2. Retrieves the Class<?> instance which describes the caller class
  3. Reads the @Loggable annotation from the caller class
  4. Returns the suitable Logger instance, depending on the class and its @Loggable annotation definition

The whole code for this class will be available within the meta-library package, so I’ll focus just on the main private method: getLogger().

Bonus hint: as you can see, in my development environment the Log class makes a direct access to a Logger instance. This is strictly necessary because of recursions problems: if the Log class would call itself for logging purposes, this will generate a never-ending recursion stack. Try it, and try to explain why: this will be your homework for today 🙂 .

The private getLogger() method

This method is the key for everything, I’d say. It controls the logic and the interpretation of the annotation parameters. It handles the Logger instance creation and retrieval and will be in our scope in the next paragraphs. The source code is the following:

[java][RAW]
private static Logger getLogger(Loggable annotation, Class<?> clazz) {
if (annotation == null)
return LoggerContainer.getRootLogger();

if (annotation.exclude())
return LoggerContainer.getVoidLogger();

// If a "loggerName" parameter has been passed to the annotation,
// returns that specific logger instance
if (!"".equals(annotation.loggerName()))
return LoggerContainer.getInstance(annotation.loggerName(), annotation);

// If no "class" parameter has been passed to the annotation, returns
// the default logger for the caller class …
if (annotation.clazz() == Object.class)
return LoggerContainer.getInstance(clazz, annotation);

// … otherwise use the "class" parameter to build the logger
return LoggerContainer.getInstance(annotation.clazz(), annotation);
}
[/RAW][/java]

What does it do? Just what we said in the previous “episode”:

  1. If no @Loggable annotation has been set for the class, returns the root logger
  2. If the annotation requires the class to be excluded by logging, returns a void logger
  3. If the annotation defines a logger name, returns that logger (= Logger.getLogger(annotation.loggerName()) )
  4. If the clazz parameter of the annotation is still the default (Object.class), returns the default logger for the caller class (= Logger.getLogger(CallerClass.class) )
  5. Otherwise, returns the default logger with the class specified in the annotation (= Logger.getLogger(annotation.clazz()) )

How does this work? This method uses a third class, LoggerContainer. This is a really simple container: when a logger is required, if it has already been built and customized, the same object will be returned; otherwise, the new instance is built, customized, added to the local container and finally returned. This will save time and memory when we call the Log.get() method. (It is a somewhat similar implementation of the static final definition for the usual logger instance).

Conclusion

Given these three simple components, two classes and a single annotation, I tried to build a handy log4j meta-library. I am currently using it in a bunch of personal projects as it has drastically simplified the logging process throughout the whole applications. I found it very helpful and customizable.

I still need some feedback on this project. I will try to complete the setup of the package, and hope to release version 1.0 of the meta-library as soon as possible.

See you soon!

Update: the first official release is now available! Give it a try!

406 thoughts on “Loggable: a simple log4j meta-library – Part 2

  1. My wife and i got fortunate when Raymond could carry out his analysis out of the precious recommendations he grabbed through the web page. It is now and again perplexing to just always be making a gift of things that many some people might have been making money from. So we fully grasp we have the writer to give thanks to because of that. Most of the illustrations you’ve made, the straightforward website navigation, the friendships you help to engender – it’s got most spectacular, and it is letting our son and us know that that topic is excellent, which is incredibly mandatory. Thank you for all!

  2. When I originally left a comment I appear to have clicked on the -Notify me when new comments are added- checkbox and now whenever a comment is added I recieve four emails with the exact same comment. There has to be an easy method you are able to remove me from that service? Thanks a lot.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *