Java: Custom logger factory that automatically infers the class name

In this post I show how you can declare loggers like this:

public class MyService {
    private static final Logger LOG = MyLoggerFactory.getLogger();

There is no argument to the MyLoggerFactory::getLogger method. Contrast that to the normal way to declare a logger:

public class MyService {
    private static final Logger LOG = LoggerFactory.getLogger(MyService.class);

This is business as usual. But have you ever made that silly mistake where you copy/paste a class – and then, in the new class, forget to change the argument to that logger? It can be horribly misleading when reading log files afterwards.

The custom MyLoggerFactory::getLogger method is really super simple to implement: 3 lines of meat.

UPDATE: Alternative to the custom factory

On Reddit, while announcing this post, I was made aware of a simple alternative to the custom logger factory technique described in this post:

public class MyService {
    private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.Lookup.lookupClass());

That technique uses a plain standard Java SE API to get the class name – see [1]. Personally I think this is a clever technique as well!

I guess it is a matter of personal preferences to decide which logger declaration you want to use. If you still find the logger factory compelling – then read on…


I have prepared an example on GitHub – consult that to see the code in its entirety and full context. But here it goes, using SLF4j/Logback:

package com.never.that.copy.paste.mistake.again;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyLoggerFactory {

    public static Logger getLogger() {

        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

        String callersClassName = stackTrace[2].getClassName();

        return LoggerFactory.getLogger(callersClassName);

3 lines of meat. The magic number 2 represents the class calling MyLoggerFactory::getLogger. The first positions in the stackTrace array represents the invocation to the Thread::getStackTrace method as well as this MyLoggerFactory::getLogger method itself.

I chose to name the method getLogger here, so that it aligns with the underlying logging framework SLF4j/Logback.

Please note, that no code here is specific to SLF4j/Logback: So go ahead and implement a corresponding factory for your own favorite logging framework.

The example on GitHub has a very limited JUnit test that shows it works as expected:

package com.never.that.copy.paste.mistake.again;

import org.junit.Test;
import org.slf4j.Logger;

import static org.junit.Assert.assertEquals;

public class MyLoggerFactoryTests {

    public void getLogger_whenGivenNothing_thenReturnsLoggerWithCallersClassName() {

        // Given
        // ( a little bit of magic ... )

        // When
        Logger loggerOne = MyLoggerFactory.getLogger();
        Logger loggerTwo = LoggerTester.LOG;

        // Then
        assertEquals(MyLoggerFactoryTests.class.getName(), loggerOne.getName());
        assertEquals(LoggerTester.class.getName(), loggerTwo.getName());

    private static class LoggerTester {
        private static final Logger LOG = MyLoggerFactory.getLogger();


That’s all there is to it.


[1] Java SE’s MethodHandles API:–

Latest Comments

  1. Robert says:

    Thanks for sharing this technique. It is valuable.

  2. Tom says:

    private final Logger log = LoggerFactory.getLogger(getClass());

    Simple and solid. No need to be static. You get a pooled Reference which does the same purpose.

  3. Stefano says:

    My only doubt is that the approach that you use can be expensive ’cause of exception stacktrace. In some my experiements i use also another technique []. It seems that using MethodHandles can be a good compromise and you can use it in Java 7+

    • moelholm says:

      Fine point. I did mention MethodHandles above ;). Regarding expensiveness: In practice you won’t “feel” it. And that’s how I choose which performance battles I want to engage in.(remember it’s a one time cost per class that needs to log)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s