如何使用我的日志格式简单地创建自己的自定义控制台记录器?

时间:2017-05-21 14:01:01

标签: java logging

我使用标准的Java日志记录api,即java.util.logging

关于这一点的教程,我发现使用extends Formatter,但在java 8 Formatter中是最终的。

我想要的是创建自己的类来确定在控制台中发送的消息的格式。这是我未完成的初始化日志记录的代码:

 // Init logger
 {
    // get the global logger to configure it
    Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
    // Remove all old/default loggers
    Logger rootLogger = Logger.getLogger("");
    java.util.logging.Handler[] handlers = rootLogger.getHandlers();
    for(java.util.logging.Handler h: handlers)
        rootLogger.removeHandler(h);

    logger.addHandler(new ConsoleLoggerBase());
 }

这是我登录stdout的课程:

package cz.autoclient.logging;

import java.util.logging.Handler;
import java.util.logging.LogRecord;

public class ConsoleLoggerBase extends Handler {

    @Override
    public void publish(LogRecord record) {
        System.out.println(record.getMessage());
    }

    @Override
    public void flush() {
        System.out.flush();
    }
    // No need to close system.out
    @Override
    public void close() throws SecurityException {}
}

但程序日志是空的......我很惊讶在互联网上找不到关于此的简明信息。任何人都可以解释我应该如何使用这个API?

1 个答案:

答案 0 :(得分:0)

您必须始终hold a strong non-local reference要修改的记录器。否则,您的记录器可能会与新连接的处理程序一起被垃圾收集。

正如Java Logging Overview

中所述
  

记录器会在日志记录命名空间中跟踪其父记录器。记录器的父级是其在日志记录命名空间中最近的现存祖先。根记录器(名为"")没有父记录。

您正在将处理程序附加到GLOBAL_LOGGER_NAME。全局记录器的父级是根记录器。通常情况下,全局记录器没有子节点,除非您直接写入全局记录器,否则您将看不到任何输出。我的建议是忘记使用全局记录器。而是专注于修改根记录器的输出格式,并让应用程序代码创建命名记录器。

您不必创建自定义处理程序。而是创建一个自定义格式化程序并将其安装在连接到根记录器的ConsoleHandler上。

以下是一个示例程序:

import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class ModifyRoot {

    private static final Logger[] PINNED_LOGGERS;

    static {
        //Assuming the default config file.
        PINNED_LOGGERS = new Logger[]{
            Logger.getLogger(""),
            Logger.getLogger(ModifyRoot.class.getName())
        };

        for (Logger l : PINNED_LOGGERS) {
            for (Handler h : l.getHandlers()) {
                if (h instanceof ConsoleHandler) {
                    h.setFormatter(new DynamicFormatter());
                    h.setLevel(Level.ALL);
                }
            }
        }

        //Safe because it is already pinned.
        Logger.getLogger(ModifyRoot.class.getName()).setLevel(Level.ALL);
    }

    private static class DynamicFormatter extends java.util.logging.Formatter {

        @Override
        public String format(LogRecord record) {
            if (isJumpSite(record)) {
                return record.getSourceClassName() + '.'
                        + record.getSourceMethodName() + ' '
                        + formatMessage(record) + System.lineSeparator();
            } else {
                return formatMessage(record) + System.lineSeparator();
            }
        }

        private boolean isJumpSite(LogRecord record) {
            //Check the raw message not the formatted message.
            final String msg = String.valueOf(record.getMessage());
            return msg.startsWith("ENTRY") || msg.startsWith("RETURN")
                    || msg.startsWith("THROW");
        }
    }

    //========
    private static final String CLASS_NAME = ModifyRoot.class.getName();
    private static final Logger logger = Logger.getLogger(CLASS_NAME);

    public static void main(String[] args) {
        logger.entering(CLASS_NAME, "main");
        logger.info("Hello World!");
        logger.exiting(CLASS_NAME, "main");
    }
}

哪个输出:

ModifyRoot.main ENTRY
Hello World!
ModifyRoot.main RETURN

您应该考虑使用java.util.logging.config.file系统属性配置记录器并创建自己的logging.properties文件。