跳到主要内容
版本:Dev

可观测性导出器

可观测性导出器会将网关用量事件发送到用于链路追踪、日志记录、存储或记账的目标。本指南通过 AISIX Enterprise 和 AISIX Cloud 的控制面路径,或 AISIX OSS 的资源文件路径配置 OTLP/HTTP 导出器,再说明目标选择、内容采集和投递行为。

准备工作​

请先准备以下内容:

  • 以下任一配置路径:
    • AISIX Enterprise 或 AISIX Cloud,其中包含一个环境、已关联的网关和具备写入作用域的 Admin Token。对于 AISIX Enterprise,请按照 AISIX Enterprise 入门指南操作。如需申请 AISIX Cloud 访问权限,请联系 API7。
    • 加载声明式 resources.yaml 文件的开源 AISIX 网关。
  • 计划使用的导出器对应的遥测目标。
  • 用于验证投递的可用模型别名和调用方 API Key。

导出验证所用的网关和请求参数:

# AISIX_PROXY 不含尾部斜杠或端点路径
# 本地快速入门使用 http://127.0.0.1:3000
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export MODEL_ALIAS="YOUR_MODEL_ALIAS"

对于控制面示例,请导出 Admin API 基础 URL、Admin Token 和环境 ID:

# AISIX_CP 包含 /api,且不含尾部斜杠
# 本地 AISIX Enterprise 快速入门使用 http://localhost:8080/api
export AISIX_CP="YOUR_AISIX_CONTROL_PLANE_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"

其他部署方式请使用可访问的 AISIX Cloud Admin API URL。

选择导出器类型​

两种配置路径都支持所有导出器类型。AISIX Cloud Admin API 请求和资源文件条目通过 kind 值选择类型,控制台则显示同一底层类型对应的标签:

kind 值控制台标签适用场景
otlp_httpOTLP/HTTP已经通过 OTLP/HTTP 收集器或厂商端点收集链路。
object_storeObject storage希望将批量 NDJSON 请求事件写入 Amazon S3、S3 兼容存储、Google Cloud Storage 或 Azure Blob。
datadogDatadog使用 Datadog Logs HTTP 接收端。
aliyun_slsAlibaba Cloud SLS使用阿里云日志服务作为日志目标。

网关会将遥测直接发送到所选目标。

配置 OTLP 导出器​

设置示例使用的收集器端点和授权请求头:

# 请替换为实际值
export OTLP_ENDPOINT="https://collector.example.com/v1/traces"
export OTLP_AUTH_HEADER="Bearer YOUR_COLLECTOR_TOKEN"

网关进程必须能够访问该端点。端点可以是任意主机的 https:// 或 http:// URL,例如集群内的采集器 http://otel-collector-dev:4318/v1/traces。如果接收端与网关进程位于同一主机,可以使用 http://localhost:4318/v1/traces;容器化网关则需要使用接收端在容器网络或宿主机上的地址。如果接收端不要求认证,请从导出器中移除 headers 块。

使用 http:// 时,静态请求头和导出的遥测数据以明文在网络中传输。请求头可能携带认证令牌,遥测数据可能包含提示词和响应内容,因此请在可信网络中使用 http://。

1.7.0 及更早版本的网关仅对 localhost、127.0.0.1 和少数测试主机名接受 http://。环境中注册了此类网关时,AISIX Cloud Admin API 会以 422 DP_INCOMPATIBLE 拒绝保存其他主机上的 http:// 端点。将该环境的网关升级后即可保存。

AISIX Enterprise 或 AISIX Cloud​

创建导出器并获取其 ID:

EXPORTER_ID=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/observability_exporters" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "prod-otlp",
"kind": "otlp_http",
"endpoint": "'"${OTLP_ENDPOINT}"'",
"headers": {
"Authorization": "'"${OTLP_AUTH_HEADER}"'"
},
"sample_rate": 1
}' | jq -r '.observability_exporter.id')

❶ 只有当 OTLP 目标要求时才设置静态请求头。请求头值会加密存储,并且读取操作绝不会返回这些值。

❷ sample_rate: 1 可以让投递检查得到确定的结果。它等同于省略该字段,即导出每个请求链路。验证完成后,如需减少跨度数量,可以降低该值。

获取导出器,确认存储的配置:

curl -sS "$AISIX_CP/environments/$ENV_ID/observability_exporters/$EXPORTER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN"

你应该会看到类似下面的响应。读取操作通过 header_keys 暴露已配置的请求头名称,并通过 headers_set 确认已存储请求头值;但绝不会返回请求头值本身。

{
"observability_exporter": {
"id": "b46a9f5d-6a4d-4bb1-ae2c-4ab1b22f5e80",
"env_id": "0f2f6a1e-9d33-4a8f-9a6e-2a7b6a9c1d2e",
"name": "prod-otlp",
"enabled": true,
"kind": "otlp_http",
"endpoint": "https://collector.example.com/v1/traces",
"header_keys": ["Authorization"],
"headers_set": true,
"sample_rate": 1,
"created_at": "2026-07-22T08:30:00Z",
"updated_at": "2026-07-22T08:30:00Z"
}
}

保存 $EXPORTER_ID,以便后续更新或删除导出器。导出器默认启用。设置 enabled: false 可在不发送遥测的情况下保存资源。停用或删除导出器后,每个网关收到该配置变更时都会停止其投递流水线:已排队的事件会先投递完,导出器随后从网关的投递健康报告中移除。重新启用会启动一条计数器清零的新流水线。

AISIX OSS​

将以下导出器添加到完整资源文件的 observability_exporters 中。使用环境变量插值可以避免将收集器 Token 写入文件:

resources.yaml(OTLP 导出器)
observability_exporters:
- name: prod-otlp
kind: otlp_http
endpoint: ${OTLP_ENDPOINT}
headers:
Authorization: ${OTLP_AUTH_HEADER}
sample_rate: 1

验证组装后的完整文件:

aisix validate --resources resources.yaml

在进程环境中设置 OTLP_ENDPOINT 和 OTLP_AUTH_HEADER,然后启动或重启网关。只有当这些变量已经可用于运行中的进程时,才重新加载网关。导出器默认启用;添加 enabled: false 可保留条目但不发送遥测。

验证 OTLP 投递​

保存导出器只能确认 AISIX 接受了配置。要验证上面配置的 OTLP 导出器,请获取 AISIX 返回的请求 ID,在目标端查找该 ID,并检查网关的投递信号。如果正在检查的现有 OTLP 导出器的 sample_rate 小于 1,请暂时将采样率设为 1,避免该请求被采样丢弃。

通过一个可用的模型别名发送成功请求,并获取 AISIX 返回的 ID。无论 AISIX 接受调用方提供的 ID,还是自行生成 ID,这种方式都能取得准确结果:

export EXPORTER_NAME="prod-otlp"

if TEST_REQUEST_ID=$(
set -o pipefail
curl -fsS -D - -o /dev/null \
-X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer $AISIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${MODEL_ALIAS}"'",
"messages": [{"role": "user", "content": "Reply with: exporter check"}]
}' \
| awk 'tolower($1) == "x-aisix-request-id:" { id = $2; sub(/\r$/, "", id) } END { print id }'
) && test -n "$TEST_REQUEST_ID"; then
export TEST_REQUEST_ID
printf 'request ID: %s\n' "$TEST_REQUEST_ID"
else
unset TEST_REQUEST_ID
printf 'verification request failed or returned no request ID\n' >&2
false
fi

等待导出器发送该批次,然后在 OTLP 后端查找 aisix.request_id 属性等于 $TEST_REQUEST_ID 的跨度。找到该跨度即可确认端到端投递:网关已加载导出器,在需要时完成目标端认证,且目标端已接受该批次。

在 AISIX Enterprise 或 AISIX Cloud 中,环境的 Observability 视图通过导出器行显示投递是否健康,以及在线网关已发送的批次数。也可以通过 Admin API 查看相同的逐网关心跳数据:

curl -sS "$AISIX_CP/environments/$ENV_ID/dp_nodes" \
-H "Authorization: Bearer $AISIX_TOKEN" \
| jq --arg exporter "$EXPORTER_NAME" \
'[.data[] | select(.status != "offline") | .exporter_health[]? | select(.name == $exporter)]'

下次心跳后,至少一个在线网关应报告大于零的 delivered_batches 和 last_error: null。网关重启或导出器配置变更时,计数器会重置。非空的 last_error 表示当前投递失败。后续成功投递会清除 last_error,但历史字段 failed_batches 和 last_failure_unix 仍会保留数值。

使用开源 AISIX 网关时,请在目标端确认成功。如果记录未到达,请在网关日志中检查 sink delivery failed; retrying 或 sink delivery dropped。

了解投递行为​

每个导出器都有自己的投递管道:一个内存队列,后面是一个把记录攒批并发往目标端的工作线程。下面这些行为是固定的,没有配置项。

记录会一直缓冲,直到批次达到 100 条记录或经过 1 秒,以先到者为准。

目标端以可恢复的方式拒收一个批次时(连接失败、429 或 5xx),网关按时间预算而不是固定次数重试。延迟从 200 毫秒开始,逐次翻倍,上限为 30 秒;重试会持续到该批次首次尝试之后的 300 秒为止。预算耗尽后,该批次被丢弃,并在 aisix_otlp_fanout_drops_total 中计为 retries_exhausted。429 或 503 响应上的 Retry-After 头会取代计算出的延迟,同样以 30 秒封顶,因此要求更长等待的目标端会被尊重而不是被反复冲击。采用时间预算而不是尝试次数,正是导出器能扛住一段已知时长的接收端故障的原因:短于该预算的故障不会丢失任何数据。

在一个批次被重试期间,新记录仍在不断到达。每个导出器队列可容纳 8,192 条记录;队列满时被拒收的是最新的那条记录,计为 queue_full,这样已经排队的记录仍有机会送达目标端。

警告

启用了完整内容采集的导出器,其记录由自己持有,包含提示词和响应文本。在 content_max_bytes 取默认值 131,072 的情况下,目标端卡住时装满 8,192 条记录的队列可能占用数百 MB 常驻内存。当你在可能卡住的目标端上启用完整采集时,请结合网关的内存上限来设置 content_max_bytes。请参阅配置内容采集。

了解 OTLP 链路结构​

对于每个产生 OTLP 遥测数据的请求,AISIX 会导出一个链路层级,而不是为每个用量事件导出彼此无关的跨度。模型请求到达上游时,层级如下:

跨度OTLP 类型范围
入站请求SERVER覆盖请求从到达开始,直到响应完成或调用方断开连接。有效的入站 traceparent 会成为此跨度的远程父级。
逻辑操作CLIENT覆盖网关执行的上游操作,包括所有重试和故障转移尝试。它是 SERVER 跨度的子级。
上游尝试CLIENT表示一次服务提供方分发。每次尝试都是逻辑操作的子级,并携带 aisix.attempt_index。

因此,重试和故障转移会显示为同一逻辑操作下的同级尝试跨度。对于每个用量事件,AISIX 会把完整属性和捕获内容放在当前最具体的跨度上:优先放在尝试跨度,其次放在逻辑操作跨度,最后放在 SERVER 跨度。其他跨度仅携带关联该层级所需的字段,不会重复整个事件。

并非每个请求都包含所有三个层级:

  • 缓存命中、输入安全护栏阻断或其他分发前结果只有 SERVER 跨度,因为 AISIX 没有调用上游。
  • 不采用逐次尝试追踪的 MCP、A2A、Realtime、任务和透传调用包含 SERVER 跨度,以及一个表示上游操作的 CLIENT 跨度。

统计导出链路时,请根据跨度类型和父子关系,而不要只根据跨度名称。筛选 SERVER 跨度可以统计已采样的请求链路。sample_rate 小于 1 时,未被选中的请求不会出现。部分身份认证和格式错误输入路径会在用量事件或 OTLP 跨度产生前拒绝请求,因此 SERVER 跨度不能完整表示入站请求数。网关请求量请使用请求指标。分析单次模型尝试时,请使用携带 aisix.attempt_index 的 CLIENT 跨度。

延续入站 W3C 链路​

请求中恰好包含一个有效的 traceparent 时,AISIX 会延续该链路,并让自己的 SERVER 跨度成为调用方跨度的子级。取值格式错误或存在多个 traceparent 时,AISIX 会忽略它们并启动本地链路,而不会拒绝请求。通过网关字符和长度检查的配套 tracestate 会记录在 SERVER 跨度上。

除非 forward_client_headers 精确点名,否则 AISIX 不会把调用方的 traceparent 或 tracestate 转发给模型服务提供方、透传目标、MCP 服务器或 A2A Agent;通配符模式永远不会匹配到它们。默认情况下,该上下文只用于建立调用方到网关的关系。转发边界参见上游请求头。

OTLP 跨度属性参考​

OTLP 跨度遵循 OpenTelemetry 生成式 AI 与 HTTP 语义约定(semantic-conventions v1.41.1 发布版本)。约定未定义的属性使用 aisix. 前缀。

相对 1.6.0 及更早版本的变更

针对 1.6.0 及更早版本网关编写的链路查询、看板和告警需要更新。除请求头采集外,导出器配置无需改动。

  • 移除 gen_ai.system,请改用 gen_ai.provider.name。
  • OTLP 跨度不再携带 gen_ai.prompt 和 gen_ai.completion。采集的内容改用采集内容中的属性。Datadog 和阿里云 SLS 导出器的内容字段也做了同样的变更,详见 Datadog 和 SLS 记录中的采集内容。
  • gen_ai.request.model 是发送给上游的模型名称。调用方请求的别名或模型组名称改由 aisix.requested_model 携带。
  • gen_ai.usage.input_tokens 包含缓存的输入 Token。对于以 Anthropic 形态上报的用量(缓存读取和缓存写入与输入 Token 分开计数),该值现在会把两者加到输入 Token 上。Datadog 导出器的 gen_ai.usage.input_tokens 同样变化。详见导出遥测中的 Token 计数。
  • 跨度名称变化:不再使用 chat.completions;SERVER 跨度以 HTTP 路由命名,例如 POST /v1/chat/completions;MCP 跨度命名为 tools/call <tool>,而不是 execute_tool <tool>。
  • 成功的跨度不再设置 OK 状态,而是保持未设置。4xx 响应不再把 SERVER 跨度标记为错误。
  • aisix.client_source_ip 和 aisix.client_user_agent 更名为 client.address 和 user_agent.original。它们以及 http.request.header.<name> 属性从操作跨度移到 SERVER 跨度。
  • SERVER 跨度和聚合各次尝试的逻辑跨度不再携带 gen_ai.* 属性,只有生成式 AI 操作跨度携带,因此把生成式 AI 跨度转换为模型调用的后端对每次调用只计一次。
  • 资源属性 service.name 取网关的 observability.service_name(默认为 aisix),而不再是固定值 aisix-dp。
  • 要记录的请求头改由每个导出器的 request_headers 选择,不再由网关的 observability.usage_event.request_headers 决定。参见导出遥测中的请求头与响应头。

跨度名称与状态​

链路层级中的每个跨度各有一个角色。生成式 AI 操作跨度是当前最具体的跨度:优先是尝试跨度,其次是逻辑跨度,最后是 SERVER 跨度。

跨度名称错误状态
SERVER{method} {route},例如 POST /v1/chat/completions。只有当请求路径本身就是网关的固定路由时才附加路由,因此透传路径或 /v1/videos/{id} 只以方法命名。非标准方法以 HTTP 代替方法名。仅 5xx 状态为 ERROR。4xx 或 499 保持状态未设置。
生成式 AI 操作{gen_ai.operation.name} {gen_ai.request.model},例如 chat gpt-4o。MCP 跨度为 tools/call {tool},A2A 跨度为 invoke_agent {agent},透传跨度为 passthrough {route}。目标为空或超过 64 字节,或请求由通配符模型处理时(该模型名由调用方选定),名称只包含操作名。状态码大于等于 400 时为 ERROR,499 除外,因为关闭请求的调用方是主动取消。
聚合各次尝试的逻辑跨度与生成式 AI 操作跨度相同。与生成式 AI 操作跨度相同。

状态为 ERROR 的跨度还携带 error.type,取值为网关的错误类别(aisix.error_class),没有时为状态码。成功的跨度保持状态未设置。

SERVER 跨度的类型为 SERVER,逻辑跨度和尝试跨度的类型为 CLIENT。只有 SERVER 跨度的请求(例如缓存命中)以该 SERVER 跨度作为生成式 AI 操作跨度。

生成式 AI 操作跨度属性​

生成式 AI 操作跨度携带用量事件:

属性取值
gen_ai.operation.name/v1/chat/completions、/v1/messages 和 /v1/responses 为 chat;/v1/completions 为 text_completion;/v1/embeddings 为 embeddings;A2A 为 invoke_agent;MCP 为 execute_tool。其他请求类型报告其 aisix.operation 值,例如 passthrough。
aisix.operation网关自己的请求类型,可区分 chat、messages 和 responses。
gen_ai.provider.name实际分发的上游服务提供方。使用 Amazon Bedrock、Google Vertex AI 或 Azure OpenAI 适配器的服务提供方 Key 分别报告 aws.bedrock、gcp.vertex_ai 或 azure.ai.openai。其他服务提供方 Key 对相应服务提供方报告 openai、anthropic、gcp.gemini、deepseek、x_ai、mistral_ai、groq、cohere、perplexity 或 ibm.watsonx.ai,其余服务提供方原样报告其小写 ID。透传跨度报告路由所用服务提供方 Key 的服务提供方,A2A 跨度报告 a2a。MCP 跨度不携带该属性。
gen_ai.request.model发送给上游的模型名称。对通配符模型,是代入模型模板后的具体名称。
aisix.requested_model调用方请求的模型别名或模型组名称。
aisix.requested_model_idaisix.requested_model 所指模型的 ID。该名称未解析到已配置的模型时不携带。参见按请求模型 ID 关联。
server.address 和 server.port请求所发往的基础 URL 的主机和端口。Amazon Bedrock、Google Vertex AI 和 Azure OpenAI 服务提供方 Key 仅在设置了 api_base 时报告。透传跨度报告路由 target_url 的主机,preserve_host 路由不报告。MCP 和 A2A 跨度报告 MCP 服务器或 Agent 的 URL。未到达上游的请求(例如缓存命中或拒绝)不报告。
gen_ai.response.model服务提供方上报的具体模型版本。
gen_ai.response.id服务提供方的响应 ID。
gen_ai.response.finish_reasons只含结束原因一个元素的数组。
aisix.service_tier上游报告其实际处理该次尝试时所用的服务档位,原样记录。上游未报告时省略。参见读取实际服务档位。
gen_ai.response.time_to_first_chunk流式响应中,从本次尝试分发到收到第一个上游帧的秒数。
http.response.status_code用量事件记录的状态。
error.type失败时设置,见上文。
http.response.header.<name>导出器 upstream_response_headers 中列出的上游响应头,取自本次尝试的上游响应。参见导出遥测中的请求头与响应头。

当网关无法确定上游时(例如在选出路由目标之前就失败的请求),不携带 gen_ai.provider.name、gen_ai.request.model 和 server.*。

还会附加各协议专属的属性:

  • MCP:值为 tools/call 的 mcp.method.name、gen_ai.tool.name 和 aisix.mcp.server_name。
  • A2A:gen_ai.agent.name、gen_ai.conversation.id(即 A2A 的上下文),以及 aisix.a2a.operation、aisix.a2a.method、aisix.a2a.protocol_version、aisix.a2a.task_id、aisix.a2a.task_state 和 aisix.a2a.stream_event_count。
  • 透传路由:aisix.passthrough.route_name;当路由的 identity_header 提取到最终用户身份时,还携带 aisix.client_identity。

该跨度还会保留网关自己的关联和归因属性(有值时):aisix.request_id、aisix.exporter_name、aisix.api_key_id、aisix.api_key_name、aisix.user_id、aisix.model_id、aisix.attempt_index、aisix.attempt_kind、aisix.attempt_model、aisix.error_class、aisix.error_message、aisix.upstream_ttft_ms、aisix.downstream_latency_ms、aisix.gateway_overhead_ms、aisix.upstream_tpot_ms、aisix.audio.duration_seconds、aisix.gateway_embedding_calls、aisix.gateway_embedding_calls_dropped、aisix.jwt_subject、aisix.jwt_provider 和 aisix.jwt_claim_mapping。

请求参数​

在 /v1/chat/completions、/v1/messages、/v1/responses 和 /v1/completions 上,生成式 AI 操作跨度会记录调用方发送的参数,按请求自身的协议从请求体读取。同一请求的每次尝试都携带相同的值。

属性来源
gen_ai.request.max_tokensmax_completion_tokens 或 max_tokens;/v1/responses 上为 max_output_tokens。
gen_ai.request.temperature 和 gen_ai.request.top_ptemperature 和 top_p。
gen_ai.request.top_k聊天补全和 messages 上的 top_k。
gen_ai.request.stop_sequences聊天补全和 completions 上的 stop,或 messages 上的 stop_sequences。
gen_ai.request.frequency_penalty、gen_ai.request.presence_penalty 和 gen_ai.request.seed聊天补全和 completions 上的同名字段。
gen_ai.request.choice.count聊天补全和 completions 上的 n,仅在不为 1 时记录。
gen_ai.request.streamtrue,仅在请求为流式时记录。
gen_ai.output.typejson_object 或 json_schema 格式为 json,text 格式为 text,取自聊天补全的 response_format.type 或 responses 的 text.format.type。请求未指定格式时不记录。
openai.request.service_tierservice_tier(auto 除外),仅在 gen_ai.provider.name 为 openai 的跨度上记录。这是请求所要求的档位;上游实际处理请求的档位可能不同,记录在 aisix.service_tier 中。

在 /v1/embeddings 上,跨度从 encoding_format 记录 gen_ai.request.encoding_formats,从 dimensions 记录 gen_ai.embeddings.dimension.count。

Token 用量属性​

除 MCP 外,每个生成式 AI 操作跨度都携带用量:

属性取值
gen_ai.usage.input_tokens全部输入 Token,包括缓存部分:提示词 Token 加上上游在其之外单独上报的缓存创建和缓存读取 Token。始终存在。
gen_ai.usage.cache_read.input_tokens由服务提供方提示词缓存提供的输入 Token,两种计量形态均适用。大于零时存在。
gen_ai.usage.cache_creation.input_tokens写入服务提供方提示词缓存的输入 Token:Anthropic 的缓存创建计数,或 OpenAI 形态的 cache_write_tokens。缓存创建计数大于零或上游上报了 cache_write_tokens 时存在。
aisix.cache_creation_5m_tokens 和 aisix.cache_creation_1h_tokens上游报告了拆分时,缓存创建计数中以 5 分钟和 1 小时有效期写入的部分。二者同时出现或都不出现,参见按有效期拆分的缓存创建。
gen_ai.usage.output_tokens输出 Token,包含推理。向量嵌入跨度不携带。
gen_ai.usage.reasoning.output_tokens推理 Token。大于零时存在。
gen_ai.usage.audio.input_tokens 和 gen_ai.usage.image.input_tokens上游上报的音频和图像输入 Token。仅在上游上报了该计数时存在。
gen_ai.usage.audio.output_tokens 和 gen_ai.usage.image.output_tokens上游上报的音频和图像输出 Token。仅在上游上报了该计数时存在。向量嵌入跨度不携带。

这些值与记录的用量事件之间的关系,参见导出遥测中的 Token 计数;哪些上游会上报音频和图像计数,参见音频与图像 Token。

采集内容​

设置 content_mode: full 时,生成式 AI 操作跨度携带采集到的内容。对于 /v1/chat/completions、/v1/messages、/v1/responses 和 /v1/completions,一次消息交换会转换为约定定义的结构化属性,每个属性都是符合约定消息结构的 JSON 字符串:

  • gen_ai.input.messages 携带请求消息。completions 的提示词仅在为单个字符串时转换。
  • gen_ai.system_instructions 携带 Anthropic 的 system 字段或 Responses 的 instructions 字段。聊天补全中的 system 消息仍保留在 gen_ai.input.messages 中。
  • gen_ai.tool.definitions 携带每个已声明工具的 type、name、description 和 parameters。Anthropic 工具的 input_schema 作为 parameters 报告。
  • gen_ai.output.messages 携带一条 assistant 消息,其 parts 按调用方收到的顺序排列,并带有 finish_reason。

在 /v1/chat/completions、/v1/messages 和 /v1/responses 上,无论流式还是非流式,输出消息都包含三种 part 类型:

Part type字段采集来源
textcontent聊天补全的 content、Anthropic 的 text 块,以及 Responses message 中的输出文本。
reasoningcontent聊天补全的 reasoning_content 或 reasoning、Anthropic 的 thinking 块,以及 Responses reasoning 条目中可读的摘要和文本。
tool_callid、name 和 arguments聊天补全的 tool_calls、Anthropic 的 tool_use 块,以及 Responses 的 function_call 条目。arguments 能解析为 JSON 时为解析后的值,否则为原始字符串。

这些 part 取自调用方实际收到的响应,因此会体现输出数据脱敏,原生处理的请求与从其他协议转换的请求也按同样方式采集。Responses 的 encrypted_content 永远不会导出。约定中没有精确对应 part 类型的输出不会写入该消息:Anthropic 的 redacted_thinking 块和服务端工具块、聊天补全的 refusal 和 audio,以及 Responses 的 refusal 内容和 function_call 以外的工具调用条目。在 /v1/completions 上,该消息以一个 text part 携带响应文本。

无论由哪种协议上报,输出消息的 finish_reason 都使用约定定义的取值:

finish_reason原始取值
tool_calltool_calls、tool_call、function_call 和 tool_use。
lengthlength、max_tokens、max_output_tokens 和 model_context_window_exceeded。
content_filtercontent_filter、content_filtered、refusal 和 guardrail_intervened,以及 Gemini 的 SAFETY、RECITATION、BLOCKLIST、PROHIBITED_CONTENT、SPII、IMAGE_SAFETY 和 LANGUAGE。
errorerror,以及 Gemini 的 MALFORMED_FUNCTION_CALL、UNEXPECTED_TOOL_CALL 和 TOO_MANY_TOOL_CALLS。
stop其他所有取值,包括 stop、end_turn、stop_sequence 和 STOP。

原始取值按不区分大小写匹配。gen_ai.response.finish_reasons 保留服务提供方上报的原始值。输出消息必须带有结束原因,因此事件没有结束原因时不携带输出消息,例如失败或被取消的 /v1/responses 请求。参见 Responses 结束原因。

MCP 工具调用使用 gen_ai.tool.call.arguments,调用成功时还使用 gen_ai.tool.call.result。

每个结构化属性都受导出器 content_max_bytes 的限制,提示词侧和响应侧分别判断。不属于消息交换的内容(例如向量嵌入输入、图片、音频、任务和 Agent 文本)以原始形式保留在 aisix.content.prompt 和 aisix.content.response 中。被采集截断、无法转换或转换后会超过上限的一侧同样如此,因此 gen_ai.* 内容属性永远不会是残缺的。aisix.content_truncated: true 标记内容被截断的记录。采集到的输出 part 超过 content_max_bytes 时,输出消息回落为以一个 text part 携带响应文本;如果该文本也被截断,则以原始形式保留在 aisix.content.response 中。

Datadog 和阿里云 SLS 导出器对同一事件携带相同的结构化内容,只是字段名各不相同。详见 Datadog 和 SLS 记录中的采集内容。

SERVER 跨度属性​

SERVER 跨度描述入站 HTTP 请求:

属性取值
http.request.method请求方法。非标准方法报告 _OTHER,方法本身记录在 http.request.method_original 中。
url.path请求路径,最多 512 字节。
url.schemeTLS 监听器上为 https,否则为 http。
http.route路由,仅当路径本身就是网关的固定路由时记录。
url.query请求带有查询字符串时记录,最多 1,024 字节。
http.response.status_code最终响应状态。
client.address解析出的调用方地址。
user_agent.original调用方的 User-Agent。
http.request.header.<name>导出器 request_headers 中列出的请求头。参见导出遥测中的请求头与响应头。
aisix.request_id、aisix.exporter_name 和 aisix.operation关联同一请求各跨度的键。

url.query 会把敏感参数的值替换为 REDACTED。参数名 AWSAccessKeyId、Signature、sig 和 X-Goog-Signature 区分大小写匹配,key、access_token、token、client_secret、password、api_key 和 apikey 不区分大小写匹配,参数名先做百分号解码再比较。其他值原样导出,因此如果 OTLP 目标不应收到其他密钥,就不要通过查询字符串把它们发送给网关。

聚合各次尝试的逻辑跨度只携带 aisix.request_id、aisix.exporter_name 和 aisix.operation。

资源属性​

每个导出请求都携带以下资源属性:

  • service.name:网关启动配置中的 observability.service_name,默认为 aisix。1.6.0 及更早版本的网关始终报告 aisix-dp。
  • service.version:网关的构建版本。

插桩范围为 aisix-obs.otlp_http_sink,版本为网关的构建版本。

网关不保留相应数据的属性不会导出,包括 openai.response.system_fingerprint、gen_ai.agent.id、mcp.session.id 和 jsonrpc.request.id。上游实际处理请求的服务档位以 aisix.service_tier 导出,而不是 openai.response.service_tier。

配置其他导出器​

当遥测需要发送到对象存储或日志服务,而不是 OTLP 链路后端时,请使用其他导出器类型。使用 AISIX Enterprise 或 AISIX Cloud 时,将以下对象之一作为 POST $AISIX_CP/environments/$ENV_ID/observability_exporters 的请求体。

对象存储​

对于对象存储,请选择存储服务提供方、存储桶和对象键前缀。默认认证模式使用由网关解析的凭证引用:

{
"name": "request-events-s3",
"kind": "object_store",
"provider": "s3",
"bucket": "acme-aisix-events",
"prefix": "ai-gateway",
"region": "us-east-1",
"credential_ref": "acme_s3"
}

对象存储支持 Amazon S3、Google Cloud Storage、Azure Blob 和 S3 兼容目标。只有当网关运行时带有可写入存储桶的附加身份时,才对 S3 或 GCS 使用云身份。对于 Azure Blob,以及要求静态凭证的 S3 兼容目标,请使用 credential_ref。

对于 MinIO、Cloudflare R2 或阿里云 OSS 等 S3 兼容目标,请显式设置目标端点。未设置端点时,S3 导出器会使用原生 AWS S3 端点。

endpoint 用于覆盖存储服务商的原生端点,其含义取决于 provider:

providerendpoint 设置的内容
s3上传目标的 S3 兼容主机。
gcsCloud Storage XML API 基础 URL,例如私有端点。上传走 XML API,因此该端点必须提供 XML API;只接受 JSON API 上传的模拟器(例如原版 fake-gcs-server 镜像)无法接收对象。它优先于服务账号 JSON 中的 gcs_base_url。
azure_blobBlob 服务端点。

该值可以是任意主机的 https:// 或 http:// URL,例如集群内的 MinIO http://minio.storage.svc:9000。使用 http:// 时,上传的请求事件以明文在网络中传输,因此请在可信网络中使用。1.7.0 及更早版本的网关仅对 localhost、127.0.0.1 和少数模拟器主机名接受 http://。环境中注册了此类网关时,AISIX Cloud Admin API 会以 422 DP_INCOMPATIBLE 拒绝保存其他主机上的 http:// 端点。将该环境的网关升级后即可保存。

endpoint 不能与云身份同时使用:AISIX Cloud Admin API 会拒绝该组合;开源网关加载该组合后永远不会上传,并报告永久性投递错误。控制台为 S3 兼容目标、Cloud Storage 和 Azure Blob 提供该字段,并在选择云身份时隐藏它。

gcs 端点要求网关为 1.5.0 或更高版本,因为更早的网关会忽略它,转而上传到 Google 的公共 Cloud Storage 端点。因此,只要环境中注册了早于 1.5.0 的网关,AISIX Cloud Admin API 就会以 422 DP_INCOMPATIBLE 拒绝保存带 endpoint 的 gcs 导出器。

阿里云 SLS​

配置端点主机、项目、日志库和凭证引用:

{
"name": "request-events-sls",
"kind": "aliyun_sls",
"endpoint": "ap-southeast-3.log.aliyuncs.com",
"project": "acme-observability",
"logstore": "ai-gateway",
"credential_ref": "acme_sls"
}

Datadog​

配置 Datadog 站点、服务名称、标签和凭证引用:

{
"name": "request-events-datadog",
"kind": "datadog",
"site": "datadoghq.com",
"service": "ai-gateway",
"tags": ["team:platform", "tier:prod"],
"credential_ref": "acme_datadog"
}

对于资源文件路径,请将以下条目添加到 observability_exporters:

resources.yaml(请求导出器)
observability_exporters:
- name: request-events-s3
kind: object_store
provider: s3
bucket: acme-aisix-events
prefix: ai-gateway
region: us-east-1
credential_ref: acme_s3

- name: request-events-sls
kind: aliyun_sls
endpoint: ap-southeast-3.log.aliyuncs.com
project: acme-observability
logstore: ai-gateway
credential_ref: acme_sls

- name: request-events-datadog
kind: datadog
site: datadoghq.com
service: ai-gateway
tags: ["team:platform", "tier:prod"]
credential_ref: acme_datadog

只保留实际使用的目标,然后按照 OTLP 示例所述验证资源文件并启动或重新加载网关。使用与 OTLP 相同的请求 ID 方法验证这些导出器:在对象存储和 SLS 记录中按 request_id 查找,在 Datadog 日志中按 aisix.request_id 查找。Snowflake 指南介绍了如何直接检查对象存储输出。

SLS、Datadog 和对象存储导出器通过凭证引用或云身份,让目标凭证不进入导出器资源。网关发送遥测时会在本地解析这些凭证。

配置内容采集​

导出器默认包含请求状态、Token 计数、模型和服务提供方标识、请求 ID、结束原因和时间信息,但不包含提示词和响应正文。OTLP/HTTP、SLS 和 Datadog 导出器可以选择启用完整内容采集。

启用完整内容采集​

创建导出器时添加 content_mode 和 content_max_bytes。在 AISIX Enterprise 和 AISIX Cloud 中,可以使用相同字段更新现有导出器:

curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID/observability_exporters/$EXPORTER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content_mode": "full",
"content_max_bytes": 131072
}'

在控制台中,将导出器表单的 Content mode 设置为 Full,然后调整 Max content bytes。

对于资源文件路径,请将这些字段添加到导出器条目中,然后验证并重新加载文件:

observability_exporters:
- name: prod-otlp
kind: otlp_http
endpoint: ${OTLP_ENDPOINT}
headers:
Authorization: ${OTLP_AUTH_HEADER}
content_mode: full
content_max_bytes: 131072

只有当目标已获准接收最终用户提示词和响应文本时,才使用完整内容采集。AISIX 会按配置的字节上限分别限制每个采集内容字段。

了解截断记录​

有效 JSON 超过 content_max_bytes 时,AISIX 会先按结构缩减,使导出字段仍为有效 JSON。如果缩减后仍超过上限,则回退到 UTF-8 安全的字节截断。采集的提示词是序列化后的请求体,遵循同样规则。

内容截断行为
长字符串保留前缀,并追加 ...[aisix: truncated, N bytes total] 行内标记。
Base64 数据 URI用包含原始大小的占位符替换编码数据。
长数组保留首尾样本,并插入 {"_aisix_truncated": true, "omitted_items": N} 元素,其中 N 统计全部省略项。
非 JSON 内容,或结构缩减后仍放不下的 JSON在 UTF-8 字符边界处截断。

发生截断时,OTLP 记录包含 aisix.content_truncated: true,Datadog 和 SLS 记录包含 content_truncated: true。

Datadog 和 SLS 记录中的采集内容​

设置 content_mode: full 时,Datadog 和阿里云 SLS 导出器报告消息交换所用的结构化内容与 OTLP 导出器的采集内容属性相同:相同的消息、相同的 text、reasoning 和 tool_call 输出 part,以及相同的 finish_reason 取值。两个导出器各自使用以下字段名:

内容阿里云 SLSDatadog
请求消息input_messagesgen_ai.input.messages
Anthropic system 或 Responses instructionssystem_instructionsgen_ai.system_instructions
已声明的工具tool_definitionsgen_ai.tool.definitions
assistant 输出消息output_messagesgen_ai.output.messages
未结构化的提示词侧promptgen_ai.prompt
未结构化的响应侧responsegen_ai.completion

SLS 把每个结构化值写成紧凑的 JSON 字符串,Datadog 则写成嵌套 JSON。结构化字段只在记录确有对应内容时写入,因此 system_instructions 只会出现在带 Anthropic Messages system 字段或 Responses instructions 字段的请求上。聊天补全中的 system 消息仍保留在 input_messages 中。

提示词侧和响应侧分别判断,规则与 OTLP 相同。被采集截断、无法转换,或结构化值会超过 content_max_bytes 的一侧,保留在平铺字段中。无法转换的内容包括不属于消息交换的负载,例如向量嵌入输入、图片、音频、任务和 Agent 文本。输出消息的回落方式也与 OTLP 相同:采集到的输出 part 超过上限时,输出消息改由响应文本构建;只有该文本也被截断时,响应侧才保留为平铺字段。因此,一条记录可能同时携带结构化的输入消息和平铺的 response,反之亦然。MCP 工具调用的参数仍写在平铺的提示词字段中,结果写在平铺的响应字段中。与之前一样,content_truncated: true 标记内容被截断的记录。

既没有结构化内容、也没有采集到文本的一侧,仍会写成空的平铺字段。例如,失败的聊天请求会把消息记录在 input_messages 中,并写入空的 response。OTLP 则省略这样的一侧。

content_max_bytes 分别限制每个字段,因此一条记录最多可以携带四个受上限约束的内容字段:三个输入字段和输出消息。

相对 1.6.0 及更早版本的变更

1.6.0 及更早版本的网关把所有采集到的提示词写入 SLS prompt 和 Datadog gen_ai.prompt,把所有采集到的响应写入 SLS response 和 Datadog gen_ai.completion。升级后,这些字段只携带未结构化的一侧。

  • 把读取 prompt 或 response 的 SLS 索引、保存的查询、仪表盘和告警迁移到结构化字段。对于被截断或无法转换的一侧,仍需读取 prompt 和 response。
  • 在 SLS 中为 input_messages、system_instructions、tool_definitions 和 output_messages 创建字段索引。没有字段索引时,这些字段只能通过全文检索查到。要查询值内部的键,请使用 JSON 类型索引,或为字段开启统计并在 SQL 中用 json_extract 读取。
  • 把基于 gen_ai.prompt 或 gen_ai.completion 的 Datadog facet 和 monitor 迁移到 gen_ai.input.messages 和 gen_ai.output.messages 属性。

采集透传内容​

对于成功中继的透传路由流量,完整内容采集会将请求体记录为字符串,并遵循导出器的内容上限和 JSON 结构感知截断规则。对于缓冲响应,响应符合受支持的提取结构时会记录提取出的文本,否则将响应体记录为文本。对于流式响应,会记录累积的提取文本;不透明数据负载则保留为文本。

采集失败请求​

完整内容采集适用于下表汇总的受支持 AI 请求代理端点类型和 MCP 工具调用。A2A 采集记录的是消息内容,而不是 JSON-RPC 信封。Realtime、任务和批处理遥测不会被采集。透传请求如果在身份认证、授权、输入安全护栏或限流期间被拒绝,则不包含采集内容。

在 /v1/chat/completions、/v1/messages 和 /v1/responses 上,请求解析后产生用量事件的失败会把请求体作为采集的提示词记录下来,但 401 和 403 响应除外。请求体能够转换时记录为结构化输入消息(OTLP 和 Datadog 上为 gen_ai.input.messages,SLS 上为 input_messages),否则保留在平铺的提示词字段中。这包括输入安全护栏阻断(422)、除 401 和 403 之外的上游失败,以及解析后的校验失败(例如 messages 数组为空)。执行数据脱敏时,AISIX 采集脱敏后的请求体;格式错误的 JSON 会在创建用量事件前被拒绝,因此不会采集。

还应注意以下边界:

  • 调用方认证失败会在创建用量事件前被拒绝。
  • 所有路由目标都失败时,最后一次尝试的记录携带提示词。
  • 响应侧安全护栏阻断不会采集被阻断的输出。

这些边界既避免导出被拒绝的凭证和阻断输出,也保留调查其它失败所需的请求上下文。

查看各端点采集的内容​

端点类型采集的内容
文本生成响应文本。OTLP、Datadog 和阿里云 SLS 都以结构化 part 导出输出,包括推理和工具调用,详见采集内容和 Datadog 和 SLS 记录中的采集内容。
MCP tools/call通过流量控制和输入安全护栏检查后的 params.arguments,并应用所有数据脱敏;以及存在时的 JSON-RPC result。输出安全护栏阻断不会采集这两个字段。其它 MCP 方法不会被采集。
A2Amessage/send 和 message/stream 上,请求消息与回复消息里文本部分的内容。文件部分、数据部分和 JSON-RPC 信封不会被采集。
Embeddings、Rerank 和图片生成完整响应 JSON。
音频转录返回的转录文本。上传音频不会被采集;其 SHA-256 校验和会与请求文本字段一起记录。
文本转语音不采集二进制语音响应。

导出遥测中的模型字段​

当调用方请求的模型别名与处理某次尝试的模型不同时,用量遥测会同时记录两者。这对路由和合议流量很重要,因为一个面向调用方的别名可能解析为多个目标模型调用。

不同目标会以各自的遥测格式呈现这些值。OTLP 链路使用以下字段:

  • aisix.requested_model 包含调用方请求的别名或模型组名称。
  • gen_ai.request.model 包含该次尝试发送给上游的模型名称。
  • gen_ai.response.model 包含服务提供方上报的具体响应模型版本。
  • aisix.model_id 标识调用上游的模型资源:调用方请求的直连模型,或路由模型、语义路由器为该次尝试选定的目标。在选定路由目标之前写入的记录上为空。参见记录指向哪个模型。
  • aisix.requested_model_id 标识调用方请求的模型资源。参见按请求模型 ID 关联。

1.6.0 及更早版本的网关在 gen_ai.request.model 中放置调用方请求的别名。

按请求模型 ID 关联​

aisix.requested_model 是名称,因此重命名模型会把它的遥测拆成两个序列。aisix.requested_model_id 携带调用方所请求模型的 ID,重命名不会改变它。按该字段分组或过滤,即可跨重命名追踪同一个路由模型、语义路由器或合议模型。

它的取值取决于调用方所请求模型的类型:

请求的模型aisix.requested_model_idaisix.model_id
直接模型或嵌入模型该模型的 ID。同一个 ID。
通配符模型该通配符模型的 ID。同一个 ID。
路由模型或语义路由器它自身的 ID,出现在该请求的每条记录上,包括失败的尝试、最终应答的尝试,以及选定目标之前写入的记录。该次尝试所分发到的目标模型。在选定目标之前写入的记录上为空。
合议模型该合议模型的 ID,出现在每个合议成员和评审模型的记录上。该记录对应的合议成员或评审模型。合议模型的汇总记录以及合议成员运行之后的失败携带合议模型的 ID。请求在合议成员运行前被拒绝时为空。

当请求的名称已解析到模型、但网关没有选定任何目标时,例如调用方在第一次尝试之前取消了请求、安全护栏拦截了请求、限流以 429 拒绝了请求,或响应缓存命中,aisix.requested_model_id 仍携带所请求模型的 ID。对于路由模型或语义路由器,这些记录上的 aisix.model_id 为空,因此在 aisix.model_id 中按模型组的 ID 过滤会漏掉它们,请改用 aisix.requested_model_id 过滤。

当名称未解析到已配置的模型时,该字段为空,导出器不携带它。这包括未知的模型名称、透传路由正文中的 model(网关不会把它当作模型查找),以及不指定模型的 MCP 和 A2A 调用。

1.6.0 及更早版本的网关不导出 aisix.requested_model_id。

网关协议跨度​

A2A 或 MCP 调用不是模型推理,因此不会被编码成模型推理。按照 OpenTelemetry 生成式 AI 语义约定,每种协议有自己的跨度名称和操作名,并携带生成式 AI 操作跨度属性中列出的协议细节:

  • A2A 导出为 invoke_agent <agent>,gen_ai.operation.name 为 invoke_agent。
  • MCP 导出为 tools/call <tool>,gen_ai.operation.name 为 execute_tool,mcp.method.name 为 tools/call。1.6.0 及更早版本的网关将其命名为 execute_tool <tool>。
  • 透传路由导出为 passthrough <route>,gen_ai.operation.name 为 passthrough。

模型流量以操作名和上游模型命名,例如 chat gpt-4o,因此按 gen_ai.operation.name: chat 编写的链路查询只匹配模型流量。1.6.0 及更早版本的网关把所有模型跨度命名为 chat.completions。

Datadog 日志使用 aisix.requested_model 表示调用方请求的别名,使用 aisix.requested_model_id 表示所请求模型资源的 ID,使用 gen_ai.response.model 表示具体响应模型版本,并使用 aisix.model_id 表示调用上游的模型资源,取值与 OTLP 属性相同。

对象存储和阿里云 SLS 会保留底层用量事件字段名称,例如 requested_model、requested_model_id、model_id 和 provider_model_version。其中 model_id 的取值与 aisix.model_id 相同。阿里云 SLS 不写入为空的 requested_model_id,对象存储则将其写为空字符串。

导出遥测中的请求类型​

每条记录还携带该请求要求网关做的事情——对话补全、图片生成、视频提交、工具调用。取值及其含义参见区分请求类型。

各目的地对它的命名不同:

  • 对象存储和阿里云 SLS 保留用量事件字段名 operation。
  • Datadog 映射为 aisix.operation。
  • OTLP 以 aisix.operation 跨度属性携带,并出现在该请求整个跨度层级的每一层上,因此可以在链路的根节点按类型筛选。

OTLP 跨度上同时还有 OpenTelemetry 的 gen_ai.operation.name 属性,两者回答的是不同的问题。后者在 OpenTelemetry 词汇表有对应取值时使用该取值,能区分模型推理与 Agent、工具调用,否则使用 aisix.operation 的值。聊天补全、messages 和 responses 都报告为 chat,因此它无法区分这三者。端点本身重要时,请按 aisix.operation 过滤。

导出遥测中的请求头与响应头​

每个导出器都可以记录选定的入站请求头和选定的上游响应头的值。所有导出器类型都接受两个可选的请求头名称列表:

  • request_headers:记录到该请求每条用量事件上的入站请求头,让共用一个 API Key 的调用方可以按其发送的请求头进行归因。
  • upstream_response_headers:按每次尝试记录的上游响应头,取自该次尝试自己的上游响应,例如服务提供方的请求 ID 或区域。

每个导出器只记录自己列表中的请求头,因此两个导出器可以记录不同的请求头。记录与 content_mode 无关,这些值也永远不会发送到控制面。配置方式、名称规则和取值规则参见按请求头归因事件。

各目的地对这些值的命名不同:

导出器请求头上游响应头
对象存储每条记录中嵌套的 request_headers 对象。每条记录中嵌套的 upstream_response_headers 对象。
阿里云 SLS一个 request_headers 字段,其值为该对象的紧凑 JSON 字符串。一个 upstream_response_headers 字段,其值为该对象的紧凑 JSON 字符串。
Datadog嵌套的 aisix.request_headers 属性,单个请求头即 aisix.request_headers.<name>。嵌套的 aisix.upstream_response_headers 属性,单个响应头即 aisix.upstream_response_headers.<name>。
OTLPSERVER 跨度上每个请求头一个 http.request.header.<name> 属性。1.6.0 及更早版本的网关将其放在操作跨度上。生成式 AI 操作跨度上每个响应头一个 http.response.header.<name> 属性;请求有尝试时,即尝试跨度。

两种 OTLP 属性都是只含一个元素的字符串数组,遵循 OpenTelemetry HTTP 语义约定。

导出遥测中的 Token 计数​

导出器收到的是用量事件记录下来的 Token 计数,保留的是上游使用的口径,而不是调用方读到的 usage 块。详见记录的 Token 计数。

各目的地的报告方式如下:

  • 对象存储和阿里云 SLS 按记录原样保留用量事件字段,包括 reasoning_tokens、total_tokens,以及音频和图像计数 prompt_audio_tokens、prompt_image_tokens、completion_audio_tokens 和 completion_image_tokens。为零的 reasoning_tokens,以及未上报的 total_tokens 或音频、图像计数会被省略。
  • Datadog 日志携带 gen_ai.usage.input_tokens 和 gen_ai.usage.output_tokens,存在时还携带记录的 aisix.cache_creation_tokens、aisix.cache_creation_5m_tokens、aisix.cache_creation_1h_tokens、aisix.cache_read_tokens、aisix.reasoning_tokens、aisix.total_tokens、aisix.prompt_audio_tokens、aisix.prompt_image_tokens、aisix.completion_audio_tokens 和 aisix.completion_image_tokens。
  • OTLP 跨度携带 gen_ai.usage.input_tokens、gen_ai.usage.output_tokens、gen_ai.usage.cache_read.input_tokens、gen_ai.usage.cache_creation.input_tokens、gen_ai.usage.reasoning.output_tokens,以及 gen_ai.usage.{audio,image}.{input,output}_tokens 计数。参见 Token 用量属性。

按照 OpenTelemetry 生成式 AI 约定,输入 Token 包含全部缓存 Token。因此 OTLP 和 Datadog 报告的 gen_ai.usage.input_tokens 为 prompt_tokens + cache_creation_tokens + cache_read_tokens。只有以 Anthropic 形态上报的用量(例如 Anthropic 和 Amazon Bedrock)这两个缓存字段才不为零,这种形态把缓存读取和写入与输入 Token 分开计数。OpenAI 形态的上游已经把缓存 Token 计入 prompt_tokens,因此其导出的输入计数不变。例如,一个 Anthropic 回复有 19 个输入 Token、1,200 个缓存读取 Token 和 300 个缓存创建 Token,导出的 gen_ai.usage.input_tokens 为 1,519;1.6.0 及更早版本的网关对同一回复导出 19。

按照 OpenTelemetry 生成式 AI 约定,输出 Token 包含推理。因此,当事件把推理计在补全之外时,OTLP 和 Datadog 报告的 gen_ai.usage.output_tokens 为 completion_tokens + reasoning_tokens,否则为 completion_tokens。判断条件与控制面计价时相同:total_tokens 和 reasoning_tokens 都大于零,且 total_tokens 等于提示词 + 补全 + 推理 Token 之和、而不等于提示词 + 补全 Token 之和。详见推理 Token 如何计费。

该判断按事件进行,而不是按服务提供方。Vertex AI 适配器上的 Gemini 思考模型通常满足该条件;把推理报告在 completion_tokens 之外、且总数包含推理的 OpenAI 兼容上游同样满足。对 Gemini 而言,导出的输出计数与以前相同;对后一种 OpenAI 兼容上游,导出值为补全 + 推理,而 1.4.0 及更早版本的网关只导出补全。

AISIX Enterprise 或 AISIX Cloud​

控制台在目标环境的 Observability 视图中管理相同的导出器资源。导出器表单会收集目标字段、内容模式和各类型专属选项。

无论导出器通过 API 还是控制台保存,控制面都会把配置投射到关联到该环境的 AISIX 网关。

以下行为适用于投射到 AISIX 网关的导出器:

  • AISIX 网关会直接将请求遥测发送到你的目标。控制面不会代理导出的遥测。
  • 除非在导出器上启用完整内容采集,否则提示词和响应内容会留在网关上。
  • 凭证引用由 AISIX 网关解析。当目标需要运行时凭证时,控制台会展示需要在网关上配置的环境变量。
  • 投递健康状态来自网关心跳数据,会显示批次是否正在发送,或网关是否报告了投递错误。

对于 OTLP/HTTP 导出器,控制台提供 Langfuse、Honeycomb 和 Grafana Cloud Tempo 的预设,也接受自定义 OTLP 端点。

Trace UI URL 模板是可选的。当 Request Logs 视图需要将请求记录链接到外部 Trace UI 时使用它。模板必须包含 {request_id},以便控制面用日志记录中的请求 ID 替换它。

下一步​

如需在 Snowflake 中查询对象存储遥测,请继续阅读将请求遥测加载到 Snowflake。使用指标与用量事件比较导出记录与网关指标,并使用访问日志与请求关联追踪单个请求。