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 - (
)如果已启用且可用,则 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 有两种实现方式:
仪器化应为每次尝试通过网络发送 HTTP 请求创建一个 HTTP Span。如果请求被重发,重发尝试必须遵循 HTTP 重发规范。在这种情况下,仪器化不应(也)发出逻辑上包含的 HTTP 客户端 Span。
如果由于某种原因无法为每次发送尝试发出 Span(例如,因为仪器化的库不公开允许此操作的钩子),仪器化可以为 HTTP 客户端的顶层操作创建一个 HTTP Span。在这种情况下,
url.full必须是原始请求的绝对 URL,并在执行请求时可能发生的任何 HTTP 重定向之前。
Span 名称:请参阅 Span 名称 部分。
Span 类型必须为 CLIENT。
Span 状态:请参阅 Span 状态 部分。
Attributes
| 键 | Stability | 需求级别 | Value Type | 描述 | Example Values |
|---|---|---|---|---|---|
http.request.method | 必需 | 字符串 | HTTP 请求方法。[1] | GET; POST; HEAD | |
server.address | 必需 | 字符串 | 服务器域名(如果无需反向 DNS 查询即可获得);否则,为 IP 地址或 Unix 套接字名称。[2] | example.com;10.1.2.80;/tmp/my.sock | |
server.port | 必需 | int | 服务器端口号。[3] | 80; 8080; 443 | |
url.full | 必需 | 字符串 | 根据 RFC3986 [4] 描述网络资源的绝对 URL | https://www.foo.bar/search?q=OpenTelemetry#SemConv; // | |
error.type | 有条件要求 如果请求以错误结束。 | 字符串 | 描述操作结束时的一类错误。[5] | timeout;java.net.UnknownHostException;server_certificate_invalid;500 | |
http.request.method_original | 有条件地必需 [6] | 字符串 | 客户端在请求行中发送的原始 HTTP 方法。 | GeT; ACL; foo | |
http.response.status_code | 有条件要求 如果且仅当收到/发送了该方法。 | int | HTTP 响应状态码. | 200 | |
network.protocol.name | 有条件地必需 [7] | 字符串 | OSI 应用层或非 OSI 等效层。 [8] | http; spdy | |
http.request.resend_count | 推荐 如果且仅当请求被重试。 | int | 请求重发尝试的序号(无论何种原因,包括重定向)。[9] | 3 | |
network.peer.address | 推荐 | 字符串 | 网络连接的对端地址 - IP 地址或 Unix 域套接字名称。 | 10.1.2.80;/tmp/my.sock | |
network.peer.port | 如果设置了 network.peer.address,则推荐。 | int | 网络连接的对等端口号。 | 65123 | |
network.protocol.version | 推荐 | 字符串 | 用于网络通信的实际协议版本。[10] | 1.0; 1.1; 2; 3 | |
http.request.body.size | 选择加入 | int | 请求 payload body 的大小(以字节为单位)。这是传输的字节数,不包括标头,并且通常(但不总是)以 Content-Length 标头形式出现。对于使用传输编码的请求,这应该是压缩后的尺寸。 | 3495 | |
http.request.header.<key> | 选择加入 | string[] | HTTP 请求标头,<key> 是标准化的 HTTP 标头名称(小写),值是标头值。[11] | ["application/json"]; ["1.2.3.4", "1.2.3.5"] | |
http.request.size | 选择加入 | int | 请求的总大小(以字节为单位)。这应该是通过网络传输的总字节数,包括请求行(HTTP/1.1)、帧(HTTP/2 和 HTTP/3)、标头以及任何请求体。 | 1437 | |
http.response.body.size | 选择加入 | int | 响应 payload body 的大小(以字节为单位)。这是传输的字节数,不包括标头,并且通常(但不总是)以 Content-Length 标头形式出现。对于使用传输编码的请求,这应该是压缩后的尺寸。 | 3495 | |
http.response.header.<key> | 选择加入 | string[] | HTTP 响应标头,<key> 是标准化的 HTTP 标头名称(小写),值是标头值。[12] | ["application/json"]; ["abc", "def"] | |
http.response.size | 选择加入 | int | 响应的总大小(以字节为单位)。这应该是通过网络传输的总字节数,包括状态行(HTTP/1.1)、帧(HTTP/2 和 HTTP/3)、标头以及任何响应体和尾部。 | 1437 | |
network.transport | 选择加入 | 字符串 | OSI 传输层或 进程间通信方法。[13] | tcp;udp | |
url.scheme | 选择加入 | 字符串 | The URI 方案组件,用于标识所使用的协议。 | http; https | |
url.template | 选择加入 | 字符串 | 根据 RFC3986 的低基数绝对路径引用模板。[14] | /users/{id}; /users/:id; /users?id={id} | |
user_agent.original | 选择加入 | 字符串 | 客户端发送的 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.type | 选择加入 | 字符串 | 指定合成流量的类别,例如测试或机器人。[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 中提供的敏感内容应在仪表化工具能够识别时进行清除。
查询字符串中以下键的值应默认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: 如果不是 http 且 network.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.0、HTTP/1.1 和 HTTP/2 是 tcp。对于 HTTP/3 通常是 udp。也可能存在其他不常见的实现。
[14] url.template: url.template 必须具有低基数。它通常在 HTTP 客户端上不可用,但应用程序或专用 HTTP 仪器化可能知道它。
[15] user_agent.synthetic.type: 此属性可从 user_agent.original 属性的内容派生。填充此属性的组件负责确定它们认为的合成机器人或测试流量。此属性可用于自我识别目的,或用于识别由合成请求生成的遥测数据。此属性有助于区分真正的客户端流量和由机器人或测试生成的合成流量。
以下属性对于做出采样决策可能很重要,并且应在跨度创建时提供(如果提供的话)
error.type 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
_OTHER | 当检测不到自定义值时使用的回退错误值。 |
http.request.method 具有以下一组知名值。如果适用其中一个,则必须使用相应的名称;否则,可以使用自定义名称。
| 值 | 描述 | Stability |
|---|---|---|
_OTHER | 仪器不了解的任何 HTTP 方法。 | |
CONNECT | CONNECT 方法。 | |
DELETE | DELETE 方法。 | |
GET | GET 方法。 | |
HEAD | HEAD 方法。 | |
OPTIONS | OPTIONS 方法。 | |
PATCH | PATCH 方法。 | |
POST | POST 方法。 | |
PUT | PUT 方法。 | |
QUERY | QUERY 方法。 | |
TRACE | TRACE 方法。 |
network.transport 具有以下已知值列表。如果其中一个适用,则必须使用相应的_值_;否则,可以_使用_自定义值。
| 值 | 描述 | Stability |
|---|---|---|
pipe | 命名或匿名管道。 | |
quic | QUIC | |
tcp | TCP | |
udp | UDP | |
unix | Unix 域套接字 |
user_agent.synthetic.type具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
bot | 机器人来源。 | |
test | 合成测试来源。 |
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.address 和 server.port 属性
在 HTTP 服务器的上下文中,server.address 和 server.port 属性捕获原始主机名和端口。它们旨在尽可能与客户端和服务器端相同。
HTTP 服务器仪器化应尽最大努力填充 server.address 和 server.port 属性,并应使用以下第一个适用的规则来确定它们:
- 原始主机,可能由反向代理在
Forwarded#host、X-Forwarded-Host或类似标头中传递。 - HTTP/2 或 HTTP/3 的情况下,
:authority伪标头。 Host标头。
注意:
Host和:authority标头包含服务器的主机和端口号。这同样适用于Forwarded标头的host标识符或X-Forwarded-Host标头。仪器化应通过解析相应标头的值来填充server.address和server.port属性。
应用程序开发人员可以使用 SpanProcessor 来覆盖可能不准确的 server.* 属性值,并可以使用适用的 资源属性 来捕获私有主机信息。
简单的客户端/服务器示例

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

HTTP 服务器 Span
状态:
此 Span 代表一次入站 HTTP 请求。
Span 名称:请参阅 Span 名称 部分。
Span 类型必须为 SERVER。
Span 状态:请参阅 Span 状态 部分。
Attributes
| 键 | Stability | 需求级别 | Value Type | 描述 | Example Values |
|---|---|---|---|---|---|
http.request.method | 必需 | 字符串 | HTTP 请求方法。[1] | GET; POST; HEAD | |
url.path | 必需 | 字符串 | 根据 RFC3986 的 URI 路径组件 [2] | /search | |
url.scheme | 必需 | 字符串 | 识别所用协议的 RFC3986 URI 方案组件。[3] | http; https | |
error.type | 有条件要求 如果请求以错误结束。 | 字符串 | 描述操作结束时的一类错误。[4] | timeout;java.net.UnknownHostException;server_certificate_invalid;500 | |
http.request.method_original | 有条件地必需 [5] | 字符串 | 客户端在请求行中发送的原始 HTTP 方法。 | GeT; ACL; foo | |
http.response.status_code | 有条件要求 如果且仅当收到/发送了该方法。 | int | HTTP 响应状态码. | 200 | |
http.route | 有条件要求 如果且仅当可用。 | 字符串 | 请求匹配的路由模板。此模板必须是低基数的,并且必须包含所有静态路径段,动态路径段用占位符表示。[6] | /users/:userID?; my-controller/my-action/{id?} | |
network.protocol.name | 有条件地必需 [7] | 字符串 | OSI 应用层或非 OSI 等效层。 [8] | http; spdy | |
server.port | 如果可用且 server.address 已设置,则有条件要求。 | int | 接收请求的本地 HTTP 服务器的端口。[9] | 80; 8080; 443 | |
url.query | 有条件要求 如果且仅当收到/发送了该方法。 | 字符串 | 根据 RFC3986 的 URI 查询组件 [10] | q=OpenTelemetry | |
client.address | 推荐 | 字符串 | 客户端地址 - 如果不进行反向 DNS 查找即可获得域名;否则,为 IP 地址或 Unix 套接字名称。[11] | 83.164.160.102 | |
network.peer.address | 推荐 | 字符串 | 网络连接的对端地址 - IP 地址或 Unix 域套接字名称。 | 10.1.2.80;/tmp/my.sock | |
network.peer.port | 如果设置了 network.peer.address,则推荐。 | int | 网络连接的对等端口号。 | 65123 | |
network.protocol.version | 推荐 | 字符串 | 用于网络通信的实际协议版本。[12] | 1.0; 1.1; 2; 3 | |
server.address | 推荐 | 字符串 | 接收请求的本地 HTTP 服务器的名称。[13] | example.com;10.1.2.80;/tmp/my.sock | |
user_agent.original | 推荐 | 字符串 | 客户端发送的 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.port | 选择加入 | int | 在 client.address 中捕获的客户端的端口。[14] | 65123 | |
http.request.body.size | 选择加入 | int | 请求 payload body 的大小(以字节为单位)。这是传输的字节数,不包括标头,并且通常(但不总是)以 Content-Length 标头形式出现。对于使用传输编码的请求,这应该是压缩后的尺寸。 | 3495 | |
http.request.header.<key> | 选择加入 | string[] | HTTP 请求标头,<key> 是标准化的 HTTP 标头名称(小写),值是标头值。[15] | ["application/json"]; ["1.2.3.4", "1.2.3.5"] | |
http.request.size | 选择加入 | int | 请求的总大小(以字节为单位)。这应该是通过网络传输的总字节数,包括请求行(HTTP/1.1)、帧(HTTP/2 和 HTTP/3)、标头以及任何请求体。 | 1437 | |
http.response.body.size | 选择加入 | int | 响应 payload body 的大小(以字节为单位)。这是传输的字节数,不包括标头,并且通常(但不总是)以 Content-Length 标头形式出现。对于使用传输编码的请求,这应该是压缩后的尺寸。 | 3495 | |
http.response.header.<key> | 选择加入 | string[] | HTTP 响应标头,<key> 是标准化的 HTTP 标头名称(小写),值是标头值。[16] | ["application/json"]; ["abc", "def"] | |
http.response.size | 选择加入 | int | 响应的总大小(以字节为单位)。这应该是通过网络传输的总字节数,包括状态行(HTTP/1.1)、帧(HTTP/2 和 HTTP/3)、标头以及任何响应体和尾部。 | 1437 | |
network.local.address | 选择加入 | 字符串 | 本地套接字地址。对于多 IP 主机很有用。 | 10.1.2.80;/tmp/my.sock | |
network.local.port | 选择加入 | int | 本地套接字端口。对于多端口主机很有用。 | 65123 | |
network.transport | 选择加入 | 字符串 | OSI 传输层或 进程间通信方法。[17] | tcp;udp | |
user_agent.synthetic.type | 选择加入 | 字符串 | 指定合成流量的类别,例如测试或机器人。[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#proto、X-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: 如果不是 http 且 network.protocol.version 已设置。
[8] network.protocol.name: 该值应规范化为小写。
[9] server.port: 请参阅 设置 server.address 和 server.port 属性。
[10] url.query: 应在仪器化能够识别时,擦除 url.query 中提供的敏感内容。
查询字符串中以下键的值应默认redacted,并替换为
REDACTED 值。
此列表可能会随时间而更改。
当查询字符串值被隐藏时,仍应保留查询字符串键,例如 q=OpenTelemetry&sig=REDACTED。
[11] client.address: 原始客户端在所有代理后面的 IP 地址,如果已知(例如,来自 Forwarded#for、X-Forwarded-For 或类似标头)。否则,为直接客户端对等地址。
[12] network.protocol.version: 如果协议版本需要协商(例如使用 ALPN),则此属性应设置为协商后的版本。如果实际协议版本未知,则不应设置此属性。
[13] server.address: 请参阅 设置 server.address 和 server.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.0、HTTP/1.1 和 HTTP/2 是 tcp。对于 HTTP/3 通常是 udp。也可能存在其他不常见的实现。
[18] user_agent.synthetic.type: 此属性可从 user_agent.original 属性的内容派生。填充此属性的组件负责确定它们认为的合成机器人或测试流量。此属性可用于自我识别目的,或用于识别由合成请求生成的遥测数据。此属性有助于区分真正的客户端流量和由机器人或测试生成的合成流量。
以下属性对于做出采样决策可能很重要,并且应在跨度创建时提供(如果提供的话)
client.addresshttp.request.header.<key>http.request.methodserver.addressserver.porturl.pathurl.queryurl.schemeuser_agent.original
error.type 具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
_OTHER | 当检测不到自定义值时使用的回退错误值。 |
http.request.method 具有以下一组知名值。如果适用其中一个,则必须使用相应的名称;否则,可以使用自定义名称。
| 值 | 描述 | Stability |
|---|---|---|
_OTHER | 仪器不了解的任何 HTTP 方法。 | |
CONNECT | CONNECT 方法。 | |
DELETE | DELETE 方法。 | |
GET | GET 方法。 | |
HEAD | HEAD 方法。 | |
OPTIONS | OPTIONS 方法。 | |
PATCH | PATCH 方法。 | |
POST | POST 方法。 | |
PUT | PUT 方法。 | |
QUERY | QUERY 方法。 | |
TRACE | TRACE 方法。 |
network.transport 具有以下已知值列表。如果其中一个适用,则必须使用相应的_值_;否则,可以_使用_自定义值。
| 值 | 描述 | Stability |
|---|---|---|
pipe | 命名或匿名管道。 | |
quic | QUIC | |
tcp | TCP | |
udp | UDP | |
unix | Unix 域套接字 |
user_agent.synthetic.type具有以下已知值列表。如果其中一个适用,则必须使用相应的值;否则,可以使用自定义值。
| 值 | 描述 | Stability |
|---|---|---|
bot | 机器人来源。 | |
test | 合成测试来源。 |
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.address | example.com |
server.port | 8080 |
network.peer.address | "192.0.2.5" |
network.peer.port | 8080 |
http.response.status_code | 200 |
相应的服务器 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.port | 8080 |
url.scheme | "https" |
http.route | "/webshop/articles/:article_id" |
http.response.status_code | 200 |
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_code | 500 |
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_code | 201 |
error.type | WebSocketDisconnect |