Search code examples
javaframeworkslog4j2slf4j

Log4j common custom interface


I am using slf4j and log4j2 and i want to create a common interceptor. like below so in future if any log4j uprade came up, i would not have to change every class. Please review below code and let me know your thoughts regarding performance and memory. Is there any other better way we can do this?

Class LoggingHelper {

    public static void logEvent(Class clazz, String message, Object ...args) {
      Logger logger = LoggerFactory.getLogger(clazz);
       logger.info(message,args);
    
    }

}

Solution

  • Protecting users against changes in the underlying implementation is exactly what APIs like SLF4J or Log4j2 API (cf. API separation) are for. Although a semantic major version bump in the API can break consumer code, no such change ever occurred: e.g. the recent 2.x version of SLF4J semantically is a minor version bump and only requires updates in the implementations.

    Using API wrappers like the one you are proposing is usually a bad idea, because you have to reimplement a lot of details that the API already takes care of. In your example:

    • instantiating a logger is an expensive operation, that is why loggers are almost always static fields or are instantiated in constructors of services (cf. Static vs non-static loggers),
    • your wrapper breaks location information: all logs will appear to be generated by LoggingHelper,
    • your wrapper always creates a temporary varargs array, which must be then collected by the GC. Logging APIs don't create temporary objects for the most common cases: SLF4J supports up to 2 non-varargs parameters, Log4j2 API supports up to 10 non-varargs parameters (cf. garbage-free logging).

    Software systems have a tendency to abandon their custom logging APIs: e.g. Jetty dropped its custom logging API in version 10.x.