Preventing mistakes in the Logger name by copying

Overview

Tips for creating a Logger instance, which are also described in the SLF4J FAQ. Here's a story and a solution to Logger's declaration.

[Problem] Wrong Logger name

A common bug with Logger is the wrong Logger name. This tends to happen if you copy the Logger declaration from another source.

Example of specifying the wrong Logger name


public class MyClass {
  private static final Logger LOGGER = LoggerFactory.getLogger(User.class); //bug!Keep copying from the code of the User class
  //...
}

[Solution] Use Method Handle

By using MethodHandle [^ mh] introduced from Java7, you can get the calling Class object statically. (Use the static method [^ mhs] of the MethodHandles class (return method [^ mhs-lookup]) ← Note that it is not the MethodHandle class [^ mh])

Get Class object


Class<?> clazz = MethodHandles.lookup().lookupClass();

An idiom for generating a Logger using this is posted in the SLF4J FAQ [^ slf4j]. In this case, you can copy and use it as it is (without rewriting the Logger name of the argument).

Logger generation idiom


import java.lang.invoke.MethodHandles;
      
public class MyClass {
  private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
  //...
}

For your own Logger class

If it is your own Logger class, you can prevent the wrong Logger name from being specified by limiting the argument type of the factory method as follows. I wrote about my own Logger class earlier. → Use LocationAwareLogger for your own Logger

Factory method argument MethodHandles.Look up only


import java.lang.invoke.MethodHandles;

public class MyLocationAwareLogger {
  // (Omitting parts unrelated to this topic)

  //Constructor private
  private MyLocationAwareLogger(org.slf4j.spi.LocationAwareLogger logger) {
    this.logger = logger;
  }

  //Factory method(Only this method is exposed)
  public static MyLocationAwareLogger getLogger(MethodHandles.Lookup lookup) {
    return getLogger(lookup.lookupClass());
  }

  //Factory methods other than the above are private
  private static MyLocationAwareLogger getLogger(Class<?> clazz) {
    org.slf4j.spi.LocationAwareLogger logger = (org.slf4j.spi.LocationAwareLogger) LoggerFactory.getLogger(clazz);
    return new MyLocationAwareLogger(logger);
  }

  // (Omitting parts unrelated to this topic)
}

Logger generation


private static final MyLocationAwareLogger LOGGER = MyLocationAwareLogger.getLogger(java.lang.invoke.MethodHandles.lookup());
//The following will result in a compilation error
// private static final MyLocationAwareLogger LOGGER_NG1 = MyLocationAwareLogger.getLogger(User.class);
// private static final MyLocationAwareLogger LOGGER_NG2 = MyLocationAwareLogger.getLogger("User");

at the end

Although it is only a Logger name, if an incorrect value is specified, it will have a tremendous adverse effect on defect investigation. I think there are many people who have been fooled by the Logger name and end up investigating endlessly unrelated parts of the bug. It's an easy tip to introduce, so please try it.

Recommended Posts

Preventing mistakes in the Logger name by copying
I checked the package name referenced by the class contained in the JAR file
Sort by multiple fields in the class
Call a method of the parent class by explicitly specifying the name in Ruby
When you get lost in the class name
Customize the bean name set by Spring component-scan
[Java] Judgment by entering characters in the terminal
Format of the log output by Tomcat itself in Tomcat 8
[Kotlin] Get the argument name of the constructor by reflection
Read the packet capture obtained by tcpdump in Java
Get the anime name for this term by scraping
Get the name of the test case in the JUnit test class
Include the source code generated by Doma in the source JAR