RPC Span 的语义约定
状态: 开发中
本文档定义了如何使用 Span 来描述远程过程调用(也称为“远程方法调用” / “RMI”)。
警告:现有使用 v1.37.0 或更早版本 本文档的 RPC 仪器化
- 不应在现有主版本中更改其默认发出的 RPC 约定版本。约定包括(但不限于)属性、指标和 Span 名称以及度量单位。
- 应在其现有主版本中引入一个环境变量
OTEL_SEMCONV_STABILITY_OPT_IN,该变量是以逗号分隔的类别特定值列表(例如,http、databases、rpc)。值列表包括
rpc- 发出稳定的 RPC 约定,并停止发出仪器化先前发出的实验性 RPC 约定。rpc/dup- 同时发出实验性和稳定的 RPC 约定,从而允许对稳定语义约定进行分阶段推出。- 默认行为(在没有这些值的情况下)是继续发出仪器化先前发出的旧实验性 RPC 约定的任何版本。
- 注意:如果同时存在
rpc和rpc/dup这两个值,rpc/dup的优先级高于rpc。- SHOULD 在开始发出这两套约定后,至少维护其现有主版本(至少包括安全补丁)六个月。
- 可以在其下一个主版本中删除环境变量,并且仅发出稳定的 RPC 约定。
通用远程过程调用约定
Span 名称
Span 名称 必须是完整的 RPC 方法名称,格式如下:
$package.$service/$method
(其中 $service 不得包含点, $method 不得包含斜杠)
如果没有包名或未知包名,则省略 $package. 部分(包括句点)。
Span 名称示例
grpc.test.EchoService/Echocom.example.ExampleRmiService/exampleMethodMyCalcService.Calculator/Add由服务器报告,MyServiceReference.ICalculator/Add由客户端报告(适用于 .NET WCF 调用)MyServiceWithNoPackage/theMethod
服务名称
在接收和处理远程过程调用的服务器进程上,rpc.service 中提供的服务名称不必与 service.name 资源属性匹配。一个进程可以公开多个 RPC 端点,因此具有多个 RPC 服务名称。从部署的角度来看,如 service.* 资源属性所表达的,它将被视为一个已部署的、具有一个 service.name 的服务。同样,在向服务器发送 RPC 请求的客户端上,rpc.service 中提供的服务名称不必与 peer.service Span 属性匹配。
例如,给定一个部署为 QuoteService 的进程,这将是 service.name 资源属性(适用于整个进程)的名称。该进程可以公开两个 RPC 端点:一个名为 CurrencyQuotes(= rpc.service)的方法 getMeanRate(= rpc.method),另一个名为 StockQuotes(= rpc.service)的方法 getCurrentBid 和 getLastClose(= rpc.method)。在此示例中,表示客户端请求的 Span 应将其 peer.service 属性设置为 QuoteService,以匹配服务器的 service.name 资源属性。通常,用户不应将 peer.service 设置为完全限定的 RPC 服务名称。
RPC 客户端 Span
状态:
此 Span 代表一个出站的远程过程调用 (RPC)。
Span 名称:请参考 Span 名称 部分。
Span 类型必须为 CLIENT。
**Span 状态**应遵循 记录错误文档。
Attributes
| 键 | Stability | 需求级别 | Value Type | 描述 | Example Values |
|---|---|---|---|---|---|
rpc.system | 必需 | 字符串 | 标识远程系统的字符串。有关知名标识符列表,请参阅下文。 | grpc; java_rmi; dotnet_wcf | |
server.address | 必需 | 字符串 | RPC 服务器 主机名。[1] | example.com;10.1.2.80;/tmp/my.sock | |
error.type | 有条件必需 仅在操作失败时。 | 字符串 | 描述操作结束时发生的错误类型。[2] | timeout;java.net.UnknownHostException;server_certificate_invalid;500 | |
server.port | 有条件地必需 [3] | int | 服务器端口号。[4] | 80; 8080; 443 | |
network.peer.address | 推荐 | 字符串 | 网络连接的对端地址 - IP 地址或 Unix 域套接字名称。 | 10.1.2.80;/tmp/my.sock | |
network.peer.port | 如果设置了 network.peer.address,则推荐。 | int | 网络连接的对等端口号。 | 65123 | |
network.protocol.name | 推荐 | 字符串 | OSI 应用层或非 OSI 等效层。[5] | http | |
network.protocol.version | 推荐 | 字符串 | 用于网络通信的协议的实际版本。[6] | 1.1; 2 | |
network.transport | 推荐 | 字符串 | OSI 传输层或进程间通信方法。[7] | tcp;udp | |
rpc.method | 推荐 | 字符串 | 这是从 RPC 接口角度看的方法的逻辑名称。[8] | exampleMethod | |
rpc.service | 推荐 | 字符串 | 被调用的服务的完整(逻辑)名称,包括其包名(如果适用)。[9] | myservice.EchoService |
[1] server.address: 可能包含服务器 IP 地址、DNS 名称或本地套接字名称。当主机组件是 IP 地址时,仪器化不应进行反向 DNS 查找以获取 DNS 名称,而应将 server.address 设置为主机组件中提供的 IP 地址。
[2] error.type: error.type 应可预测且具有低基数。
当 error.type 设置为某个类型(例如,异常类型)时,应该使用该工件内识别类型的规范类名。
Instrumentations 应该记录它们报告的错误列表。
一个仪器库内的 error.type 基数性应该低。从多个仪器库和应用程序聚合数据的遥测消费者,在没有额外过滤时,应准备好 error.type 在查询时具有高基数性。
如果操作已成功完成,Instrumentations 不应设置 error.type。
如果特定域定义了自己的一组错误标识符(例如 HTTP 或 gRPC 状态码),则建议
- 使用特定于域的属性
- 设置
error.type以捕获所有错误,无论它们是否包含在特定于域的集合中。
[3] server.port: 如果端口被用于通信的网络传输所支持。
[4] server.port: 从客户端观察时,并且在通过中介进行通信时,server.port 应代表任何中介(例如代理)之后的服务器端口,如果可用。
[5] network.protocol.name: 该值应规范化为小写。
[6] network.protocol.version: 如果协议版本需要协商(例如使用 ALPN),则此属性应设置为协商后的版本。如果实际协议版本未知,则不应设置此属性。
[7] network.transport: 该值应规范化为小写。
在设置端口号时,应始终考虑设置传输协议,因为没有传输协议的端口号是模糊的。例如,不同的进程可能正在监听 TCP 端口 12345 和 UDP 端口 12345。
[8] rpc.method: 这是从 RPC 接口角度看的方法的逻辑名称,可能与任何实现方法/函数的名称不同。code.function.name 属性可用于存储后者(例如,在服务器端实际执行调用的方法,客户端上的 RPC 客户端存根方法)。
[9] rpc.service: 这是从 RPC 接口角度看的服务的逻辑名称,可能与任何实现类的名称不同。code.namespace 属性可用于存储后者(尽管属性名称如此,它也可能包含类名;例如,在服务器端实际执行调用的方法的类,客户端上的 RPC 客户端存根类)。
error.type 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
_OTHER | 当检测不到自定义值时使用的回退错误值。 |
network.transport 具有以下已知值列表。如果其中一个适用,则必须使用相应的_值_;否则,可以_使用_自定义值。
| 值 | 描述 | Stability |
|---|---|---|
pipe | 命名或匿名管道。 | |
quic | QUIC | |
tcp | TCP | |
udp | UDP | |
unix | Unix 域套接字 |
rpc.system 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以改用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
apache_dubbo | Apache Dubbo | |
connect_rpc | Connect RPC | |
dotnet_wcf | .NET WCF | |
grpc | gRPC | |
java_rmi | Java RMI | |
jsonrpc | JSON-RPC | |
onc_rpc | ONC RPC (Sun RPC) |
RPC 服务器 Span
状态:
此 Span 代表一个入站的远程过程调用 (RPC)。
Span 名称:请参考 Span 名称 部分。
Span 类型必须为 SERVER。
**Span 状态**应遵循 记录错误文档。
Attributes
| 键 | Stability | 需求级别 | Value Type | 描述 | Example Values |
|---|---|---|---|---|---|
rpc.system | 必需 | 字符串 | 标识远程系统的字符串。有关知名标识符列表,请参阅下文。 | grpc; java_rmi; dotnet_wcf | |
server.address | 必需 | 字符串 | RPC 服务器 主机名。[1] | example.com;10.1.2.80;/tmp/my.sock | |
error.type | 有条件必需 仅在操作失败时。 | 字符串 | 描述操作结束时发生的错误类型。[2] | timeout;java.net.UnknownHostException;server_certificate_invalid;500 | |
server.port | 有条件地必需 [3] | int | 服务器端口号。[4] | 80; 8080; 443 | |
client.address | 推荐 | 字符串 | 客户端地址 - 如果可用且无需反向 DNS 查找,则为域名;否则,为 IP 地址或 Unix 域套接字名称。[5] | client.example.com; 10.1.2.80; /tmp/my.sock | |
client.port | 推荐 | int | 客户端端口号。[6] | 65123 | |
network.peer.address | 推荐 | 字符串 | 网络连接的对端地址 - IP 地址或 Unix 域套接字名称。 | 10.1.2.80;/tmp/my.sock | |
network.peer.port | 如果设置了 network.peer.address,则推荐。 | int | 网络连接的对等端口号。 | 65123 | |
network.protocol.name | 推荐 | 字符串 | OSI 应用层或非 OSI 等效层。[7] | http | |
network.protocol.version | 推荐 | 字符串 | 网络通信实际使用的协议版本。[8] | 1.1; 2 | |
network.transport | 推荐 | 字符串 | OSI 传输层或进程间通信方法。[9] | tcp;udp | |
rpc.method | 推荐 | 字符串 | 这是从 RPC 接口角度看的方法的逻辑名称。[10] | exampleMethod | |
rpc.service | 推荐 | 字符串 | 正在调用的服务的完整(逻辑)名称,包括其包名称(如果适用)。[11] | myservice.EchoService |
[1] server.address: 可能包含服务器 IP 地址、DNS 名称或本地套接字名称。当主机组件是 IP 地址时,仪器化不应进行反向 DNS 查找以获取 DNS 名称,而应将 server.address 设置为主机组件中提供的 IP 地址。
[2] error.type: error.type 应可预测且具有低基数。
当 error.type 设置为某个类型(例如,异常类型)时,应该使用该工件内识别类型的规范类名。
Instrumentations 应该记录它们报告的错误列表。
一个仪器库内的 error.type 基数性应该低。从多个仪器库和应用程序聚合数据的遥测消费者,在没有额外过滤时,应准备好 error.type 在查询时具有高基数性。
如果操作已成功完成,Instrumentations 不应设置 error.type。
如果特定域定义了自己的一组错误标识符(例如 HTTP 或 gRPC 状态码),则建议
- 使用特定于域的属性
- 设置
error.type以捕获所有错误,无论它们是否包含在特定于域的集合中。
[3] server.port: 如果端口被用于通信的网络传输所支持。
[4] server.port: 从客户端观察时,并且在通过中介进行通信时,server.port 应代表任何中介(例如代理)之后的服务器端口,如果可用。
[5] client.address: 从服务器端观察时,并且当通过中间设备通信时,client.address 应代表任何中间设备(例如代理)后的客户端地址(如果可用)。
[6] client.port: 从服务器端观察时,并且当通过中间设备通信时,client.port 应代表任何中间设备(例如代理)后的客户端端口(如果可用)。
[7] network.protocol.name: 该值应规范化为小写。
[8] network.protocol.version: 如果协议版本需要协商(例如,使用 ALPN),则此属性应设置为协商后的版本。如果实际协议版本未知,则不应设置此属性。
[9] network.transport: 该值应规范化为小写。
在设置端口号时,应始终考虑设置传输协议,因为没有传输协议的端口号是模糊的。例如,不同的进程可能正在监听 TCP 端口 12345 和 UDP 端口 12345。
[10] rpc.method: 这是从 RPC 接口角度看的方法的逻辑名称,它可能与任何实现的方法/函数名称不同。code.function.name 属性可用于存储后者(例如,实际在服务器端执行调用的方法,RPC 客户端存根方法)。
[11] rpc.service: 这是从 RPC 接口角度看的服务的逻辑名称,它可能与任何实现类的名称不同。code.namespace 属性可用于存储后者(尽管属性名称如此,但它可能包含类名;例如,在服务器端实际执行调用的方法所属的类,RPC 客户端存根类)。
error.type 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
_OTHER | 当检测不到自定义值时使用的回退错误值。 |
network.transport 具有以下已知值列表。如果其中一个适用,则必须使用相应的_值_;否则,可以_使用_自定义值。
| 值 | 描述 | Stability |
|---|---|---|
pipe | 命名或匿名管道。 | |
quic | QUIC | |
tcp | TCP | |
udp | UDP | |
unix | Unix 域套接字 |
rpc.system 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以改用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
apache_dubbo | Apache Dubbo | |
connect_rpc | Connect RPC | |
dotnet_wcf | .NET WCF | |
grpc | gRPC | |
java_rmi | Java RMI | |
jsonrpc | JSON-RPC | |
onc_rpc | ONC RPC (Sun RPC) |
事件
消息事件
状态:
事件名称必须是 rpc.message。
描述在 RPC 调用上下文中发送或接收的消息。
在 RPC 流的生命周期中,应为客户端和服务器 Span 上发送/接收的每条消息创建事件。对于一元调用,仅为客户端和服务器 Span 记录一条发送消息和一条接收消息。
Attributes
| 键 | Stability | 需求级别 | Value Type | 描述 | Example Values |
|---|---|---|---|---|---|
rpc.message.compressed_size | 推荐 | int | 消息的压缩大小(字节)。 | ||
rpc.message.id | 推荐 | int | 必须计算为两个不同的计数器,一个用于发送的消息,一个用于接收的消息,都从 1 开始。[1] | ||
rpc.message.type | 推荐 | 字符串 | 这是接收到的消息还是发送的消息。 | SENT;RECEIVED | |
rpc.message.uncompressed_size | 推荐 | int | 消息的未压缩大小(字节)。 |
[1] rpc.message.id: 这样可以确保不同实现的值是一致的。
rpc.message.type 有以下一系列预定义值。如果其中一个适用,则必须使用相应的选项;否则,可以改用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
RECEIVED | received | |
SENT | sent |
与 HTTP Span 的区别
HTTP 调用通常仅使用 HTTP Span 即可表示。如果它们针对的是调用者已知的特定远程服务和方法,即当它是通过 HTTP 传输的远程过程调用时,可以在该 Span 上额外添加 rpc.* 属性,或者在作为承载 HTTP 调用的父 Span 的单独 RPC Span 中添加。请注意,此处的“方法”指的是被调用的远程过程,而不是 HTTP 动词(GET、POST 等)。
特定 RPC 技术的语义约定
为以下 RPC 技术定义了更具体的语义约定: