将处理程序添加到每个记录器

use*_*377 1 java logging java.util.logging java-8

我想为我的项目的每个类的每个记录器添加一个自定义处理程序。我有一个 logging.properties 文件,它在最开始时使用:

try (InputStream in = ReportingService.class.getResourceAsStream("logging.properties")) {
    LogManager.getLogManager().readConfiguration(in);
} catch (IOException ex) {
    Logger.getLogger(myClass.class.getName()).log(Level.SEVERE, null, ex);
}
Run Code Online (Sandbox Code Playgroud)

logging.properties 文件如下所示:

handlers=java.util.logging.ConsoleHandler,myPackage.AlertHandler
.level=SEVERE
java.util.logging.ConsoleHandler.level=SEVERE
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
myPackage.AlertHandler.level=SEVERE
myPackage.AlertHandler.formatter=java.util.logging.SimpleFormatter
Run Code Online (Sandbox Code Playgroud)

而 myPackage.AlertHandler.java 看起来像这样:

package myPackage;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import javafx.scene.control.Alert;
public class AlertHandler extends Handler {
    @Override
    public void publish(LogRecord lr) {
        Alert a = new Alert(Alert.AlertType.ERROR);
        a.setTitle("Exception!");
        a.setHeaderText("Exception was thrown, here is the StackTrace:");
        a.setContentText(getFormatter().formatMessage(lr));
        Platform.runLater(()->{a.showAndWait();});
    }
    @Override
    public void flush() {
        //no real handler is open, nothing to flush
    }
    @Override
    public void close() throws SecurityException {
        //no real handler is open, nothing to close
    }
}
Run Code Online (Sandbox Code Playgroud)

读取日志文件没有问题,因为没有更多的 INFO 或 WARNING 消息打印到控制台,只有 SEVERE。但是我的自定义处理程序永远不会被调用,因为从来没有打开过警报窗口。我还尝试将处理程序添加到全局记录器,希望每个其他记录器都继承其处理程序,但它也不起作用:

Logger.getGlobal().addHandler(new AlertHandler());
Logger.getLogger("").addHandler(new AlertHandler());
Run Code Online (Sandbox Code Playgroud)

将处理程序添加到特定记录器按预期工作:如果在类中的任何地方抛出错误,则会打开带有堆栈跟踪的警报窗口。

Logger.getLogger("mySecondClass").addHandler(new AlertHandler());
Run Code Online (Sandbox Code Playgroud)

但我想将此处理程序添加到任何类中的每个记录器!

jme*_*ens 6

但我想将此处理程序添加到任何类中的每个记录器!

如果您希望此处理程序查看所有记录器输出,那么您只需在根记录器上安装一个实例。例如,Logger.getLogger("").addHandler(new AlertHander());

默认情况下,子记录器会将日志记录发布到父处理者

主要问题是您的代码将始终生成 NullPointerException,因为您从未分配过与处理程序一起使用的格式化程序。所以对 getFormatter 的调用将返回 null 然后失败。

public static void main(String[] args) {
    Handler h = new Handler() {

        @Override
        public void publish(LogRecord record) {
        }

        @Override
        public void flush() {
        }

        @Override
        public void close() throws SecurityException {
        }
    };
    System.out.println(h.getFormatter());
}
Run Code Online (Sandbox Code Playgroud)

您还需要:

  1. 添加代码以解析日志管理器为您的处理程序分配的级别、格式化程序和过滤器。
  2. 当未定义级别、格式化程序或过滤器值时,选择合理的默认值。
  3. 使用Platform.runLater处理创建和显示对话框的非JavaFX 应用程序线程
  4. 在您的发布方法中调用 isLoggable 以确定您的处理程序是否应该发布。
  5. 在您的发布方法中捕获运行时异常并通过调用Handler.reportError 来跟踪它们。

让生活变得轻松并创建单元测试以确保您的处理程序在您尝试在野外使用它之前实际工作。