跳到主要内容

分布式追踪的上下文传播

分布式追踪允许您的企业应用程序追踪消息从发布者到事件网格再到接收应用程序的流动。有关详细概述,请参阅分布式追踪。有关版本要求的信息,请参阅分布式追踪版本兼容性。

  • PubSub+ OpenTelemetry API库仅支持W3C传播器。
  • 有关配置OpenTelemetry SDK环境变量的信息,请参阅OpenTelemetry SDK配置。
  • 默认情况下,追踪包括后端应用程序(如Jaeger)可见的命令行参数。出于安全原因,重要的是禁用此功能,因为这些参数可能包含敏感信息,如您的用户名和密码。有关说明,请参阅GitHub上的OpenTelemetry文档中的禁用自动资源提供程序。

为分布式追踪集成JMS

使用PubSub+ JMS API将分布式追踪集成到应用程序中有两种方法:

  • 自动集成允许您的应用程序在不修改源代码的情况下注入和提取标准OpenTelemetry数据。

  • 手动集成涉及修改企业应用程序的源代码。这些代码修改允许您将额外的上下文(如行李和追踪状态)注入和提取到消息中。

自动集成

自动集成不需要任何应用程序代码更改即可发送遥测数据。您不需要更改应用程序的启动参数或实现任何额外的库。要使用自动集成:

  1. 从以下位置下载.jar文件,并将它们放置在您的项目中:

    • OpenTelemetry Java instrumentation
    • PubSub+ OpenTelemetry Integration for Solace JMS API 有关OpenTelemetry版本兼容性,请参阅分布式追踪版本兼容性。
  2. 在命令提示符下,输入以下命令以配置您的发布应用程序将OpenTelemetry数据注入到发布的消息中。要允许您的应用程序将追踪数据发送到OTLP端点,您需要更新属性otel.exporter.otlp.endpoint=http://localhost:4317以指向您的收集器的IP地址:

java -javaagent:<absolute-path-to-otel-jar>/opentelemetry-javaagent-all-<otel-java-version>.jar \
-Dotel.javaagent.extensions=<absolute-path-to-solace-jar>/solace-opentelemetry-jms-integration-<solace-opentelemetry-version>.jar \
-Dotel.propagators=solace_jms_tracecontext \
-Dotel.exporter.otlp.endpoint=<http://localhost:4317> \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=none \
-Dotel.instrumentation.jms.enabled=true \
-Dotel.resource.attributes="service.name=SolaceJMSPublisher" \
-jar <your-jms-publisher-application>.jar

其中:

  • <absolute-path-to-otel-jar>是包含您的OpenTelemetry Java Agent JAR文件的目录的绝对文件路径。
  • <absolute-path-to-solace-jar>是包含您的SolacePubSub+ OpenTelemetry JMS Integration JAR文件的目录的绝对文件路径。
  • <http://localhost:4317>是您使用的收集器的URL。示例localhost:4317是本地运行的OpenTelemetry收集器的默认端口。
  • <your-jms-publisher-application>是与您的JMS发布应用程序关联的JAR文件的名称。
  • <otel-java-version>是与PubSub+ OpenTelemetry Integration for Solace JMS API版本(<solace-opentelemetry-version>)兼容的OpenTelemetry Instrumentation Java Library版本。有关兼容性的信息,请参阅分布式追踪版本兼容性。
  • <solace-opentelemetry-version>是与OpenTelemetry Instrumentation Library(<otel-java-version>)一起使用的PubSub+ OpenTelemetry Integration for Solace JMS版本。有关兼容性的信息,请参阅分布式追踪版本兼容性。
  1. 在命令提示符下,输入以下命令以配置您的队列接收应用程序从接收到的消息中提取OpenTelemetry数据:
java -javaagent:<absolute-path-to-otel-jar>/opentelemetry-javaagent-all-<otel-java-version>.jar \
-Dotel.javaagent.extensions=<absolute-path-to-solace-jar>/solace-opentelemetry-jms-integration-<solace-opentelemetry-version>.jar \
-Dotel.propagators=solace_jms_tracecontext \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=none \
-Dotel.instrumentation.jms.enabled=true \
-Dotel.resource.attributes="service.name=SolaceJMSQueueSubscriber" \
-jar <your-jms-queue-receiver-application>.jar

其中:

  • <absolute-path-to-otel-jar>是包含您的OpenTelemetry Java Agent JAR文件的目录的绝对文件路径。
  • <absolute-path-to-solace-jar>是包含您的PubSub+ OpenTelemetry JMS Integration JAR文件的目录的绝对文件路径。
  • <your-jms-queue-receiver-application>是与您的JMS队列接收应用程序关联的JAR文件的名称。
  • <otel-java-version>是与PubSub+ OpenTelemetry Integration for Solace JMS API版本(<solace-opentelemetry-version>)兼容的OpenTelemetry Instrumentation Java Library版本(例如1.29.0)。有关兼容性的信息,请参阅分布式追踪版本兼容性。
  • <solace-opentelemetry-version>是与OpenTelemetry Instrumentation Library(<otel-java-version>)一起使用的PubSub+ OpenTelemetry Integration for Solace JMS版本(例如1.1.0)。有关兼容性的信息,请参阅分布式追踪版本兼容性。

当您使用自动集成时,不应将最新版本的opentelemetry-javaagent-all-<otel-java-version>.jarsolace-opentelemetry-jms-integration-<solace-opentelemetry-version>.jar添加为应用程序的Maven或Gradle依赖项。有关兼容性的信息,请参阅分布式追踪版本兼容性。

对于自动集成,Solace建议您使用OpenTelemetry Instrumentation for Java库版本1.29,Solace已测试该版本与支持自动集成的PubSub+产品兼容。该库的早期版本可能与PubSub+产品不兼容。有关版本详细信息,请参阅https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases。

有关如何在JMS API中设置自动集成的更详细示例,请参阅Solace分布式追踪和上下文传播入门。

手动集成

手动集成涉及修改企业应用程序的源代码,并允许您将额外的上下文(如行李和追踪状态)注入和提取到消息中。上下文传播使调试和优化应用程序变得容易。有关Solace事件消息中上下文传播的更多信息,请参阅分布式追踪上下文传播。以下示例展示了如何使用OpenTelemetry API创建跨度。

了解上下文传播如何在JMS PubSub+ API中启用分布式追踪

在客户端应用程序中,您可以使用OpenTelemetry API创建一个跨度,其中包含分布式系统中操作的元数据。此跨度与上下文相关联,其中包含唯一的TraceID。接下来,当您使用PubSub+消息生产者发布消息时,Solace OTel集成包将上下文(包含TraceID)注入到消息中。当消息通过事件代理并被消费应用程序接收时,每个步骤都会生成跨度,并且原始消息上下文中存在相同的TraceID。当在发布或消费应用程序中关闭每个跨度时,Java OpenTelemetry API将其发送到OpenTelemetry收集器,该收集器收集、处理并将跨度导出到使用其唯一TraceID相关联跨度的后端应用程序。后端应用程序使用相关跨度创建一个_追踪_,这是一个端到端快照,详细说明了消息如何通过分布式系统传输。如果您不使用上下文传播,则后端应用程序无法使用唯一的TraceID链接跨度,使得通过分布式系统追踪消息流动变得困难。

依赖项

要启用分布式追踪的上下文传播,您必须首先将Solace PubSub+ OpenTelemetry Integration For Solace JMS API作为依赖项添加到您的应用程序中。此库自动添加OpenTelemetry API和SDK库,这些库是上下文传播所必需的。有关OpenTelemetry版本兼容性,请参阅分布式追踪版本兼容性。添加库后,您可以访问以下两个接口:

  • SolaceJmsW3CTextMapSetter—此接口允许TextMapPropagator在发布方将上下文注入到消息中。

  • SolaceJmsW3CTextMapGetter—此接口允许TextMapPropagator在接收方从消息中提取上下文。

本指南假设您熟悉配置OpenTelemetry类的实例。有关配置OpenTelemetry对象的说明,请参阅OpenTelemetry文档中的OpenTelemetry Java手动集成。

在消息发布时生成发送跨度

您的发布应用程序可以生成发送跨度并将其导出到OpenTelemetry收集器。以下步骤展示了如何将上下文注入到消息中并为发布的消息生成发送跨度:

  1. 使用setAttribute()方法为新跨度设置跨度属性。接下来,将当前上下文设置为此跨度的父级。使用startSpan()方法启动跨度:
final Span sendSpan = tracer
.spanBuilder("mySolacePublisherApp" + " " + MessagingOperationValues.PROCESS)
.setSpanKind(SpanKind.CLIENT)
// 发布到非临时主题端点
.setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND, MessagingDestinationKindValues.TOPIC)
.setAttribute(SemanticAttributes.MESSAGING_TEMP_DESTINATION, false)
// 根据需要设置更多属性
//.setAttribute(...)
//.setAttribute(...)
.setParent(Context.current()) // 将当前上下文设置为父级跨度
.startSpan();
  1. 将步骤1中创建的跨度(在此示例中为sendSpan)设置为新的当前上下文。接下来,将当前上下文注入到您的消息中,然后发布消息。调用跨度的end()方法以导出跨度数据:
try (Scope scope = sendSpan.makeCurrent()) {
final SolaceJmsW3CTextMapSetter setter = new SolaceJmsW3CTextMapSetter();
final TextMapPropagator propagator = openTelemetry.getPropagators().getTextMapPropagator();
// 将带有发送跨度的当前上下文注入到消息中
propagator.inject(Context.current(), message, setter);
// 将消息发布到给定主题
messageProducer.send(messageDestination, message);
} catch (Exception e) {
sendSpan.recordException(e); // 跨度可以记录异常
sendSpan.setStatus(StatusCode.ERROR, e.getMessage()); // 将跨度状态设置为ERROR/FAILED
} finally {
sendSpan.end(); // 调用end()后导出跨度数据
}

在消息接收时生成接收跨度

您的消费应用程序可以生成接收跨度,然后将其导出到OpenTelemetry收集器。以下步骤展示了如何从接收到的消息中提取追踪上下文并生成接收跨度:

  1. 使用SolaceJmsW3CTextMapGetter从接收到的消息中提取任何现有上下文:
final SolaceJmsW3CTextMapGetter getter = new SolaceJmsW3CTextMapGetter();
final Context extractedContext = openTelemetry.getPropagators().getTextMapPropagator()
.extract(Context.current(), message, getter);
  1. 使用makeCurrent()方法将提取的上下文设置为当前上下文。接下来创建一个子跨度(在此示例中为receiveSpan)并将提取的上下文设置为该子跨度的父级。使用startSpan()方法启动跨度:
try (Scope scope = extractedContext.makeCurrent()) {
// 创建一个子跨度并将提取的/当前上下文设置为该跨度的父级
final Span receiveSpan = tracer
.spanBuilder("mySolaceReceiverApp" + " " + MessagingOperationValues.RECEIVE)
.setSpanKind(SpanKind.CLIENT)
// 如果消息是在非临时队列端点上接收的
.setAttribute(SemanticAttributes.MESSAGING_DESTINATION_KIND,
MessagingDestinationKindValues.QUEUE)
.setAttribute(SemanticAttributes.MESSAGING_TEMP_DESTINATION, false)
// 根据需要设置更多属性
//.setAttribute(...)
//.setAttribute(...)
.setParent(extractedContext) // 为消息发布者的应用程序跨度创建父子关系
.startSpan();

// Try-catch在下一步继续...
}
  1. 接受并处理接收到的消息,然后在接收跨度上调用end()方法以导出跨度数据:
try {
// 在回调函数中对消息执行某些操作
messageProcessor.accept(receivedMessage);
} catch (Exception e) {
receiveSpan.recordException(e); // 如果有异常,跨度可以记录异常
receiveSpan.setStatus(StatusCode.ERROR, e.getMessage()); // 并将跨度状态设置为ERROR/FAILED
} finally {
receiveSpan.end(); // 调用span.end()时导出跨度数据
}