Log4j Transform 包含用于对使用 Apache Log4j2 API 的项目的二进制后处理的工具。

Log4j 变换 Maven 插件

Transform 插件用于对项目的编译类进行后处理,并将所有 Log4j 2.x API 调用替换为 LogBuilder 调用,并使用静态预计算的位置。这使您能够在日志中使用位置信息,而无需进行通常用于获取位置信息的昂贵运行时调用。

为什么我们需要它

查找日志调用的位置是一个非常昂贵的操作(几微秒)。

在配备 Java 17 的 Ryzen 7 2700U 笔记本电脑上运行 LocationBenchmark 会得到以下结果

日志接口 同步/异步记录器 线程数 预计算位置 得分 错误 单位

LogBuilder

同步

1

202343,624

±719,875

ops/s

LogBuilder

同步

1

68449,813

±5086,148

ops/s

记录器

同步

1

202579,793

±547,961

ops/s

记录器

同步

1

100105,246

±13748,554

ops/s

记录器

异步

8

726877,012

±38214,575

ops/s

记录器

异步

8

440245,135

±4849,946

ops/s

这些数字表明,当使用 Logger 时,每个日志语句的性能提升约为 5 µs,而当使用 LogBuilder 时,每个日志语句的性能提升约为 9 µs。

相比之下,在同一台机器上禁用位置信息会得到

日志接口 同步/异步记录器 线程数 预计算位置 得分 错误 单位

LogBuilder

同步

1

234666,556

±19759,779

ops/s

LogBuilder

同步

1

212562,315

±3631,670

ops/s

记录器

同步

1

210751,730

±1508,148

ops/s

记录器

同步

1

220837,404

±13248,184

ops/s

记录器

异步

8

743467,533

±38046,044

ops/s

记录器

异步

8

776778,635

±38878,794

ops/s

它是如何工作的

工作原理非常简单:对 Log4j 2.x API 的每次调用,例如

public void helloLog() {
    logger.info(MarkerManager.getMarker("NET"), "Sending {} bytes of data.", 1000);
}

在字节码级别被重写为等效的 LogBuilder 调用

private static final StackTraceElement[] locations = {
        new StackTraceElement("org.apache.logging.log4j.HelloWorld", "HelloWorld.java", "helloLog", 1234)
};

public void helloLog() {
    logger.atInfo()
          .withLocation(locations[0])
          .withMarker(MarkerManager.getMarker("NET"))
          .log("Sending {} bytes of data.", 1000);
}

在当前实现中,位置存储在以 $$Log4j2$$Cache 结尾的类中,因此它们不会意外地被 XML/JSON 序列化器使用。

目标

此插件包含一个目标

log4j-transform:process-classes

绑定到 process-classes 阶段,并编织您的类以包含预计算的位置信息。

log4j-transform:process-classes

完整名称

org.apache.logging.log4j:log4j-transform-maven-plugin:0.1.0:process-classes

描述

在项目类中生成 Log4j 2.x API 调用的静态位置信息。生成的字节码将不依赖于位置信息的运行时解析。

属性
  • 需要执行 Maven 项目

  • 需要在范围为 <code>compile</code> 的情况下解析工件的依赖项

  • 该目标是线程安全的,支持并行构建

  • 默认情况下绑定到 生命周期阶段process-classes

必需参数
名称 类型 描述

<sourceDirectory>

文件

包含要处理的类的目录。它默认为 ${project.build.outputDirectory}

<sourceDirectory>

文件

编织后的类将写入的目录。它默认为 ${project.build.outputDirectory}

可选参数
名称 类型 描述

<includes>

List<String>

要包含的文件。如果为空,将处理所有类文件。

<excludes>

List<String>

要排除的文件。

<staleMillis>

int

设置用于测试类文件是否需要编织的最后修改日期的粒度(以毫秒为单位)。它默认为 0,可以使用 lastModGranularityMs 属性进行配置。

用法

要使用该插件,您需要声明对 log4j-api 版本 2.20.0 或更高版本的依赖项。

将以下配置添加到您的 POM 文件中

<plugin>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-transform-maven-plugin</artifactId>
  <version>0.1.0</version>
  <executions>
    <execution>
      <goals>
        <goal>process-classes</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Maven Shade 插件扩展

此项目包含一个 Apache Maven Shade 插件的 资源转换器 集合,允许您使用其他 Log4j 2.x Core 组件模块。

Log4j 插件缓存转换器

用于 Apache Maven Shade 插件资源转换器,它会合并来自所有包含 Log4j 2.x Core 组件的 jar 的 Log4j2Plugins.dat 插件缓存。

此转换器以前在 edwgiz/maven-shaded-log4j-transformer 中可用,并由其作者捐赠给 Apache 软件基金会。

用法

此资源转换器通常与 ManifestResourceTransformerServicesResourceTransformer 一起使用,以将 Log4j 2.x 库集成到阴影 JAR 中。

典型的配置是

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.4.1</version>
  <dependencies>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId>
      <version>0.1.0</version>
    </dependency>
  </dependencies>
  <executions>
    <execution>
      <id>shade-jar-with-dependencies</id>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <transformers>
          <transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <manifestEntries>
              <Multi-Release>true</Multi-Release>
            </manifestEntries>
          </transformer>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>

开发

Log4j Transform 使用 GitHub 进行源代码管理。

该项目需要与 [17,18) 范围匹配的 Java 编译器,并针对 Java 8

您可以使用以下命令构建和验证源代码

./mvnw verify

您可以使用以下命令构建并查看网站

./mvnw -N site
python -m http.server -d target/site

分发

根据 Apache 软件基金会的发布 分发策略创建流程,项目工件正式可从以下位置获取

有关详细信息,请参阅 发布说明

支持

请记住,此项目仅用于内部使用。您可以使用 GitHub Issues 提出功能请求和错误报告,而不是问题!有关详细信息,请参阅 Log4j 支持策略

安全

如果您遇到未列出的安全漏洞或其他具有安全影响的意外行为,请私下向 Log4j 安全邮件列表 报告。有关更多详细信息,请参阅 Log4j 安全页面

发行说明

0.x.x

这是该项目的第二个版本。

添加

更改

  • 迁移到 logging-parent 10.1.1,并采用其 CI 和 pom.xml 基础设施

  • org.ow2.asm:asm-bom 更新到版本 9.6

0.1.0

发布日期

2023-05-05

这是该项目的第一个版本。

添加

  • 添加了 log4j-transform-maven-plugin 字节码转换工具,以在没有反射的情况下提供位置信息(LOG4J2-3638

  • 添加了 log4j-transform-maven-shade-plugin-extensions 资源转换器,用于 Maven Shade 插件以合并 Log4j2Plugins.dat 插件缓存(LOG4J2-673

发布说明

Log4j Transform 采用由 logging-parent 提供的 CI/CD 基础。您可以简单地使用其发布说明。

许可证

根据一个或多个贡献者许可协议授予 Apache 软件基金会 (ASF) 许可。有关版权所有权的更多信息,请参阅随此作品分发的 NOTICE.txt。ASF 根据 Apache 许可证 2.0 版(“许可证”)向您授予此文件的许可;您不得在不遵守许可证的情况下使用此文件。您可以在以下网址获取许可证副本:https://www.apache.org/licenses/LICENSE-2.0.

除非适用法律要求或以书面形式同意,否则根据许可证分发的软件按“现状”分发,没有任何明示或暗示的担保或条件。请参阅许可证以了解管理许可证下权限和限制的具体语言。