【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存

Java,SDK,日志,Hub · 浏览次数 : 243

小编点评

**代码结构** * **App.java** :主类 * **logger** :日志对象 * **azureEventHubConnectionString** :事件 hub 连接字符串 * **azureEventHubHostName** :事件 hub名称 * **eventHubConsumerAsyncClient** :事件消费者 * **eventHubClientBuilder** :事件 hub 建立者 * **eventHubClient** :事件 hub * **eventProcessorClientBuilder** :事件处理者 建立者 * **eventProcessor** :事件处理者 * **eventHubConsumer** :事件消费者 **日志输出** * **recollect consumer** :重新采集消费者 * ** Press enter to stop.** :用户输入停止事件

正文

问题描述

在使用Azure Event Hub的SDK时候,常规情况下,发现示例代码中并没有SDK内部的日志输出。因为在Java项目中,没有添加 SLF4J 依赖,已致于在启动时候有如下提示:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

那么,有什么方便的办法,能把SDK中,内部处理Event Hub的日志打印出来,并且保存在日志文件中呢?

问题解答

是的,如提示所说,使用 SLF4J 就可以了。因为Azure Event Hub SDK中使用 (com.azure.core.util.logging.ClientLogger) 对日志进行输出,所以在最外层(应用代码级)就需要有一个接收日志的Provider,那就是SLF4J。

下面的步骤,就是展示如何添加SLF4J依赖,如何添加输出到文件,输出到Console的配置,最后查看输出结果。

 

前提要求根据官方示例代码,已经成功运行消费端应用:https://docs.azure.cn/zh-cn/event-hubs/event-hubs-java-get-started-send (文末附带本文的示例代码)

第一步:在 pom.xml 中添加 SLF4J 的3个依赖项

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.25</version>
  </dependency>
  <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.25</version>
  </dependency>
  <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
  </dependency>

 

第二步:在 .\src\main\resources 目录中添加 log4j.properties 文件,并设置最关键的 日志输出级别路径格式

# Root logger option
log4j.rootLogger=INFO, stdout, FILE
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n

# Direct log messages to file

# Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
# Set the name of the file
log4j.appender.FILE.File=Logs/log.out
# Set the immediate flush to true (default)
log4j.appender.FILE.ImmediateFlush=true
# Set the threshold to debug mode
log4j.appender.FILE.Threshold=debug
# Set the append to false, overwrite
log4j.appender.FILE.Append=false
# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n

 

第三步: 检查输出结果

1)实验项目的文件结构

2)pom.xml 中添加的 slf4j 依赖

3)为日志输出到文件和控制台配置属性

4)查看文件日志输出 

5)查看控制台日志输出

 

 

附录一:本文实验中的全部代码

1:POM.XML 文件内容

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>ConsumeMessageAbort</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>ConsumeMessageAbort</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-messaging-eventhubs</artifactId>
      <version>5.12.2</version>
    </dependency>
    <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-messaging-eventhubs-checkpointstore-blob</artifactId>
      <version>1.14.0</version>
    </dependency>
    <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-identity</artifactId>
      <version>1.5.3</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.25</version>
  </dependency>
  <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.25</version>
  </dependency>
  <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
  </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.5.5</version>
        <configuration>
          <archive>
            <manifest>
              <mainClass>com.example.App</mainClass>
            </manifest>
          </archive>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

 

2:src\main\resources\log4j.properties 文件内容

# Root logger option
log4j.rootLogger=INFO, stdout, FILE
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n

# Direct log messages to file
# Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
# Set the name of the file
log4j.appender.FILE.File=Logs/log.out
# Set the immediate flush to true (default)
log4j.appender.FILE.ImmediateFlush=true
# Set the threshold to debug mode
log4j.appender.FILE.Threshold=debug
# Set the append to false, overwrite
log4j.appender.FILE.Append=false
# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n

 

3:src\main\java\com\example\App.java 文件内容

package com.example;

import com.azure.messaging.eventhubs.EventData;
import com.azure.messaging.eventhubs.EventHubClientBuilder;
import com.azure.messaging.eventhubs.EventHubConsumerAsyncClient;
import com.azure.messaging.eventhubs.EventProcessorClientBuilder;

import java.io.IOException;
import java.sql.Date;
import java.time.Instant;
import java.time.temporal.TemporalUnit;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Hello world!
 *
 */
public class App {

    final static Logger logger = LoggerFactory.getLogger(App.class);
    private static final String azureEventHubConnectionString = "event hub namespace connection string";
    private static final String azureEventHubHostName = "event hub name";

    public static void main(String[] args) throws IOException {
        System.out.println("Hello World!");

        EventHubConsumerAsyncClient consumer = new EventHubClientBuilder()
                .connectionString(azureEventHubConnectionString, azureEventHubHostName)
                .consumerGroup(EventHubClientBuilder.DEFAULT_CONSUMER_GROUP_NAME)
                .buildAsyncConsumerClient();

        try {
            consumer.receive(true).subscribe(
                    event -> {
                        EventData data = event.getData();
                        String message = "SequenceNumber is" + data.getSequenceNumber().toString()
                                + " The eventData is "
                                + data.getBodyAsString();
                        System.out.println(message);
                        logger.info(message);
                    },
                    error -> logger.error("The iot hub failed to listen for messages, error is {}" + error.toString()));

        } catch (Exception e) {
            consumer = new EventHubClientBuilder()
                    .connectionString(azureEventHubConnectionString, azureEventHubHostName)
                    .consumerGroup(EventHubClientBuilder.DEFAULT_CONSUMER_GROUP_NAME)
                    .buildAsyncConsumerClient();
            System.out.println("recollect consumer");
            logger.warn("recollect consumer");
        }

        System.out.println("Press enter to stop.");
        logger.info("Press enter to stop.");
        System.in.read();

        System.out.println("...End...");
    }

}

 

4:文件结构

 

 

参考资料

开启 Apache Flink 制造者 Producer 示例代码中的日志输出 : https://www.cnblogs.com/lulight/p/15789878.html

使用 Java 向/从 Azure 事件中心 (azure-messaging-eventhubs) 发送/接收事件 : https://docs.azure.cn/zh-cn/event-hubs/event-hubs-java-get-started-send

 

与【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存相似的内容:

【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存

问题描述 在使用Azure Event Hub的SDK时候,常规情况下,发现示例代码中并没有SDK内部的日志输出。因为在Java项目中,没有添加 SLF4J 依赖,已致于在启动时候有如下提示: SLF4J: Failed to load class "org.slf4j.impl.StaticLog

【Azure 事件中心】Event Hub 无法连接,出现 Did not observe any item or terminal signal within 60000ms in 'flatMapMany' 的错误消息

2022-11-03 10:58:21.474 INFO --- [pool-7-thread-1] c.a.m.e.PartitionBasedLoadBalancer []: Load balancer already running 2022-11-03 10:58:51.014 WARN --- [ parallel-2] c.a.m.e.Partition

【Azure 事件中心】Azure Event Hub中的数据能不能存储大于7天呢?如果7天之后是不是会自动删除呢?

问题描述 Event Hub中有个retention的设置为7天,有没有办法增大这个Retention的时间? 如果没办法,是不是超过7天的数据就会被删除? 问题解答 因为Azure Event Hub(事件中心)是一个实时事件流引擎,其设计意图并不是用于代替数据库以及/或者用作无限期保存的事件流的

【Azure 事件中心】使用Apache Flink 连接 Event Hubs 出错 Kafka error: No resolvable bootstrap urls

问题描述 参考Github上 Event Hub的示例代码(Using Apache Flink with Event Hubs for Apache Kafka Ecosystems : https://github.com/Azure/azure-event-hubs-for-kafka/tre

【Azure 事件中心】Event Hubs中存在非常多的错误数据,是否能提前删除这些数据呢?

问题描述 因为一些特殊原因,Event Hub 里面堆积了很多不需要的数据事件,正常要等事件中的过期时间到后才有Event Hub自动删除掉,但希望能够尽快马上删除,有没有什么手动的方法吗? 问题解答 Event Hub是一个数据事件处理服务,最主要的功能就是:接收和发送事件。它并不是一个数据存储服

【Azure 事件中心】向Event Hub发送数据异常 : partitionId[null]: Sending messages timed out

问题描述 在使用Java 代码向 Azure Event Hub发送数据时,先后遇见了如下两种异常消息: 1)ERROR c.t.d.h.s.source.EventHubLogConsumer - Error occurred in partition processor for partitio

【Azure事件中心】使用Python SDK(Confluent)相关方法获取offset或lag时提示SSL相关错误

问题描述 使用Python SDK(Confluent)相关方法获取offset或lag时, 提示SSL相关错误, 是否有更清晰的实例以便参考呢? 问题解决 执行代码,因为一直连接不成功,所以检查 confluent_kafka 的连接配置,最后定位是 sasl.password 值设置有误。此处,

【Azure 事件中心】通过 az rest --method get 如何获得Event Hub Entity 级的统计指标

问题描述 通过 az rest --method get 如何获得Event Hub Entity 级的统计指标? 问题解答 查阅文档 https://learn.microsoft.com/en-us/rest/api/monitor/metrics/list?tabs=HTTP , 可以通过 f

【Azure 事件中心】Event Hub服务中的度量值指标介绍

问题描述 Event Hub服务中的度量值指标解说 1)request和message的区别 2)capture backlog 和 capture message 怎么理解 3)quota exceed error, 哪里可以知道这个quota 4)size 是指的存储大小 5) 为EventHu

【Azure 事件中心】Azure Event Hub客户端遇见 Expired Heartbeat 错误

问题描述 Azure Event Hub 在消费数端中,经常性遇见 Expired Heartbeat 错误 (consumer-xxxxxxxxxxxxx-c84873c6c828e8df6c843861ad36affb from group xxxxxxxxxxxx due to expired