Java - 配置自定义记录器以供使用

时间:2016-10-10 15:21:54

标签: java logging java.util.logging

尝试使用java.util.logging并失败。

试图利用https://stackoverflow.com/a/8249319/3322533

handlers = mypackage.logging.RequestFileHandler, mypackage.logging.MainFileHandler
config   =

mainLogger.handlers       = mypackage.logging.MainFileHandler

requestLogger.handlers    = mypackage.logging.RequestFileHandler

java.util.logging.ConsoleHandler.level     = INFO
java.util.logging.ConsoleHandler.filter    =
java.util.logging.ConsoleHandler.formatter = mypackage.logging.VerySimpleFormatter
java.util.logging.ConsoleHandler.encoding  =

mypackage.RequestFileHandler.level     = SEVERE
mypackage.RequestFileHandler.filter    =
mypackage.RequestFileHandler.formatter = mypackage.logging.VerySimpleFormatter
mypackage.RequestFileHandler.encoding  =
mypackage.RequestFileHandler.limit     =
mypackage.RequestFileHandler.count     =
mypackage.RequestFileHandler.append    = false
mypackage.RequestFileHandler.pattern   = REQUESTS.%u.%g.log

mypackage.MainFileHandler.level     = INFO
mypackage.MainFileHandler.filter    =
mypackage.MainFileHandler.formatter = mypackage.logging.VerySimpleFormatter
mypackage.MainFileHandler.encoding  =
mypackage.MainFileHandler.limit     =
mypackage.MainFileHandler.count     =
mypackage.MainFileHandler.append    = false
mypackage.MainFileHandler.pattern   = MAIN.%u.%g.log

,其中

public class MainFileHandler extends FileHandler {
    public MainFileHandler() throws IOException, SecurityException {
        super();
    }
}

public class RequestFileHandler extends FileHandler {
    public RequestFileHandler() throws IOException, SecurityException {
        super();
    }
}

意图:提供两个可通过

访问的记录器
Logger.getLogger("mainLogger");

Logger.getLogger("requestLogger");

分别是(专门)写入MAIN[...].log而另一个写入REQUESTS[...].log

(可以记录到任一文件的消息数量没有限制,如果需要,可以使用日志记录级别将不需要的消息过滤掉。)

但是,当我(例如)

时,两个文件都没有创建
public static final Logger log = Logger.getLogger("mainLogger");

然后

public void configureLogger(){
    try {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        InputStream config = classLoader.getResourceAsStream("logging.properties");

        LogManager.getLogManager().readConfiguration(config);

    }catch(Exception ex){
       throw new RuntimeException("logging properties failed");
    }
}

之前我

log.info("Hello World!")

我知道属性已加载,因为当我在java.util.logging.ConsoleHandler列表中包含handlers = ...并使用全局记录器时,格式化程序将应用于控制台输出。

所以......我想我尝试设置文件记录器是错误的。我如何使这个工作?

修改

所以我删除了[...].pattern = [...]行,而是硬编码了文件名:

public class MainFileHandler extends FileHandler implements FileHandlerProperties {
    public MainFileHandler() throws IOException, SecurityException {
        super("MAIN_" + new SimpleDateFormat(TIME_PATTERN).format(new Date()) + ".log");
    }
}

public class RequestFileHandler extends FileHandler implements FileHandlerProperties {
    public RequestFileHandler() throws IOException, SecurityException {
        super("REQUESTS_" + new SimpleDateFormat(TIME_PATTERN).format(new Date()) + ".log");
    }
}

,其中

public interface FileHandlerProperties {
    static final String TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
}

两个文件现在都已创建但是两者包含完全相同(尽管它们的级别设置和记录器不同),它们包含的内容是xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2016-10-10T18:49:23</date>
  <millis>1476118163654</millis>
  <sequence>0</sequence>
  <logger>mainLogger</logger>
  <level>INFO</level>
  <class>mypackage.main.Main</class>
  <method>&lt;init&gt;</method>
  <thread>1</thread>
  <message>Hello World</message>
</record>
</log>

请帮忙......

1 个答案:

答案 0 :(得分:1)

问题是在类加载期间第一次调用Logger.getLogger会读取日志配置,而configureLogger方法由于JDK-8033661: readConfiguration does not cleanly reinitialize the logging system而失败。

要解决此问题,您必须确保configureLogger在第一次调用Logger.getLogger之前运行。

public class BootMain {

    static {
        configureLogger();
        mainLogger = Logger.getLogger("mainLogger");
        requestLogger = Logger.getLogger("requestLogger");
    }

    private static final Logger mainLogger;

    private static final Logger requestLogger;

    public static void main(String[] args) throws IOException {
        mainLogger.log(Level.SEVERE, "Test from main.");
        requestLogger.log(Level.SEVERE, "Test from request.");
        System.out.println(new File(".").getCanonicalPath());
    }

    private static void configureLogger() {
        try {
            InputStream config = config();
            LogManager.getLogManager().readConfiguration(config);
        } catch (Exception ex) {
            throw new RuntimeException("logging properties failed");
        }
    }

    private static String prefix() {
        return "mypackage.logging";
    }

    private static InputStream config() throws IOException {
        String p = prefix();
        Properties props = new Properties();
        props.put("mainLogger.handlers", p + ".MainFileHandler");
        props.put("requestLogger.handlers", p + ".RequestFileHandler");
        props.put(p + ".RequestFileHandler.level", "SEVERE");
        props.put(p + ".MainFileHandler.level", "INFO");
        props.put(p + ".RequestFileHandler.pattern", "REQUESTS.%u.%g.log");
        props.put(p + ".MainFileHandler.pattern", "MAIN.%u.%g.log");
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        props.store(out, "");
        return new ByteArrayInputStream(out.toByteArray());
    }
}

另外请确保您没有使用旧版本的JDK,否则可能会遇到JDK-5089480: java.util.logging.FileHandler uses hardcoded classname when reading properties

否则您可以使用LogManager config option to manually setup your configuration