消息 Span 的语义约定
状态: 开发中
正在使用 此文档 v1.24.0(或之前版本) 的现有消息传递仪器
- 在消息传递语义约定被标记为稳定之前,不应更改它们默认发出的消息传递约定版本。约定包括但不限于属性、指标和跨度名称、跨度种类和度量单位。
- 在现有主版本中,应引入一个名为
OTEL_SEMCONV_STABILITY_OPT_IN的环境变量,该变量是一个逗号分隔的类别特定值列表(例如,http、databases、messaging)。值列表包括:messaging- 发出新的、稳定的消息传递约定,并停止发出仪器先前发出的旧实验性消息传递约定。messaging/dup- 同时发出旧的稳定消息传递约定和新的稳定消息传递约定,实现无缝过渡。- 默认行为(在没有这些值的情况下)是继续发出仪器先前发出的旧实验性消息传递约定的任何版本。
- 注意:如果同时存在
messaging和messaging/dup,则messaging/dup的优先级高于messaging。
- 在开始发出两组约定后,应至少维护现有主版本(至少进行安全修补)六个月。
- 应在下一个主版本中删除该环境变量。
- 当
messaging/dup出现在列表中时,应为跨度名称、跨度种类和类似的“单一”值概念发出新的、稳定的值。
定义
消息
虽然消息系统不像 HTTP 那样标准化,但假定以下定义适用于大多数具有相似概念的消息系统(名称主要借自 JMS)。
消息是一个带有可能为空的消息体的信封。此信封可能提供传递附加元数据的可能性,通常是键/值形式。
消息由消息生产者发送至
- 物理上:某个消息代理(可以是单个服务器、集群,或通过 IPC 访问的本地进程)。代理处理实际的传递、重试、持久化等。在某些消息系统中,代理可能与(某些)消息消费者相同或共存。对于 Apache Kafka,消息写入的物理代理取决于分区数量,以及哪个代理是写入记录的分区的领导者。
- 逻辑上:某个特定的消息目的地。
根据协议的调度语义,消息可以传递给 0、1 或多个消费者。
生产者
“生产者”是创建和发送消息的特定实例、进程或设备。“发送”是将一条或一批消息传输到中间件或消费者的过程。一些中间件使用“发布”作为发送的同义词。
消费者
“消费者”接收消息并对其进行操作。它使用上下文和数据来执行某些逻辑,这可能导致新事件的发生。
消费者接收、处理和确认消息。“接收”是从中间件获取消息的过程,“处理”是根据消息内容执行操作的过程,“确认”是通知中间件消息已成功处理的过程。
中间件
“中间件”接收消息以将其转发给下一个接收者,这可能是另一个中间件或消费者。
目的地
目的地代表消息系统中发送和消耗消息的实体。
目的地通常在其所属的消息系统实例中由其名称唯一标识。目的地名称的示例可以是 URL 或简单的单字标识符。
目的地的典型示例包括 Kafka 主题、RabbitMQ 队列和主题。
消息消费
消息的消费可以分多个步骤进行。首先,在消费者端接收消息的较低级别,然后是消息的逻辑处理。通常,等待消息并不特别有趣,而是隐藏在框架中,该框架只在收到消息时调用某个处理程序函数(类似于监听 TCP 端口以获取传入 HTTP 消息并不特别有趣)。
消费者组
消费者组为消息消费者提供逻辑分组。消息系统使用它们来对组内的消息消费进行负载均衡,将消息广播到不同类型的消费者,独立管理每个组的偏移量。结果是,不同消费者组可以以不同的速度或使用不同的设置接收消息。
订阅
订阅代表消息系统中的实体,这些实体允许多个消费者从主题接收消息,遵循特定于订阅的消费行为,包括负载均衡、持久性、过滤或其他系统特定功能。
命名订阅和消费者组是消息系统用于类似场景(如负载均衡或广播)的语义上不同的机制。
会话
在某些消息系统中,一条消息可以接收一条或多条回复消息,以回答之前发送的某条特定消息。所有通过此类回复关系分组在一起的消息都称为一个会话。分组通常通过某种“In-Reply-To:”元信息或显式的会话 ID(有时称为相关 ID)进行。有时一个会话可以跨越多个消息目的地(例如,通过主题启动,在临时的一对一队列上继续)。
临时和匿名目的地
某些消息系统支持临时目的地(通常只是临时队列)的概念,这些目的地仅为特定一组通信伙伴(通常是一对一)或会话而建立。通常,此类目的地也是未命名的(匿名的)或具有自动生成的名称。
约定
鉴于这些定义,本节的其余部分描述了描述与消息系统交互的 Span 的语义约定。
上下文传播
当消息从生产者传播到消费者时,它可能会在一个或多个中间件的许多不同组件和层之间传递。为了能够使用现有的上下文传播机制将消费者跟踪与生产者跟踪关联起来,所有组件都必须将上下文向下传播。
消息系统本身可能会在消息从生产者传递到消费者时对其进行跟踪。此类跟踪将涵盖传输层,但无助于将生产者与消费者关联起来。为了能够直接将生产者与消费者关联起来,需要与消息一起传播另一个上下文。
消息创建上下文允许将生产者与消息的消费者关联起来,并对它们之间的依赖关系进行建模,而不管底层消息传输机制及其检测如何。
消息创建上下文由生产者创建,应传播给消费者。如果消息创建上下文未附加并随消息传播,则消费者跟踪无法直接与生产者跟踪关联。
生产者应将消息创建上下文附加到每条消息。如果可能,消息创建上下文应以不被中间件更改的方式附加。
本文档不指定将创建上下文附加/提取到/从消息的确切机制。这些约定的未来版本将在这些标准达到稳定状态后,遵循行业标准(包括但不限于 Trace Context: AMQP protocol 和 Trace Context: MQTT protocol)给出明确的建议。
Span 名称
消息 Span 应遵循 Span 名称的总体 指南。
Span 名称应为 {messaging.operation.name} {destination}(有关 {destination} 占位符的确切定义,请参阅下文)。
特定消息系统的语义约定可以指定不同的 Span 名称格式,然后必须在其特定消息技术的语义约定中进行记录。
{destination}占位符应描述操作所针对的实体,并应遵循以下值之一,前提是它们是可访问的
- 如果可用,应使用
messaging.destination.template。 - 当已知目的地既不是 临时也不是匿名时,应使用
messaging.destination.name。 - 仅用于不针对任何特定目的地的操作。
如果特定操作没有(低基数)相应的 {destination} 值,则检测代码应省略 {destination}。
示例
publish shop.orderssend shop.orderssubscribe shop.ordersack shop.ordersnack print_jobsprocess topic with spacessettle AuthenticationRequest-Conversations
操作类型
为这些语义约定定义了以下与消息相关的操作类型:
| 操作类型 | 描述 |
|---|---|
create | 消息被创建或传递给客户端库进行发送。“创建” Span 始终指单个消息,并用于为批量发送场景中的消息提供唯一的创建上下文。 |
send | 提供一个或多个消息以发送到中介。如果发送了单条消息,“Send”跨度的上下文可用作创建上下文,无需创建“Create”跨度。 |
receive | 一个或多个消息由消费者请求。此操作指拉取式场景,其中消费者显式调用消息 SDK 的方法来接收消息。 |
process | 一个或多个消息由消费者处理。 |
settle | 一个或多个消息已结算。 |
Span 类型
Span 类型应根据下表设置,基于 Span 所描述的操作类型。
| 操作类型 | Span 类型 |
|---|---|
create | PRODUCER |
send | PRODUCER(如果“发送” Span 的上下文用作创建上下文),否则为 CLIENT。 |
receive | CLIENT |
process | CONSUMER |
settle | CLIENT |
根据此表设置 Span 类型,使分析工具无需其他语义提示即可解释 Span 及其之间的关系。
Span 状态
有关如何记录 Span 状态的详细信息,请参阅 Recording Errors 文档。
Trace 结构
生产者 Span
当消息被创建或传递给负责发送的客户端库或其他组件时,“创建” Span 可能会被创建。单个“创建” Span 应只处理单条消息。“发送” Span 应为将消息发送或发布到中间件的操作而创建。单个“发送” Span 可以处理单条消息,或多条消息(在批量发送消息的情况下)。
如果用户在消息中提供了自定义创建上下文,则不应修改此上下文,并且不应创建“创建” Span。否则,如果存在消息的“创建” Span,则其上下文应注入到消息中。如果不存在“创建” Span 并且消息中未注入自定义创建上下文,则应将相关“发送” Span 的上下文注入到消息中。
“发送” Span 应始终链接到注入到消息中的创建上下文,无论是来自“创建” Span 还是自定义创建上下文。
在检测总是发送单条消息的库 API 时,建议在没有“创建” Span 的情况下创建“发送” Span。
在检测通常处理批量的库 API 时,建议为每条消息创建“创建” Span,并同时创建“发送” Span。还建议提供一个配置选项以允许禁用“创建” Span 的创建。
消费者 Span
当应用程序代码启动消息传递操作时(拉取场景),应为“接收”操作创建“接收” Span。
当消息传递操作不是由应用程序代码启动时(推送场景),应为“处理”操作创建“处理” Span。此类“处理” Span 涵盖此类操作的持续时间,这通常是一个回调或处理程序。
在拉取场景中,为了处理消息的操作,可以创建“处理” Span,以补充“接收” Span。此类 Span 可以由应用程序代码或构建在消息 SDK 之上的抽象层创建。
在消息被消息库或 SDK 预取或缓存直到转发给调用者之前,不得为这些消息创建“接收”或“处理” Span。
单个“处理”或“接收” Span 可以处理单条消息、一批消息,或者不处理任何消息(如果已发出信号表明未收到消息)。对于其处理的每条消息,“处理”或“接收” Span 应链接到消息的创建上下文。
这些约定使用 Span 链接作为关联生产者和消费者的默认机制,因为
鉴于可用的消息系统模型多种多样,这是唯一可以保证的一致的 Trace 结构。
在批量场景中关联生产者和消费者是唯一的选择,因为一个 Span 只能有一个父级。
在消息消费可能发生在另一个环境上下文(例如 HTTP 服务器 Span)的范围内时,关联生产者和消费者是唯一的选择。
对于每手动或自动触发的确认操作,应创建“确认” Span。单个“确认” Span 可以处理单条消息或多条消息(如果消息作为批次传递以进行确认)。对于其处理的每条消息,“确认” Span 可以链接到消息的创建上下文。
作为“处理” Span 父级的消息创建上下文
仅适用于单消息场景,“处理” Span 可以使用消息的创建上下文作为其父级,从而实现生产者和消费者之间的直接父子关系。检测代码应记录它们是否将消息创建上下文用作“处理” Span 的父级,并可以提供配置选项以允许用户控制此行为。
当处理发生在另一个 Span 的范围内时,不建议(默认情况下)将消息创建上下文用作“处理” Span 的父级。
如果检测代码将消息创建上下文用作另一个有效环境上下文范围内的“处理” Span 的父级,则应将环境上下文添加为“处理” Span 上的链接,以保留消息处理与该上下文之间的关联。
例如,消息代理通过 HTTP 将消息推送到具有 HTTP 服务器和消息传递检测功能的消费者应用程序。
消息检测将按照以下可能的方法之一创建“处理” Span:
“处理” Span 是 HTTP 服务器 Span 上下文的子级,并链接到消息创建上下文。这是默认行为。
“处理” Span 是消息创建上下文的子级,并具有两个链接:一个链接到消息创建上下文,另一个链接到 HTTP 服务器 Span 上下文。这是可选行为。
消息传递属性
消息传递属性按以下命名空间组织:
messaging.message:包含描述单个消息的属性。messaging.destination:包含描述消息发送到的逻辑实体的属性。有关更多详细信息,请参阅 目的地。messaging.batch:包含描述批量操作的属性。messaging.consumer:包含描述消耗消息的应用程序实例的属性。有关更多详细信息,请参阅 消费者。
特定于消息系统的属性必须在相应的 messaging.{system} 命名空间中定义。
Attributes
| 键 | Stability | 需求级别 | Value Type | 描述 | Example Values |
|---|---|---|---|---|---|
messaging.operation.name | 必需 | 字符串 | 消息操作的系统特定名称。 | ack; nack; send | |
messaging.system | 必需 | 字符串 | 由客户端检测识别的消息系统。[1] | activemq; aws.sns; aws_sqs | |
error.type | 条件必需 仅当消息操作失败时。 | 字符串 | 描述操作结束时发生的错误类型。[2] | amqp:decode-error; KAFKA_STORAGE_ERROR; channel-error | |
messaging.batch.message_count | 有条件地必需 [3] | int | 在批处理操作范围内发送、接收或处理的消息数量。[4] | 0; 1; 2 | |
messaging.consumer.group.name | 条件必需 如果适用。 | 字符串 | 消费者所属的消费者组的名称。[5] | my-group; indexer | |
messaging.destination.anonymous | 有条件地必需 [6] | 布尔值 | 一个布尔值,如果消息目的地是匿名的(可能是未命名的或具有自动生成的名称),则为 true。 | ||
messaging.destination.name | 有条件地必需 [7] | 字符串 | 消息目的地名称 [8] | MyQueue; MyTopic | |
messaging.destination.subscription.name | 条件必需 如果适用。 | 字符串 | 从中消耗消息的目的地订阅的名称。[9] | subscription-a | |
messaging.destination.template | 有条件地必需 [10] | 字符串 | 消息目的地名称的低基数表示形式 [11] | /customers/{customerId} | |
messaging.destination.temporary | 有条件地必需 [12] | 布尔值 | 一个布尔值,如果消息目的地是临时的,并且在消息处理后可能不再存在,则为 true。 | ||
messaging.operation.type | 条件必需 如果适用。 | 字符串 | 标识消息操作类型的字符串。[13] | create; send; receive | |
server.address | 有条件必需 如果可用。 | 字符串 | 如果可用,则为服务器域名,无需反向 DNS 查找;否则,为 IP 地址或 Unix 套接字名称。[14] | example.com;10.1.2.80;/tmp/my.sock | |
messaging.client.id | 推荐 | 字符串 | 标识消耗或生成消息的客户端的唯一标识符。 | client-5; myhost@8742@s8083jm | |
messaging.destination.partition.id | 推荐 适用时。 | 字符串 | 发送或接收消息的分区的标识符,在 messaging.destination.name 中是唯一的。 | 1 | |
messaging.message.conversation_id | 推荐 | 字符串 | 标识消息所属会话的会话 ID,表示为字符串。有时称为“相关 ID”。 | MyConversationId | |
messaging.message.id | 推荐 如果 span 描述的是单条消息的操作。 | 字符串 | 消息传递系统用作消息标识符的值,表示为字符串。 | 452a7c7c7c7048c2f887f61572b18fc2 | |
network.peer.address | 推荐 如果此消息系统适用。 | 字符串 | 执行操作的消息中间件节点的服务地址。[15] | 10.1.2.80;/tmp/my.sock | |
network.peer.port | 推荐,当且仅当设置了 network.peer.address 时。 | int | 执行操作的消息中间件节点的服务端口。 | 65123 | |
server.port | 推荐 | int | 服务器端口号。[16] | 80; 8080; 443 | |
messaging.message.body.size | 选择加入 | int | 消息体的大小(以字节为单位)。[17] | 1439 | |
messaging.message.envelope.size | 选择加入 | int | 消息体和元数据的大小(以字节为单位)。[18] | 2738 |
[1] messaging.system: 实际的消息系统可能与客户端已知的不同。例如,在使用 Kafka 客户端库与 Azure Event Hubs 通信时,messaging.system 根据检测代码的最佳知识设置为 kafka。
[2] error.type: error.type 应可预测且具有低基数。
当 error.type 设置为某个类型(例如,异常类型)时,应该使用该工件内识别类型的规范类名。
Instrumentations 应该记录它们报告的错误列表。
一个仪器库内的 error.type 基数性应该低。从多个仪器库和应用程序聚合数据的遥测消费者,在没有额外过滤时,应准备好 error.type 在查询时具有高基数性。
如果操作已成功完成,Instrumentations 不应设置 error.type。
如果特定域定义了自己的一组错误标识符(例如 HTTP 或 gRPC 状态码),则建议
- 使用特定于域的属性
- 设置
error.type以捕获所有错误,无论它们是否包含在特定于域的集合中。
[3] messaging.batch.message_count:如果 span 描述的是对消息批次的操作。
[4] messaging.batch.message_count:Instrumentation 不应在对单个消息进行操作的 span 上设置 messaging.batch.message_count。当消息客户端库支持同一操作的批处理和单消息 API 时,Instrumentation 应为批处理 API 使用 messaging.batch.message_count,而为单消息 API 不应使用它。
[5] messaging.consumer.group.name: 特定消息系统的语义约定应记录 messaging.consumer.group.name 是否适用及其在该系统中的含义。
[6] messaging.destination.anonymous: 如果值为 true。如果缺失,则假定值为 false。
[7] messaging.destination.name: 如果 Span 描述的是单条消息的操作,或者该值适用于批次中的所有消息。
[8] messaging.destination.name: 目的地名称应唯一标识代理中的特定队列、主题或其他实体。如果代理没有此类概念,则目的地名称应唯一标识代理。
[9] messaging.destination.subscription.name: 特定消息系统的语义约定应记录 messaging.destination.subscription.name 是否适用及其在该系统中的含义。
[10] messaging.destination.template: 如果可用。除非保证目的地名称的低基数,否则检测代码不得使用 messaging.destination.name 作为模板。
[11] messaging.destination.template: 目的地名称可以由模板构成。例如,一个包含用户名或产品 ID 的目的地名称。尽管在这种情况下目的地名称是高基数的,但底层模板是低基数的,可以有效地用于分组和聚合。
[12] messaging.destination.temporary: 如果值为 true。如果缺失,则假定值为 false。
[13] messaging.operation.type: 如果使用自定义值,则必须是低基数的。
[14] server.address: 如果可用,则为代理的服务器域名,无需反向 DNS 查找;否则,为 IP 地址或 Unix 套接字名称。
[15] network.peer.address: 特定消息系统的语义约定应记录 network.peer.* 属性是否适用。当应用程序直接与单个中间件节点交互时,网络对等地址和端口很重要。如果消息操作涉及多个网络调用(例如重试),则应使用最后一次联系的节点地址。
[16] server.port: 从客户端观察到,并且当通过中间件通信时,server.port 应代表任何中间件(例如代理)后面的服务器端口,如果可用。
[17] messaging.message.body.size: 这可以指压缩或未压缩的消息体大小。如果两者都已知,则应使用未压缩的消息体大小。
[18] messaging.message.envelope.size: 这可以指压缩或未压缩的大小。如果两者都已知,则应使用未压缩的大小。
以下属性对于做出采样决策可能很重要,并且应在跨度创建时提供(如果提供的话)
messaging.consumer.group.namemessaging.destination.namemessaging.destination.partition.idmessaging.destination.subscription.namemessaging.destination.templatemessaging.operation.namemessaging.operation.typemessaging.systemserver.addressserver.port
error.type 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
_OTHER | 当检测不到自定义值时使用的回退错误值。 |
messaging.operation.type 具有以下一系列已知值。如果适用其中一个,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
create | 创建消息。“Create”跨度始终指单条消息,用于为批量发送场景中的消息提供唯一的创建上下文。 | |
process | 一个或多个消息由消费者处理。 | |
receive | 一个或多个消息由消费者请求。此操作指拉取式场景,其中消费者显式调用消息 SDK 的方法来接收消息。 | |
send | 提供一个或多个消息以发送到中介。如果发送了单条消息,“Send”跨度的上下文可用作创建上下文,无需创建“Create”跨度。 | |
settle | 一个或多个消息已结算。 |
messaging.system 具有以下一系列已知值。如果适用其中一个,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
activemq | Apache ActiveMQ | |
aws.sns | Amazon Simple Notification Service (SNS) | |
aws_sqs | Amazon Simple Queue Service (SQS) | |
eventgrid | Azure Event Grid | |
eventhubs | Azure Event Hubs | |
gcp_pubsub | Google Cloud Pub/Sub | |
jms | Java Message Service | |
kafka | Apache Kafka | |
pulsar | Apache Pulsar | |
rabbitmq | RabbitMQ | |
rocketmq | Apache RocketMQ | |
servicebus | Azure Service Bus |
在批量操作上记录每条消息的属性
所有消息操作(send、receive、process 或本规范未涵盖的其他操作)都可以描述单条消息和/或一批消息。messaging.message 或 messaging.{system}.message 命名空间中的属性适用于单个消息,并且通常在同一批次内的消息之间有所不同。
某些消息系统(如 Kafka 或 Azure Event Grid)允许在单个操作中将一批消息发送到不同的主题,从而在单个消息操作中产生不同的 messaging.destination.name 或其他目的地属性。
如果属性值对批次中的所有消息都相同,则检测代码应将该属性设置在描述批量操作的 Span 上。如果属性值不同,则检测代码应将这些属性设置在描述单个消息的链接上。
有关使用链接进行关联的更多信息,请参阅 批量接收。
示例
本节包含一个示例列表,说明了上述约定的使用方法。绿色框表示为了符合这些约定而必需存在的 Span。其他框表示不是必需的、但被约定涵盖的 Span,但有望帮助理解消息 Span 如何集成到整体 Trace 流中。实线箭头表示父子关系,虚线箭头表示链接关系。
“Span”框内的文本仅用于参考和可视化目的。请查看附带的表格以了解要报告的实际 Span 名称以及其他属性。
具有多个消费者的主题
以下是一个发布者,它将一条消息发布到 RabbitMQ 的主题交换“T”,以及两个都接收到该消息的消费者。
flowchart LR; subgraph PRODUCER direction TB P[Span Send A] end subgraph CONSUMER1 direction TB R1[Span Process A 1] end subgraph CONSUMER2 direction TB R2[Span Process A 2] end P-. link .-R1; P-- parent -->R1; P-. link .-R2; P-- parent -->R2; classDef normal fill:green class P,R1,R2 normal linkStyle 0,1,2,3 color:green,stroke:green
| 字段或属性 | Producer | 消费者 1 | 消费者 2 |
|---|---|---|---|
| Span 名称 | publish T | consume T | consume T |
| 父级(可选) | publish T | publish T | |
| 链接 | publish T | publish T | |
| SpanKind | PRODUCER | CONSUMER | CONSUMER |
server.address | "ms" | "ms" | "ms" |
server.port | 1234 | 1234 | 1234 |
messaging.system | "rabbitmq" | "rabbitmq" | "rabbitmq" |
messaging.destination.name | "T" | "T" | "T" |
messaging.operation.name | "publish" | "consume" | "consume" |
messaging.operation.type | "send" | "process" | "process" |
messaging.message.id | "a" | "a" | "a" |
批量接收
以下是一个生产者,它将两条消息发布到 Kafka 的主题“Q”,以及一个消费者,它一次接收这两条消息。
flowchart LR; subgraph PRODUCER direction TB PA[Span Send A] PB[Span Send B] end subgraph CONSUMER direction TB D1[Span Receive A B] end PA-. link .-D1; PB-. link .-D1; classDef normal fill:green class PA,PB,D1 normal linkStyle 0,1 color:green,stroke:green
| 字段或属性 | 生产者 Span A | 生产者 Span B | 消费者 |
|---|---|---|---|
| Span 名称 | send Q | send Q | poll Q |
| Parent | |||
| 链接 | Span Send A, Span Send B | ||
| 链接属性 | Span Send A: messaging.message.id: "a1" | ||
Span Send B: messaging.message.id: "a2" | |||
| SpanKind | PRODUCER | PRODUCER | CLIENT |
server.address | "ms" | "ms" | "ms" |
server.port | 1234 | 1234 | 1234 |
messaging.system | "kafka" | "kafka" | "kafka" |
messaging.destination.name | "Q" | "Q" | "Q" |
messaging.operation.name | "send" | "send" | "poll" |
messaging.operation.type | "send" | "send" | "receive" |
messaging.message.id | "a1" | "a2" | |
messaging.batch.message_count | 2 |
批量发布带有“创建” Span
以下是一个生产者,它将包含两条消息的批次发布到 Kafka 的主题“Q”,以及两个不同的消费者,它们分别接收其中一条消息。
在这种情况下,检测代码为每条消息报告“创建” Span,并报告一个链接到“创建” Span 的“发送” Span。
flowchart LR; subgraph PRODUCER direction TB CA[Span Create A] CB[Span Create B] P[Span Send] end subgraph CONSUMER1 direction TB D1[Span Receive A] end subgraph CONSUMER2 direction TB D2[Span Receive B] end CA-. link .-P; CB-. link .-P; CA-. link .-D1; CB-. link .-D2; classDef normal fill:green class P,CA,CB,D1,D2 normal linkStyle 0,1,2,3 color:green,stroke:green
| 字段或属性 | 生产者 Span Create A | 生产者 Span Create B | 生产者 Span Send | 消费者 1 | 消费者 2 |
|---|---|---|---|---|---|
| Span 名称 | create Q | create Q | send Q | poll Q | poll Q |
| Parent | |||||
| 链接 | Span Create A | Span Create B | |||
| SpanKind | PRODUCER | PRODUCER | CLIENT | CLIENT | CLIENT |
server.address | "ms" | "ms" | "ms" | "ms" | "ms" |
server.port | 1234 | 1234 | 1234 | 1234 | 1234 |
messaging.system | "kafka" | "kafka" | "kafka" | "kafka" | "kafka" |
messaging.destination.name | "Q" | "Q" | "Q" | "Q" | "Q" |
messaging.operation.name | "create" | "create" | "send" | "poll" | "poll" |
messaging.operation.type | "create" | "create" | "send" | "receive" | "receive" |
messaging.message.id | "a1" | "a2" | "a1" | "a2" | |
messaging.batch.message_count | 2 |
批量发布不带“创建” Span
以下是一个生产者,它将包含两条消息的批次发布到 Kafka 的主题“Q”,以及两个不同的消费者,它们分别接收其中一条消息。
根据用户提供的配置,检测代码在这种情况下只报告“发送” Span。它将“发送” Span 的上下文注入到两条消息中。
flowchart LR; subgraph PRODUCER direction TB P[Span Send] end subgraph CONSUMER1 direction TB D1[Span Receive A] end subgraph CONSUMER2 direction TB D2[Span Receive B] end P-. link .-D1; P-. link .-D2; classDef normal fill:green class P,D1,D2 normal linkStyle 0,1 color:green,stroke:green
| 字段或属性 | Producer | 消费者 1 | 消费者 2 |
|---|---|---|---|
| Span 名称 | send Q | poll Q | poll Q |
| Parent | |||
| 链接 | Span Send | Span Send | |
| SpanKind | PRODUCER | CLIENT | CLIENT |
server.address | "ms" | "ms" | "ms" |
server.port | 1234 | 1234 | 1234 |
messaging.system | "kafka" | "kafka" | "kafka" |
messaging.destination.name | "Q" | "Q" | "Q" |
messaging.operation.name | "send" | "poll" | "poll" |
messaging.operation.type | "send" | "receive" | "receive" |
messaging.message.id | "a1" | "a2" | |
messaging.batch.message_count | 2 |