Helidon MP:如何将 slf4j 日志消息发送到 Kafka 代理?

swe*_*123 1 java slf4j apache-kafka log4j2 helidon

我正在尝试将 Helidon MP 应用程序中的 slf4j 日志消息发送到在端口 9092 上运行的 Kafka 服务器。我有以下类作为示例:

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Service {

  private final ConfigProvider configProvider;

  @Inject
  public Service(ConfigProvider configProvider) {
    this.configProvider = configProvider;
  }

  public String getString() {
    String msg = String.format("%s %s !", configProvider.getString());
    log.info("Entered getString() method");
    return msg;
  }
}
Run Code Online (Sandbox Code Playgroud)

我还有一个logging.xml文件,它将Appender指定为KafkaAppender:

<Configuration>
    <Appenders>
        <Kafka name="KafkaAppender" topic="app-logs"
               syncSend="false">
            <Property name="bootstrap.servers"
                      value="localhost:9092"/>
        </Kafka>
    </Appenders>
    <Loggers>
        <Logger name="org.apache.kafka" level="WARN"/> <!-- avoid recursive logging -->
        <Root level="INFO">
            <AppenderRef ref="KafkaAppender"/>
        </Root>
    </Loggers>
</Configuration>
Run Code Online (Sandbox Code Playgroud)

但是,当我运行该应用程序时,出现以下错误:

2022-11-28 14:23:17,358 main ERROR No layout provided for KafkaAppender
2022-11-28 14:23:17,362 main ERROR Null object returned for Kafka in Appenders.
2022-11-28 14:23:17,364 main ERROR Unable to locate appender "KafkaAppender" for logger config "root"
Run Code Online (Sandbox Code Playgroud)

关于如何让 KafkaAppender 与 Helidon 一起工作有什么建议吗?

小智 6

Helidon 对于日志记录没有做任何特别的事情。唯一需要注意的是 Helidon 使用 JUL ( java.util.logging) 进行日志记录。

KafkaAppender是一个 Log4J2 附加程序,但是您说“指定 slf4j 向 Kafka 发送消息”。

1. 设置 SLF4J 到 JUL 桥接器

请参阅javadoc

将以下依赖项添加到您的pom.xml

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)

您可以通过编程或配置来设置桥。

以编程方式

import org.slf4j.bridge.SLF4JBridgeHandler;

SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
Run Code Online (Sandbox Code Playgroud)

使用logging.properties

如果您使用 Helidon SE,则需要在主类中包含代码才能加载logging.properties. Helidon 为此提供了一个实用程序,请参见下文。如果您使用 Helidon MP,则会自动为您完成此操作。

import io.helidon.common.LogConfig;

LogConfig.configureRuntime();
Run Code Online (Sandbox Code Playgroud)

如果您的主方法中已包含上述语句,则可以通过将以下内容添加到logging.properties文件中来设置桥。

handlers = org.slf4j.bridge.SLF4JBridgeHandler
Run Code Online (Sandbox Code Playgroud)

如果您还没有logging.properties文件,请在下面创建它src/main/resources,以便将其添加到您的项目 JAR 中。

2. 设置 SLF4J 实现

将 Log4J2 bom 导入您的pom.xml

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-bom</artifactId>
            <version>2.19.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
Run Code Online (Sandbox Code Playgroud)

将以下依赖项添加到您的pom.xml

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)

请参阅文档

3.配置Log4J2

请参阅文档

XML 配置文件的默认路径是log4j2.xml. 创建文件于src/main/resources/log4j2.xml

<Configuration>
    <Appenders>
        <Kafka name="KafkaAppender" topic="app-logs" syncSend="false">
            <PatternLayout pattern="%date %message" />
            <Property name="bootstrap.servers" value="localhost:9092"/>
        </Kafka>
    </Appenders>
    <Loggers>
        <Logger name="org.apache.kafka" level="WARN"/> <!-- avoid recursive logging -->
        <Root level="INFO">
            <AppenderRef ref="KafkaAppender"/>
        </Root>
    </Loggers>
</Configuration>
Run Code Online (Sandbox Code Playgroud)

将依赖项添加kafka-clients到您的pom.xml

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)

请注意,除了依赖版本管理和提供的加载实用程序之外,这里没有任何特定于 Helidon 的内容logging.properties。您可以在任何“普通”Java 项目上使用相同的步骤。