Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java logging framework which does not require LOGGER declaration on every class

I tried the following loggers

  • Java Logging API
  • Log4j
  • slf4j

All of these requires a LOGGER declaration at the class level, like the ones below

private final static java.util.logging.Logger.Logger LOGGER = java.util.logging.Logger.Logger.getLogger(MyClass.class.getName());
private final Logger slf4jLogger = LoggerFactory.getLogger(SLF4JHello.class);
private final static Logger log4jLogger = Logger.getLogger(Log4jHello.class);

This looks hideous to me, is there an logger framework in java that does not require this declaration?

What I'm looking for is, I can have a global declaration like

private final static Logger Logger = Logger.getLogger(MyApp.class);

But when I call Logger.log(..) from class XXX.class then the Logger should make use of the XXX.class name.

like image 244
Edi Avatar asked Feb 24 '16 03:02

Edi


1 Answers

Your problem is more than likely not with the logging framework but with the layout.

Concrete example

so35592962/App.java

package so35592962;
import org.apache.logging.log4j.*;
import so35592962.sub.OtherClass;
public class App {
  public static final Logger logger = LogManager.getLogger();
  public static void main(String[] args) {
    logger.error("in App.main");
    OtherClass.act();
  }
}

so35592962/sub/OtherClass.java

package so35592962.sub;
import static so35592962.App.logger;

public class OtherClass {
  public static void act() {
    logger.error("OtherClass.act");
  }
}

So you can see this is totally what you want: classes that use a single logger. So good point, Log4J2 can be used for that.

Now I add the magic file log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %C{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

Running this will print:

12:05:28.834 [main] ERROR so35592962.App - in App.main
12:05:28.836 [main] ERROR so35592962.sub.OtherClass - OtherClass.act

Look, there are different class names here! Yet I used Log4J2.

What happened here?

Note the pattern used in the PatternLayout tag:

%d{HH:mm:ss.SSS} [%t] %-5level %C{36} - %msg%n

The standard examples and what you usually see on the Internet all use the %L pattern. This pattern is to show the logger name. But you said you don't want it. Fortunately, other patterns exist. %C will show the class name instead of the logger name. This is the pattern that is used here.

According to the PatternLayout documentation, the %C pattern does the following:

Outputs the fully qualified class name of the caller issuing the logging request.

Important note, also mentioned in the documentation:

Generating the class name of the caller (location information) is an expensive operation and may impact performance. Use with caution.

like image 132
Olivier Grégoire Avatar answered Oct 14 '22 18:10

Olivier Grégoire