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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存

问题描述

在使用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

 

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
20天前
|
Java Maven Android开发
【Azure Developer】VS Code打包Java maven Project 遇见 BUILD FAILURE
Unknown lifecycle phase "lean". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>
|
21天前
|
人工智能 Oracle Java
解决 Java 打印日志吞异常堆栈的问题
前几天有同学找我查一个空指针问题,Java 打印日志时,异常堆栈信息被吞了,导致定位不到出问题的地方。
30 2
|
1月前
FFmpeg【SDK01】日志和字典的使用
FFmpeg中日志功能的使用方法,包括日志级别的设置和AVDictionary的基本操作,同时展示了字符串解析函数如av_parse_video_size、av_parse_video_rate和av_parse_time的应用。
30 2
|
2月前
【Azure Policy】分享Policy实现对Azure Activity Log导出到Log A workspace中
在Policy Rule部分中,选择资源的类型为 "Microsoft.Resources/subscriptions", 效果使用 DeployIfNotExists (如果不存在,则通过修复任务进行修正。 在 existenceCondition 条件中,如果当前订阅已经启用了 diagnostic setting并且输出日志到同一个Log A workspace,表示满足Policy要求,不需要进行修正。 在 deployment 中,使用了 ARM 模板, 为订阅添加Diagnostic Setting并且所有的日志Category均启用。
|
3月前
|
Java 开发工具
通过Java SDK调用阿里云模型服务
在阿里云平台上,可以通过创建应用并使用模型服务完成特定任务,如生成文章内容。本示例展示了一段简化的Java代码,演示了如何调用阿里云模型服务生成关于“春秋战国经济与文化”的简短文章。示例代码通过设置系统角色为历史学家,并提出文章生成需求,最终处理并输出生成的文章内容。在实际部署前,请确保正确配置环境变量中的密钥和ID,并根据需要调整SDK导入语句及类名。更多详情和示例,请参考相关链接。
|
3月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
|
3月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
Java应用结构规范问题之配置Logback以在控制台输出日志的问题如何解决
|
3月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
|
3月前
【Azure Function & Application Insights】在Azure Function的日志中,发现DrainMode mode enabled Traces。它是什么意思呢?
【Azure Function & Application Insights】在Azure Function的日志中,发现DrainMode mode enabled Traces。它是什么意思呢?
|
3月前
|
存储 消息中间件 监控
Java日志详解:日志级别,优先级、配置文件、常见日志管理系统ELK、日志收集分析
Java日志详解:日志级别,优先级、配置文件、常见日志管理系统、日志收集分析。日志级别从小到大的关系(优先级从低到高): ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF 低级别的会输出高级别的信息,高级别的不会输出低级别的信息