乐趣区

关于java:log4j的替换方案

去年 12 月份,随着 log4j 暴露出高危破绽,对于 Java 开发人员来说不是一个好消息,对于 Ops 来说更是如此。前者必须应用固定的 Log4J 版本从新打包他们的应用程序,而后者必须重新部署。但对于程序 log 来说,并不只是。明天让咱们来理解一下 java 零碎自带的 log 机制

简而言之,System.Logger 它是日志引擎的一个 API。与其应用 SFL4J 的 API 和想要的实现,不如应用 System.Logger。Java 9 开始 java 就曾经凋谢了 System.Logger,但我最近才晓得它,这真是令人遗憾。

System.Logger API

该 API 与其余日志记录 API 有点不同:它防止了不同的日志记录办法,例如 debug(),反对传递日志记录参数 info() 的繁多办法。log()“Level


如果您没有在类门路上提供任何相应的实现,则 System.Logger 默认为 JUL。

public class LoggerExample {private static final System.Logger LOGGER = System.getLogger("c.f.b.DefaultLogger"); // 1

  public static void main(String[] args) {LOGGER.log(DEBUG, "A debug message");
      LOGGER.log(INFO, "Hello world!");
  }
}
  1. 获取记录器。

运行下面的代码段会输入以下内容:

Dec 24, 2021 10:38:15 AM c.f.b.DefaultLogger main
INFO: Hello world!

宽泛兼容其余日志零碎

大多数应用程序以后应用 Log4J2 或 SLF4J。两者都提供了兼容的 System.Logger 实现。

对于 Log4J,咱们须要增加两个依赖项:

<dependencies>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>            <!-- 1 -->
        <version>2.17.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>    <!-- 2 -->
        <artifactId>log4j-jpl</artifactId>
        <version>2.17.0</version>
    </dependency>
</dependencies>
  1. Log4J 实现 System.Logger
  2. System.Logger 从到 Log4J 的反对。

与下面雷同的日志记录片段当初输入以下内容:

11:00:07.373 [main] INFO  c.f.b.DefaultLogger - Hello world!

要改用 SLF4J,须要增加以下依赖项:

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>               <!-- 1 -->
        <version>2.0.0-alpha5</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk-platform-logging</artifactId> <!-- 2 -->
        <version>2.0.0-alpha5</version>
    </dependency>
</dependencies>
  1. 根本的 SLF4J 实现。任何其余实现都能够, 例如 Logback。
  2. System.Logger 从到 SLF4J 的反对。
[main] INFO c.f.b.DefaultLogger - Hello world!

你本人的 System.Logger 实现

System.Logger 依赖于 Java 的 ServiceLoader 机制。两者 log4j-jpl 蕴含 slf4j-jdk-platform-logging 一个 META-INF/services/java.lang.System$LoggerFinder 指向 LoggerFinder 实现的文件。


咱们能够基于 System.out 目标创立咱们本人的日志零碎。\
第一步是实现日志自身。

public class ConsoleLogger implements System.Logger {

    private final String name;

    public ConsoleLogger(String name) {this.name = name;}

    @Override
    public String getName() {return name;}

    @Override
    public boolean isLoggable(Level level) {return level.getSeverity() >= Level.INFO.getSeverity();}

    @Override
    public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {if (isLoggable(level)) {System.out.println(msg);
            thrown.printStackTrace();}
    }

    @Override
    public void log(Level level, ResourceBundle bundle, String format, Object... params) {if (isLoggable(level)) {System.out.println(MessageFormat.format(format, params));
        }
    }
}

而后,咱们须要编写代码 System.LoggerFinder:

public class ConsoleLoggerFinder extends System.LoggerFinder {private static final Map<String, ConsoleLogger> LOGGERS = new HashMap<>(); // 1

    @Override
    public System.Logger getLogger(String name, Module module) {return LOGGERS.computeIfAbsent(name, ConsoleLogger::new);              // 2
    }
}

保留所有现有日志的门路:

  1. 如果它不存在,则创立一个记录器并存储它。

最初,咱们创立一个服务文件:

ch.frankel.blog.ConsoleLoggerFinder

当初,运行雷同的代码片段输入:

Hello world!

论断

尽管 API 比起其余更成熟的日志零碎 API 更受限制,但这 System.Logger 是一个好抉择。它提供了作为 JDK 一部分的 api。因而,它防止了其余第三方 api 的破绽危险, 例如 SLF4J 到 Log4J2。

出于这个起因,前期可基于 System.Logger 实现系统日志性能。

退出移动版