HTTP Span 的语义约定

状态: 稳定,除非另有说明。

本文档定义了 HTTP 客户端和服务器 Span 的语义约定。它们可用于 http 和 https 协议以及各种 HTTP 版本,如 1.1、2 和 SPDY。

警告 使用 此文档 v1.20.0(或更早版本)的现有 HTTP 仪器化

  • 在 HTTP 语义约定被标记为稳定之前,**不应**更改其默认发出的 HTTP 或网络约定版本(HTTP 稳定化将包括一组核心网络约定(也用于 HTTP 仪表化)的稳定化)。约定包括但不限于属性、指标和跨度名称以及度量单位。
  • 在现有主版本中,应引入一个名为 OTEL_SEMCONV_STABILITY_OPT_IN 的环境变量,该变量是一个逗号分隔的类别特定值列表(例如,http、databases、messaging)。值列表包括:
    • http - 发出新的、稳定的 HTTP 和网络约定,并停止发出仪表化先前发出的旧的实验性 HTTP 和网络约定。
    • http/dup - 同时发出旧的和稳定的 HTTP 和网络约定,实现无缝过渡。
    • 默认行为(如果没有指定这些值之一)是继续发出仪表化先前发出的旧的实验性 HTTP 和网络约定版本。
    • 注意:如果同时存在这两个值,http/dup 的优先级高于 http
  • 在开始发出两组约定后,应至少维护现有主版本(至少进行安全修补)六个月。
  • 应在下一个主版本中删除该环境变量。

名称

HTTP Span 必须遵循 Span 名称的总体 准则

如果存在(低基数)target,HTTP Span 名称应为 {method} {target}。如果不存在(低基数){target},HTTP Span 名称应为 {method}

(有关 {method}{target} 占位符的确切定义,请参见下文)。

如果 {method} 代表仪器化已知的原始方法,则 {method} 必须是 {http.request.method}。在其他情况下(当 {http.request.method} 设置为 _OTHER 时),{method} 必须是 HTTP

{target} 应为以下之一

  • HTTP 服务器 Span 的 http.route
  • Development)如果已启用且可用,则 HTTP 客户端 Span 的 url.template
  • 其他值可以通过自定义钩子在 Span 开始时或之后提供。

仪器化不得默认为使用 URI 路径作为 {target}

状态

如果 HTTP 状态码在 1xx、2xx 或 3xx 范围内,Span 状态必须保持未设置,除非发生其他错误(例如,接收响应体时的网络错误;或超过最大重定向次数的 3xx 代码),在这种情况下,状态必须设置为 Error

注意

HTTP 状态码是否表示错误取决于上下文。例如,404“未找到”状态码表示错误,如果应用程序期望该资源可用。但是,当应用程序只是检查资源是否存在时,它就不是错误。

具有特定请求额外上下文的仪器化可以使用此上下文更精确地设置 Span 状态。没有额外上下文的仪器化必须遵循本节的指南。

对于 4xx 范围内的 HTTP 状态码,在 SpanKind.SERVER 的情况下,Span 状态必须保持未设置;在 SpanKind.CLIENT 的情况下,应将其设置为 Error

对于 5xx 范围内的 HTTP 状态码,以及客户端未能解释的任何其他代码,Span 状态应设置为 Error

如果原因可以从 http.response.status_code 推断出来,则不要设置 Span 状态描述。

HTTP 请求可能失败,如果它被取消或发生错误,阻止客户端或服务器完全发送/接收请求/响应。

当仪器化检测到此类错误时,它应将 Span 状态设置为 Error,并应设置 error.type 属性。

状态开发中 - 有关记录 Span 状态的一般注意事项,请参阅 Recording Errors 文档。

HTTP 客户端 Span

状态: 稳定

此 Span 代表一次出站 HTTP 请求。

HTTP 客户端 Span 有两种实现方式:

  1. 仪器化应为每次尝试通过网络发送 HTTP 请求创建一个 HTTP Span。如果请求被重发,重发尝试必须遵循 HTTP 重发规范。在这种情况下,仪器化不应(也)发出逻辑上包含的 HTTP 客户端 Span。

  2. 如果由于某种原因无法为每次发送尝试发出 Span(例如,因为仪器化的库不公开允许此操作的钩子),仪器化可以为 HTTP 客户端的顶层操作创建一个 HTTP Span。在这种情况下,url.full 必须是原始请求的绝对 URL,并在执行请求时可能发生的任何 HTTP 重定向之前。

Span 名称:请参阅 Span 名称 部分。

Span 类型必须为 CLIENT

Span 状态:请参阅 Span 状态 部分。

Attributes

Stability需求级别Value Type描述Example Values
http.request.methodStable必需字符串HTTP 请求方法。[1]GET; POST; HEAD
server.addressStable必需字符串服务器域名(如果无需反向 DNS 查询即可获得);否则,为 IP 地址或 Unix 套接字名称。[2]example.com10.1.2.80/tmp/my.sock
server.portStable必需int服务器端口号。[3]80; 8080; 443
url.fullStable必需字符串根据 RFC3986 [4] 描述网络资源的绝对 URLhttps://www.foo.bar/search?q=OpenTelemetry#SemConv; //
error.typeStable有条件要求 如果请求以错误结束。字符串描述操作结束时的一类错误。[5]timeoutjava.net.UnknownHostExceptionserver_certificate_invalid500
http.request.method_originalStable有条件地必需 [6]字符串客户端在请求行中发送的原始 HTTP 方法。GeT; ACL; foo
http.response.status_codeStable有条件要求 如果且仅当收到/发送了该方法。intHTTP 响应状态码.200
network.protocol.nameStable有条件地必需 [7]字符串OSI 应用层或非 OSI 等效层。 [8]http; spdy
http.request.resend_countStable推荐 如果且仅当请求被重试。int请求重发尝试的序号(无论何种原因,包括重定向)。[9]3
network.peer.addressStable推荐字符串网络连接的对端地址 - IP 地址或 Unix 域套接字名称。10.1.2.80/tmp/my.sock
network.peer.portStable如果设置了 network.peer.address,则推荐int网络连接的对等端口号。65123
network.protocol.versionStable推荐字符串用于网络通信的实际协议版本。[10]1.0; 1.1; 2; 3
http.request.body.sizeDevelopment选择加入int请求 payload body 的大小(以字节为单位)。这是传输的字节数,不包括标头,并且通常(但不总是)以 Content-Length 标头形式出现。对于使用传输编码的请求,这应该是压缩后的尺寸。3495
http.request.header.<key>Stable选择加入string[]HTTP 请求标头,<key> 是标准化的 HTTP 标头名称(小写),值是标头值。[11]["application/json"]; ["1.2.3.4", "1.2.3.5"]
http.request.sizeDevelopment选择加入int请求的总大小(以字节为单位)。这应该是通过网络传输的总字节数,包括请求行(HTTP/1.1)、帧(HTTP/2 和 HTTP/3)、标头以及任何请求体。1437
http.response.body.sizeDevelopment选择加入int响应 payload body 的大小(以字节为单位)。这是传输的字节数,不包括标头,并且通常(但不总是)以 Content-Length 标头形式出现。对于使用传输编码的请求,这应该是压缩后的尺寸。3495
http.response.header.<key>Stable选择加入string[]HTTP 响应标头,<key> 是标准化的 HTTP 标头名称(小写),值是标头值。[12]["application/json"]; ["abc", "def"]
http.response.sizeDevelopment选择加入int响应的总大小(以字节为单位)。这应该是通过网络传输的总字节数,包括状态行(HTTP/1.1)、帧(HTTP/2 和 HTTP/3)、标头以及任何响应体和尾部。1437
network.transportStable选择加入字符串OSI 传输层或 进程间通信方法。[13]tcpudp
url.schemeStable选择加入字符串The URI 方案组件,用于标识所使用的协议。http; https
url.templateDevelopment选择加入字符串根据 RFC3986 的低基数绝对路径引用模板。[14]/users/{id}; /users/:id; /users?id={id}
user_agent.originalStable选择加入字符串客户端发送的 HTTP User-Agent 标头的值。CERN-LineMode/2.15 libwww/2.17b3; Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1; YourApp/1.0.0 grpc-java-okhttp/1.27.2
user_agent.synthetic.typeDevelopment选择加入字符串指定合成流量的类别,例如测试或机器人。[15]bot; test

[1] http.request.method HTTP 请求方法值应被仪器化“已知”。默认情况下,此约定将“已知”方法定义为 RFC9110 中列出的方法、RFC5789 中定义的 PATCH 方法以及 httpbis-safe-method-w-body 中定义的 QUERY 方法。

如果 HTTP 请求方法仪器不了解,则必须将 http.request.method 属性设置为 _OTHER

如果 HTTP 仪器最终可能将有效的 HTTP 请求方法转换为 _OTHER,则必须提供一种方法来覆盖已知 HTTP 方法的列表。如果此覆盖是通过环境变量完成的,则环境变量必须命名为 OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS,并支持一个逗号分隔的、区分大小写的已知 HTTP 方法列表(此列表必须完全覆盖默认已知方法,而不是默认方法之外的已知方法列表)。

HTTP 方法名称区分大小写,http.request.method 属性值必须精确匹配一个已知的 HTTP 方法名称。对于将 HTTP 方法视为不区分大小写的特定 Web 框架的仪器,应填充一个规范等效值。进行此操作的跟踪仪器还必须将 http.request.method_original 设置为原始值。

[2] server.address 在 HTTP/1.1 中,当 请求目标 以其 绝对形式 传递时,server.address 应匹配请求目标的 host 组件。

在所有其他情况下,server.address 应匹配 HTTP/1.1 中的 Host 标头或 HTTP/2 和 HTTP/3 中的 :authority 伪标头的 host 组件。

[3] server.port 在 HTTP/1.1 中,当 请求目标 以其 绝对形式 传递时,server.port 应匹配请求目标的 port 组件。

在所有其他情况下,server.port 应匹配 HTTP/1.1 中的 Host 标头或 HTTP/2 和 HTTP/3 中的 :authority 伪标头的 port 组件。

[4] url.full 对于网络调用,URL 通常具有 scheme://host[:port][path][?query][#fragment] 格式,其中 fragment 不会通过 HTTP 传输,但如果已知,仍应包含在内。

url.full 不能包含通过 URL 形式传递的凭证,例如 https://username:password@www.example.com/。在这种情况下,用户名和密码应被redacted,属性值应为 https://REDACTED:REDACTED@www.example.com/

url.full 应该捕获可用(或可以重建)的绝对 URL。

url.full 中提供的敏感内容应在仪表化工具能够识别时进行清除。

Development 查询字符串中以下键的值应默认redacted,并替换为 REDACTED 值。

此列表可能会随时间而更改。

当查询字符串值被redacted时,查询字符串键仍应保留,例如 https://www.example.com/path?color=blue&sig=REDACTED

[5] error.type 如果请求在发送或接收响应状态码之前因错误而失败,error.type 应设置为异常类型(如果适用,则为其完全限定类名)或特定于组件的低基数错误标识符。

如果已发送或接收响应状态码,且状态根据 HTTP Span 状态定义 表示错误,则 error.type 应设置为状态码数字(表示为字符串)、异常类型(如果抛出)或特定于组件的错误标识符。

error.type 值应是可预测的,并且应具有低基数。仪器化应记录其报告的错误列表。

一个仪器化库中的 error.type 的基数应较低,但聚合来自多个仪器化库和应用程序的数据的遥测消费者应准备好在查询时(当没有应用额外过滤器时)error.type 具有高基数。

如果请求已成功完成,仪器化不应设置 error.type

[6] http.request.method_original 如果且仅当它与 http.request.method 不同。

[7] network.protocol.name 如果不是 httpnetwork.protocol.version 已设置。

[8] network.protocol.name 该值应规范化为小写。

[9] http.request.resend_count 每次客户端重发 HTTP 请求时,都应添加 http.request.resend_count 属性并设置为请求重发尝试的序号(例如,重定向、授权失败、503 服务器不可用、网络问题或其他任何原因)。

[10] network.protocol.version 如果协议版本需要协商(例如使用 ALPN),则此属性应设置为协商后的版本。如果实际协议版本未知,则不应设置此属性。

[11] http.request.header.<key> 仪器化应要求显式配置要捕获的标头。包含所有请求标头可能存在安全风险 - 显式配置有助于避免泄露敏感信息。

User-Agent 标头已在 user_agent.original 属性中捕获。用户可以显式配置仪器化来捕获它们,即使不推荐。

属性值必须包含多个标头值作为字符串数组,或者一个包含可能已逗号连接的字符串的单项数组,具体取决于 HTTP 库提供标头访问的方式。

示例

  • 标头 Content-Type: application/json 应以 http.request.header.content-type 属性的形式记录,值为 ["application/json"]
  • 标头 X-Forwarded-For: 1.2.3.4, 1.2.3.5 应以 http.request.header.x-forwarded-for 属性的形式记录,值为 ["1.2.3.4", "1.2.3.5"]["1.2.3.4, 1.2.3.5"],具体取决于 HTTP 库。

[12] http.response.header.<key> 仪器化应要求显式配置要捕获的标头。包含所有响应标头可能存在安全风险 - 显式配置有助于避免泄露敏感信息。

用户可以显式配置仪器化来捕获它们,即使不推荐。

属性值必须包含多个标头值作为字符串数组,或者一个包含可能已逗号连接的字符串的单项数组,具体取决于 HTTP 库提供标头访问的方式。

示例

  • 标头 Content-Type: application/json 应以 http.request.response.content-type 属性的形式记录,值为 ["application/json"]
  • 标头 My-custom-header: abc, def 应以 http.response.header.my-custom-header 属性的形式记录,值为 ["abc", "def"]["abc, def"],具体取决于 HTTP 库。

[13] network.transport 通常对于 HTTP/1.0HTTP/1.1HTTP/2tcp。对于 HTTP/3 通常是 udp。也可能存在其他不常见的实现。

[14] url.template url.template 必须具有低基数。它通常在 HTTP 客户端上不可用,但应用程序或专用 HTTP 仪器化可能知道它。

[15] user_agent.synthetic.type 此属性可从 user_agent.original 属性的内容派生。填充此属性的组件负责确定它们认为的合成机器人或测试流量。此属性可用于自我识别目的,或用于识别由合成请求生成的遥测数据。此属性有助于区分真正的客户端流量和由机器人或测试生成的合成流量。

以下属性对于做出采样决策可能很重要,并且应在跨度创建时提供(如果提供的话)


error.type 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。

描述Stability
_OTHER当检测不到自定义值时使用的回退错误值。Stable

http.request.method 具有以下一组知名值。如果适用其中一个,则必须使用相应的名称;否则,可以使用自定义名称。

描述Stability
_OTHER仪器不了解的任何 HTTP 方法。Stable
CONNECTCONNECT 方法。Stable
DELETEDELETE 方法。Stable
GETGET 方法。Stable
HEADHEAD 方法。Stable
OPTIONSOPTIONS 方法。Stable
PATCHPATCH 方法。Stable
POSTPOST 方法。Stable
PUTPUT 方法。Stable
QUERYQUERY 方法。Development
TRACETRACE 方法。Stable

network.transport 具有以下已知值列表。如果其中一个适用,则必须使用相应的_值_;否则,可以_使用_自定义值。

描述Stability
pipe命名或匿名管道。Stable
quicQUICStable
tcpTCPStable
udpUDPStable
unixUnix 域套接字Stable

user_agent.synthetic.type具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。

描述Stability
bot机器人来源。Development
test合成测试来源。Development

HTTP 客户端 Span 持续时间

有一些基本的约束应该被遵守

  • HTTP 客户端 Span 应在发送第一个请求字节之前开始。这可能包括也可能不包括连接时间。
  • HTTP 客户端 Span 应在完全读取 HTTP 响应标头(或读取失败)之后结束。这可能包括也可能不包括读取响应体。

如果应用程序代码有可能未完全读取 HTTP 响应(而 HTTP 客户端库随后必须异步清理 HTTP 响应),则 HTTP 客户端 Span 不应在此清理阶段结束,而应在完全读取(或读取失败)HTTP 响应标头后某个时间点结束。这可以避免 Span 在稍后异步结束,而该时间点已不再与发出 HTTP 请求的应用程序代码直接相关。

由于此问题可能引起的混淆,HTTP 客户端库仪器化应记录其在结束 HTTP 客户端 Span 时的行为。

HTTP 请求重试和重定向

重试和重定向导致发送多个物理 HTTP 请求。当 HTTP 客户端库发送多个 HTTP 请求来满足同一个 API 调用时,请求就会被重发。这可能由于遵循重定向、授权挑战、503 服务器不可用、网络问题或其他任何原因而发生。

每次重发 HTTP 请求时,http.request.resend_count 属性都应添加到每个重复的 Span 中,并设置为请求重发尝试的序号。

参阅示例了解更多关于

HTTP 服务器

阅读下一节,了解建议如何为 HTTP 服务器仪器化捕获服务器信息。

HTTP 服务器定义

HTTP 请求可以通过反向代理等中间件路由到特定的 HTTP 应用程序。发送到同一域名的 HTTP 请求可能会由多个应用程序处理,具体取决于端口、路径、标头或其他参数。

例如,同一 Web 应用程序的不同版本可以作为独立的应用程序并排运行在反向代理后面,反向代理根据请求路径将请求路由到一个或另一个。

不同 HTTP 服务器应用程序的实例可能运行在同一台物理主机上并共享同一个 IP 地址,但监听不同的 TCP/UDP 端口。为了将请求路由到特定应用程序,反向代理通常会修改 HTTP Host 标头,用实际代理的服务器名称替换客户端提供的原始值。这种行为取决于反向代理的配置。在某些情况下,路由请求到特定应用程序时不会使用 Host 标头,这使其容易包含无效内容。

HTTP 服务器框架及其仪器化对请求经过的 HTTP 基础设施和中间件的了解有限。在一般情况下,它们只能使用 HTTP 请求属性(如请求目标或标头)来填充 server.* 属性。

设置 server.addressserver.port 属性

在 HTTP 服务器的上下文中,server.addressserver.port 属性捕获原始主机名和端口。它们旨在尽可能与客户端和服务器端相同。

HTTP 服务器仪器化应尽最大努力填充 server.addressserver.port 属性,并应使用以下第一个适用的规则来确定它们:

注意Host:authority 标头包含服务器的主机和端口号。这同样适用于 Forwarded 标头的 host 标识符或 X-Forwarded-Host 标头。仪器化应通过解析相应标头的值来填充 server.addressserver.port 属性。

应用程序开发人员可以使用 SpanProcessor 来覆盖可能不准确的 server.* 属性值,并可以使用适用的 资源属性 来捕获私有主机信息。

简单的客户端/服务器示例

simple-http-server.png

带反向代理的客户端/服务器示例

reverse-proxy-http-server.png

HTTP 服务器 Span

状态: 稳定

此 Span 代表一次入站 HTTP 请求。

Span 名称:请参阅 Span 名称 部分。

Span 类型必须为 SERVER

Span 状态:请参阅 Span 状态 部分。

Attributes

Stability需求级别Value Type描述Example Values
http.request.methodStable必需字符串HTTP 请求方法。[1]GET; POST; HEAD
url.pathStable必需字符串根据 RFC3986 的 URI 路径组件 [2]/search
url.schemeStable必需字符串识别所用协议的 RFC3986 URI 方案组件。[3]http; https
error.typeStable有条件要求 如果请求以错误结束。字符串描述操作结束时的一类错误。[4]timeoutjava.net.UnknownHostExceptionserver_certificate_invalid500
http.request.method_originalStable有条件地必需 [5]字符串客户端在请求行中发送的原始 HTTP 方法。GeT; ACL; foo
http.response.status_codeStable有条件要求 如果且仅当收到/发送了该方法。intHTTP 响应状态码.200
http.routeStable有条件要求 如果且仅当可用。字符串请求匹配的路由模板。此模板必须是低基数的,并且必须包含所有静态路径段,动态路径段用占位符表示。[6]/users/:userID?; my-controller/my-action/{id?}
network.protocol.nameStable有条件地必需 [7]字符串OSI 应用层或非 OSI 等效层。 [8]http; spdy
server.portStable如果可用且 server.address 已设置,则有条件要求int接收请求的本地 HTTP 服务器的端口。[9]80; 8080; 443
url.queryStable有条件要求 如果且仅当收到/发送了该方法。字符串根据 RFC3986 的 URI 查询组件 [10]q=OpenTelemetry
client.addressStable推荐字符串客户端地址 - 如果不进行反向 DNS 查找即可获得域名;否则,为 IP 地址或 Unix 套接字名称。[11]83.164.160.102
network.peer.addressStable推荐字符串网络连接的对端地址 - IP 地址或 Unix 域套接字名称。10.1.2.80/tmp/my.sock
network.peer.portStable如果设置了 network.peer.address,则推荐int网络连接的对等端口号。65123
network.protocol.versionStable推荐字符串用于网络通信的实际协议版本。[12]1.0; 1.1; 2; 3
server.addressStable推荐字符串接收请求的本地 HTTP 服务器的名称。[13]example.com10.1.2.80/tmp/my.sock
user_agent.originalStable推荐字符串客户端发送的 HTTP User-Agent 标头的值。CERN-LineMode/2.15 libwww/2.17b3; Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1; YourApp/1.0.0 grpc-java-okhttp/1.27.2
client.portStable选择加入intclient.address 中捕获的客户端的端口。[14]65123
http.request.body.sizeDevelopment选择加入int请求 payload body 的大小(以字节为单位)。这是传输的字节数,不包括标头,并且通常(但不总是)以 Content-Length 标头形式出现。对于使用传输编码的请求,这应该是压缩后的尺寸。3495
http.request.header.<key>Stable选择加入string[]HTTP 请求标头,<key> 是标准化的 HTTP 标头名称(小写),值是标头值。[15]["application/json"]; ["1.2.3.4", "1.2.3.5"]
http.request.sizeDevelopment选择加入int请求的总大小(以字节为单位)。这应该是通过网络传输的总字节数,包括请求行(HTTP/1.1)、帧(HTTP/2 和 HTTP/3)、标头以及任何请求体。1437
http.response.body.sizeDevelopment选择加入int响应 payload body 的大小(以字节为单位)。这是传输的字节数,不包括标头,并且通常(但不总是)以 Content-Length 标头形式出现。对于使用传输编码的请求,这应该是压缩后的尺寸。3495
http.response.header.<key>Stable选择加入string[]HTTP 响应标头,<key> 是标准化的 HTTP 标头名称(小写),值是标头值。[16]["application/json"]; ["abc", "def"]
http.response.sizeDevelopment选择加入int响应的总大小(以字节为单位)。这应该是通过网络传输的总字节数,包括状态行(HTTP/1.1)、帧(HTTP/2 和 HTTP/3)、标头以及任何响应体和尾部。1437
network.local.addressStable选择加入字符串本地套接字地址。对于多 IP 主机很有用。10.1.2.80/tmp/my.sock
network.local.portStable选择加入int本地套接字端口。对于多端口主机很有用。65123
network.transportStable选择加入字符串OSI 传输层或 进程间通信方法。[17]tcpudp
user_agent.synthetic.typeDevelopment选择加入字符串指定合成流量的类别,例如测试或机器人。[18]bot; test

[1] http.request.method HTTP 请求方法值应被仪器化“已知”。默认情况下,此约定将“已知”方法定义为 RFC9110 中列出的方法、RFC5789 中定义的 PATCH 方法以及 httpbis-safe-method-w-body 中定义的 QUERY 方法。

如果 HTTP 请求方法仪器不了解,则必须将 http.request.method 属性设置为 _OTHER

如果 HTTP 仪器最终可能将有效的 HTTP 请求方法转换为 _OTHER,则必须提供一种方法来覆盖已知 HTTP 方法的列表。如果此覆盖是通过环境变量完成的,则环境变量必须命名为 OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS,并支持一个逗号分隔的、区分大小写的已知 HTTP 方法列表(此列表必须完全覆盖默认已知方法,而不是默认方法之外的已知方法列表)。

HTTP 方法名称区分大小写,http.request.method 属性值必须精确匹配一个已知的 HTTP 方法名称。对于将 HTTP 方法视为不区分大小写的特定 Web 框架的仪器,应填充一个规范等效值。进行此操作的跟踪仪器还必须将 http.request.method_original 设置为原始值。

[2] url.path 应在仪器化能够识别时,擦除 url.path 中提供的敏感内容。

[3] url.scheme 原始客户端请求的方案,如果已知(例如,来自 Forwarded#protoX-Forwarded-Proto 或类似标头)。否则,为直接对等请求的方案。

[4] error.type 如果请求在发送或接收响应状态码之前因错误而失败,error.type 应设置为异常类型(如果适用,则为其完全限定类名)或特定于组件的低基数错误标识符。

如果已发送或接收响应状态码,且状态根据 HTTP Span 状态定义 表示错误,则 error.type 应设置为状态码数字(表示为字符串)、异常类型(如果抛出)或特定于组件的错误标识符。

error.type 值应是可预测的,并且应具有低基数。仪器化应记录其报告的错误列表。

一个仪器化库中的 error.type 的基数应较低,但聚合来自多个仪器化库和应用程序的数据的遥测消费者应准备好在查询时(当没有应用额外过滤器时)error.type 具有高基数。

如果请求已成功完成,仪器化不应设置 error.type

[5] http.request.method_original 如果且仅当它与 http.request.method 不同。

[6] http.route 如果 HTTP 服务器框架不支持此项,则不得填充此项,因为路由属性应具有低基数,而 URI 路径不能替代它。应包含(如果存在)应用程序根目录

静态路径段是路由模板中具有固定、低基数值的ส่วน。这包括字面字符串,如 /users/,以及受限于有限、预定义值集合的占位符,例如 {controller}{action}

动态路径段是占位符,用于存储具有高基数且不受预定义列表约束的值,就像静态路径段一样。

仪器应使用相应 Web 框架提供的路由信息。它们应选择最精确的路由信息来源,并可以支持自定义路由格式。仪器应记录使用的格式和获取路由字符串的 API。

[7] network.protocol.name 如果不是 httpnetwork.protocol.version 已设置。

[8] network.protocol.name 该值应规范化为小写。

[9] server.port 请参阅 设置 server.addressserver.port 属性

[10] url.query 应在仪器化能够识别时,擦除 url.query 中提供的敏感内容。

Development 查询字符串中以下键的值应默认redacted,并替换为 REDACTED 值。

此列表可能会随时间而更改。

当查询字符串值被隐藏时,仍应保留查询字符串键,例如 q=OpenTelemetry&sig=REDACTED

[11] client.address 原始客户端在所有代理后面的 IP 地址,如果已知(例如,来自 Forwarded#forX-Forwarded-For 或类似标头)。否则,为直接客户端对等地址。

[12] network.protocol.version 如果协议版本需要协商(例如使用 ALPN),则此属性应设置为协商后的版本。如果实际协议版本未知,则不应设置此属性。

[13] server.address 请参阅 设置 server.addressserver.port 属性

[14] client.port 从服务器端观察时,并且在通过中介进行通信时,client.port 应代表任何中介(例如代理)后面的客户端端口,如果可用。

[15] http.request.header.<key> 仪器化应要求显式配置要捕获的标头。包含所有请求标头可能存在安全风险 - 显式配置有助于避免泄露敏感信息。

User-Agent 标头已在 user_agent.original 属性中捕获。用户可以显式配置仪器化来捕获它们,即使不推荐。

属性值必须包含多个标头值作为字符串数组,或者一个包含可能已逗号连接的字符串的单项数组,具体取决于 HTTP 库提供标头访问的方式。

示例

  • 标头 Content-Type: application/json 应以 http.request.header.content-type 属性的形式记录,值为 ["application/json"]
  • 标头 X-Forwarded-For: 1.2.3.4, 1.2.3.5 应以 http.request.header.x-forwarded-for 属性的形式记录,值为 ["1.2.3.4", "1.2.3.5"]["1.2.3.4, 1.2.3.5"],具体取决于 HTTP 库。

[16] http.response.header.<key> 仪器化应要求显式配置要捕获的标头。包含所有响应标头可能存在安全风险 - 显式配置有助于避免泄露敏感信息。

用户可以显式配置仪器化来捕获它们,即使不推荐。

属性值必须包含多个标头值作为字符串数组,或者一个包含可能已逗号连接的字符串的单项数组,具体取决于 HTTP 库提供标头访问的方式。

示例

  • 标头 Content-Type: application/json 应以 http.request.response.content-type 属性的形式记录,值为 ["application/json"]
  • 标头 My-custom-header: abc, def 应以 http.response.header.my-custom-header 属性的形式记录,值为 ["abc", "def"]["abc, def"],具体取决于 HTTP 库。

[17] network.transport 通常对于 HTTP/1.0HTTP/1.1HTTP/2tcp。对于 HTTP/3 通常是 udp。也可能存在其他不常见的实现。

[18] user_agent.synthetic.type 此属性可从 user_agent.original 属性的内容派生。填充此属性的组件负责确定它们认为的合成机器人或测试流量。此属性可用于自我识别目的,或用于识别由合成请求生成的遥测数据。此属性有助于区分真正的客户端流量和由机器人或测试生成的合成流量。

以下属性对于做出采样决策可能很重要,并且应在跨度创建时提供(如果提供的话)


error.type 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。

描述Stability
_OTHER当检测不到自定义值时使用的回退错误值。Stable

http.request.method 具有以下一组知名值。如果适用其中一个,则必须使用相应的名称;否则,可以使用自定义名称。

描述Stability
_OTHER仪器不了解的任何 HTTP 方法。Stable
CONNECTCONNECT 方法。Stable
DELETEDELETE 方法。Stable
GETGET 方法。Stable
HEADHEAD 方法。Stable
OPTIONSOPTIONS 方法。Stable
PATCHPATCH 方法。Stable
POSTPOST 方法。Stable
PUTPUT 方法。Stable
QUERYQUERY 方法。Development
TRACETRACE 方法。Stable

network.transport 具有以下已知值列表。如果其中一个适用,则必须使用相应的_值_;否则,可以_使用_自定义值。

描述Stability
pipe命名或匿名管道。Stable
quicQUICStable
tcpTCPStable
udpUDPStable
unixUnix 域套接字Stable

user_agent.synthetic.type具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。

描述Stability
bot机器人来源。Development
test合成测试来源。Development

http.route 必须在创建 span 时提供,但仅限于其已经可用的情况。如果 span 启动后才变得可用,则必须在 span 结束前随时填充它。

示例

HTTP 客户端-服务器示例

例如,如果从 IP 地址为 192.0.2.4 的主机调用浏览器请求 https://example.com:8080/webshop/articles/4?s=1&t=2,则客户端可能具有以下 Span:

Span 名称:GET

属性名称
http.request.method"GET"
network.protocol.version"1.1"
url.full"https://example.com:8080/webshop/articles/4?s=1&t=2"
server.addressexample.com
server.port8080
network.peer.address"192.0.2.5"
network.peer.port8080
http.response.status_code200

相应的服务器 Span 可能如下所示:

Span 名称:GET /webshop/articles/:article_id

属性名称
http.request.method"GET"
network.protocol.version"1.1"
url.path"/webshop/articles/4"
url.query"s=1&t=2"
server.address"example.com"
server.port8080
url.scheme"https"
http.route"/webshop/articles/:article_id"
http.response.status_code200
client.address"192.0.2.4"
network.peer.address"192.0.2.5"(客户端通过代理)
user_agent.original"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0"

HTTP 客户端重试示例

已有入站请求启动的跟踪时的重试示例

request (SERVER, trace=t1, span=s1)
  |
  -- GET / - 500 (CLIENT, trace=t1, span=s2)
  |   |
  |   --- server (SERVER, trace=t1, span=s3)
  |
  -- GET / - 500 (CLIENT, trace=t1, span=s4, http.request.resend_count=1)
  |   |
  |   --- server (SERVER, trace=t1, span=s5)
  |
  -- GET / - 200 (CLIENT, trace=t1, span=s6, http.request.resend_count=2)
      |
      --- server (SERVER, trace=t1, span=s7)

事先未启动跟踪时的重试示例

GET / - 500 (CLIENT, trace=t1, span=s1)
 |
 --- server (SERVER, trace=t1, span=s2)

GET / - 500 (CLIENT, trace=t2, span=s1, http.request.resend_count=1)
 |
 --- server (SERVER, trace=t2, span=s2)

GET / - 200 (CLIENT, trace=t3, span=s1, http.request.resend_count=2)
 |
 --- server (SERVER, trace=t3, span=s1)

HTTP 客户端授权重试示例

已有入站请求启动的跟踪时的重试示例

request (SERVER, trace=t1, span=s1)
  |
  -- GET /hello - 401 (CLIENT, trace=t1, span=s2)
  |   |
  |   --- server (SERVER, trace=t1, span=s3)
  |
  -- GET /hello - 200 (CLIENT, trace=t1, span=s4, http.request.resend_count=1)
      |
      --- server (SERVER, trace=t1, span=s5)

事先未启动跟踪时的重试示例

GET /hello - 401 (CLIENT, trace=t1, span=s1)
 |
 --- server (SERVER, trace=t1, span=s2)

GET /hello - 200 (CLIENT, trace=t2, span=s1, http.request.resend_count=1)
 |
 --- server (SERVER, trace=t2, span=s2)

HTTP 客户端重定向示例

已有入站请求启动的跟踪时的重定向示例

request (SERVER, trace=t1, span=s1)
  |
  -- GET / - 302 (CLIENT, trace=t1, span=s2)
  |   |
  |   --- server (SERVER, trace=t1, span=s3)
  |
  -- GET /hello - 200 (CLIENT, trace=t1, span=s4, http.request.resend_count=1)
      |
      --- server (SERVER, trace=t1, span=s5)

事先未启动跟踪时的重定向示例

GET / - 302 (CLIENT, trace=t1, span=s1)
 |
 --- server (SERVER, trace=t1, span=s2)

GET /hello - 200 (CLIENT, trace=t2, span=s1, http.request.resend_count=1)
 |
 --- server (SERVER, trace=t2, span=s2)

HTTP 客户端调用:DNS 错误

例如,如果用户请求 https://does-not-exist-123.com,则客户端可能具有以下 Span:

属性名称
http.request.method"GET"
network.protocol.version"1.1"
url.full"https://does-not-exist-123.com"
server.address"does-not-exist-123.com"
error.type"java.net.UnknownHostException"

HTTP 客户端调用:内部服务器错误

例如,如果用户请求 https://example.com 并且服务器返回 500,则客户端可能具有以下 Span:

属性名称
http.request.method"GET"
network.protocol.version"1.1"
url.full"https://example.com"
server.address"example.com"
http.response.status_code500
error.type"500"

HTTP 服务器调用:在发送响应正文之前连接已断开

例如,如果用户向 https://example.com:8080/uploads/4 发送了一个带有正文的 POST 请求,我们可能会在服务器端看到以下 Span:

Span 名称:POST /uploads/:document_id

属性名称
http.request.method"POST"
url.path"/uploads/4"
url.scheme"https"
http.route"/uploads/:document_id"
http.response.status_code201
error.typeWebSocketDisconnect