我一直在为记录器依赖项摸不着头脑。我希望我自己的代码使用 SLF4J 2 API,并在测试和运行时使用 Log4J2 作为提供程序。但是,我依赖于使用 Log4J1 的 OpenLr 二进制包。此外,我想设置遥测并导出我的日志。
我找到了这些文档:
看起来正确的依赖关系是:
<dependencyManagement>
<dependencies>
<!-- Set SLF4J 2 API version -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Set Log4J 2 API version -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
...
<!-- Use SLF4J API so logging framework is code independent. -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Redirect dependencies using Log4j 1 to Log4j 2 instead. -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- Add logging framework. -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>${log4j.version}</version>
<!-- includes log4j-api of same version -->
</dependency>
<!-- OpenTelemetry to produce metrics and logs -->
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>${opentelemetry.version}</version>
</dependency>
<!-- Dependencies needed for Geneva export with OTLP agent on docker -->
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
<version>${opentelemetry.version}</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
<version>${opentelemetry.version}</version>
</dependency>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-log4j-appender-2.17</artifactId>
<version>${opentelemetry.version}-alpha</version>
<scope>runtime</scope>
</dependency>
在另一个没有 opentelemetry 的模块中,这些设置似乎有效,但在主项目 SLF4J 中找不到绑定。一位队友告诉我,以下方法(设置日志记录以使用 log4j-reload)有效:
<!-- Use SLF4J API so logging framework is code independent. -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Add logging framework. -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
我只是不确定为什么 log4j 2 提供程序无法工作。与 OpenTelemetry 是否不兼容?请帮我理解。
最终我们开始更深入地研究,并意识到还有其他日志框架和其他子项目导致了一些问题。我们确保通过依赖管理设置所需的版本,并最终得到以下日志桥:
<!-- Use SLF4J API so logging framework is code independent -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>
<!-- Use Log4j 2 as logging provider -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>${log4j.version}</version>
<scope>test</scope>
<!-- Includes log4j-api of same version -->
</dependency>
<!-- Redirect dependencies using Log4j 1 to Log4j 2 instead -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>${log4j.version}</version>
<scope>test</scope>
</dependency>
<!-- Redirect dependencies using JCL to Log4j 2 instead. -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<version>${log4j.version}</version>
<scope>test</scope>
</dependency>
为了确保日志记录在本地执行中正常工作,我们在对象的惰性 val(单例)初始化时覆盖一次配置,如下所示:
val loggerContext = LogManager.getContext(false).asInstanceOf[LoggerContext]
// load our custom configuration
val customLog4j2Config = new XmlConfigurationFactory().getConfiguration(
loggerContext,
this.getClass.getName,
log4j2ConfigFile
)
customLog4j2Config.initialize()
// transfer missing appenders to our config
loggerContext.getConfiguration
.getAppenders
.values()
.forEach(
appender => {
if (
!customLog4j2Config
.getAppenders
.containsKey(appender.getName)
) {
customLog4j2Config.addAppender(appender)
}
}
)
// transfer missing loggers to our config
loggerContext.getConfiguration
.getLoggers
.values()
.forEach(
loggerConfig => {
if (
!customLog4j2Config
.getLoggers
.containsKey(loggerConfig.getName)
) {
customLog4j2Config.addLogger(loggerConfig.getName, loggerConfig)
}
}
)
// update the context to use our custom config
loggerContext.reconfigure(customLog4j2Config)
loggerContext.updateLoggers()
}