Skip to content

JEP 264: Platform Logging API and Service | 平台日志记录 API 和服务

摘要

定义一个最小的日志记录 API,平台类可以使用该 API 记录消息,并提供一个服务接口供消息的消费者使用。库或应用程序可以提供该服务的实现,以便将平台日志消息路由到其选择的日志框架中。如果没有提供实现,则会使用基于 java.util.logging API 的默认实现。

目标

  • 定义并在 java.base 模块中使用,因此不能依赖于 java.util.logging API。
  • 易于被使用外部日志框架(如 SLF4JLog4J)的应用程序采纳。
  • 减少对 java.logging 模块的依赖,以简化 JDK 模块图。
  • 处理引导问题,以便平台类可以在日志消费者初始化之前记录消息。
  • 如果存在 java.logging 模块,则默认通过 java.util.logging API 记录日志消息。

非目标

  • 不旨在定义一个通用的日志记录接口。服务接口只包含 JDK 自身使用所需的最小方法集。
  • 不旨在通过 API 支持编程日志配置(设置级别、目标文件等)。
  • 不旨在将 JDK 中的所有类都转换为通过这个新 API 记录日志。

动机

java.util.logging API 相比,大多数现代日志框架(如 Log4J 2.0、Logback)都分为外观和实现两部分。通过这样的外部框架记录日志的应用程序应该通过提供或支持的外观创建记录器并进行记录。

该提议的服务使应用程序能够配置 JDK 使用与应用程序相同的日志框架:只需要提供一个返回包装首选日志框架的记录器的平台记录器的服务实现即可。

应用程序将继续使用其正在使用的日志框架提供的外观。LoggerFinder 服务使得 JDK 可以配置使用同一框架。

描述

使用 java.util.ServiceLoader API,使用系统类加载器定位和加载全局的 LoggerFinder 实现。如果找不到具体的实现,则使用 JDK 内部默认的 LoggerFinder 服务实现。服务的默认实现在存在 java.logging 模块时使用 java.util.logging 作为后端,以便默认情况下将日志消息路由到 java.util.logging.Logger。然而,LoggerFinder 服务使得应用程序 / 框架能够插入自己的外部日志后端,而无需配置 java.util.logging 和该后端。

LoggerFinder 服务的实现应该能够区分系统记录器(由启动类加载器的系统类使用)和应用程序记录器(由应用程序为自身使用创建的)。这种区分对于平台安全性很重要。记录器的创建者可以将创建记录器的类或模块传递给 LoggerFinder,以便 LoggerFinder 能够确定返回哪种类型的记录器。

JDK 中的类通过调用 System 类的工厂方法获取从 LoggerFinder 创建的记录器:

java
package java.lang;

...

public class System {

    System.Logger getLogger(String name) { ... }

    System.Logger getLogger(String name, ResourceBundle bundle) { ... }

}

JDK 内部的 sun.util.logging.PlatformLogger API 将被修改为通过这些方法返回的系统记录器发出日志消息。

测试

将添加新的测试来测试 LoggerFinder 服务和映射到默认的 java.util.logging 后端。我们还需要验证插入现有外部框架是否正常工作,特别是针对潜在的引导问题。

风险和假设

java.util.logging 是后端时,已转换为使用系统记录器的 JDK 类仍然应该像以前一样通过 java.util.logging 进行配置,并且如果可能,日志消息和级别不应被更改。

某些 Java SE API 当前在其公共签名中公开了 java.util.logging 类型。这可能会阻碍将这些 API 转换为通过系统记录器记录。