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.


    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.


    You could change both of these to class annotations with Lombok.

  • @Log4j
  • @Slf4j
  • 链接地址: http://www.djcxy.com/p/32524.html

    上一篇: 在rvm下运行ruby app的问题

    下一篇: Java日志框架,它不需要每个类的LOGGER声明