访问日志与请求关联
AISIX AI 网关会写入结构化访问日志,并记录可将请求与调用方、前置基础设施和上游模型服务提供方关联起来的标识符。借助这些记录,运维人员可以还原请求过程,并在各个系统中找到对应的条目。
收集访问日志
AISIX 通过进程日志记录器将访问日志写入标准错误流。容器运行时、服务管理器或主机日志流水线可以收集该数据流。
在启动配置中设置进程日志级别。默认值为 warn,只写入 WARN 及以上级别:
observability:
log_level: "warn"
排查问题时请调到 info。这会增加生命周期日志(例如 aisix listening 和 etcd connected)、单次调用日志(例如 provider call completed),以及监控模式观察结果等护栏诊断日志。默认级别下这些日志都不会写入,因此请通过 /readyz 确认网关已启动,而不是查看日志。日志级别在启动时读取,修改后需要重启。1.9.0 及更早版本的网关默认为 info。
当 RUST_LOG 环境变量设置为有效过滤器时,它会覆盖已配置的日志级别。
访问日志默认开启,且不受日志级别影响:只要 access_log 开启,无论 log_level 或 RUST_LOG 取何值,AISIX 都会写入每一行访问日志。在 RUST_LOG 中指定该目标(例如 info,aisix_obs::access_log=off)也无法关闭。要关闭访问日志,请把 access_log 设置为 false:
observability:
access_log: false
1.9.0 及更早版本的网关以 info 级别写入访问日志,因此生效的日志过滤器低于 info 时不会写入,在 RUST_LOG 中指定其目标也可以将其关闭。
设置 access_log: false 后,AISIX 不再写入任何访问日志行,其他日志行不受影响。该设置在启动时读取。1.5.0 及更早版本的网关会忽略 access_log,始终写入访问日志。访问日志没有单独的格式或接收端配置;请收集进程的标准错误流。
在相应值可用时,访问日志会包含请求方法、路径、状态、耗时、模型服务提供方、模型、API Key ID、请求 ID、Token 数量、路由结果、响应缓存的判定结果,以及请求体和响应体的大小。
对于失败的请求,error_class 提供稳定的失败类别,error 提供底层原因。状态码为 400 及以上的日志行总有 error:如果没有更具体的原因到达该行(例如被拒绝的 GET /mcp),它写 request failed with status <status>,且 error_class 可能为空。1.8.0 及更早版本的网关在这种回退情况下把 error 留空。
error_class 与用量事件的 error_class 使用同一套类别词汇,但对于上游失败,它与面向客户端的 error.type 不同。例如,上游 HTTP 错误在访问日志中是 upstream_status,在错误信封中是 upstream_error。完整的类别词汇参见读取错误类别。
1.5.0 及更早版本的网关在非流式日志行上使用较旧的类别名称,具体拼写参见读取错误类别。此外,它在 /mcp 或 /a2a 上拒绝请求(例如安全护栏拦截或限流拒绝)时,会把错误类别和 error 留空;在 /v1/responses、/v1/completions 或音频端点上以缓冲方式执行输出安全护栏拒绝时,这两个字段也会留空。
状态、错误类别、调用方寻址的模型和调用方等待时间分别写为 status_code、error_class、requested_model 和 downstream_latency_ms,与用量事件中相同取值的字段同名,因此同一 request_id 的日志行和用量事件读法一致。1.7.1 及更早版本的网关将它们写为 status、error_kind、model 和 latency_ms。网关只写其中一套名称,升级时请更新读取旧名称的日志查询或解析逻辑。
MCP 访问日志还会添加 JSON-RPC 方法、调用的工具和工具发现计数。诊断工具发现和访问问题时如何使用这些字段,请参见 MCP 可观测性。
消化消费缓慢的日志接收端
AISIX 不在产生日志行的线程上写出日志。访问日志和应用日志都先进入一个容量为 32,768 行的内存队列,再由一个专用的写入线程排空到标准错误流。因此,当接收端停止读取(容器运行时轮转日志文件是最常见的情形)时,被阻塞在管道缓冲区上的是那个写入线程,而不是请求处理。
如果阻塞持续到队列被填满,AISIX 会丢弃新产生的日志行,而不是让请求为它们等待。每次丢弃都会增加 aisix_log_lines_dropped_total;接收端恢复消费后,网关会记录一条 log sink fell behind; dropped log events 警告,说明总共丢失了多少行。该计数器在每次抓取时都会发出,因此健康的网关报告 0。
该行为没有任何配置项,队列容量是固定的。丢弃计数非零是排查日志采集链路的信号,而不是网关本身的问题。优雅关闭时,网关最多等待五秒尝试排空队列;超时后不再等待。队列排空也不是下游存储的交付确认,因此接收端阻塞、过慢或写入失败时,不能保证末尾日志全部送达。
了解哪些请求会被记录
网关代理监听端口应答的每个请求都会写一行访问日志,包括从未到达模型的请求:
- 认证拒绝:凭证缺失或被拒绝时的
401,以及 JWT 缺少必需 scope 时的403。该行携带status_code、error_class和error,但由于尚未解析出密钥,不含api_key_id。它绝不包含所提交凭证的任何部分。同一请求另有一行aisix::auth日志,携带调用方地址,以及已停用或已过期 API Key 的密钥 ID;对于缺失凭证或未知 API Key,该行以debug级别写入。 - 未匹配任何路由的路径(以
404应答),以及以不支持的方法调用已知路径(以405应答)。 GET /v1/models、位于/a2a/{agent}/.well-known/agent-card.json的 A2A Agent Card,以及 OAuth 受保护资源发现文档。
/livez 和 /readyz 探针不写访问日志。
由于未认证的请求也会被记录,面向公网的网关会在访问日志中记录扫描器探测等杂散流量。没有设置可以单独过滤它们;access_log 只能整体开启或关闭访问日志。
1.5.0 及更早版本的网关不会为认证拒绝、未匹配的路径、405 应答、/v1/models、A2A Agent Card 或 OAuth 发现文档写访问日志。
解读两个耗时字段
每条日志都携带两个耗时字段,它们回答的是不同的问题:
| 字段 | 度量内容 |
|---|---|
downstream_latency_ms | 调用方等待的时间。它在响应头写出时结束;对于流式响应,即首个 Token 或转发帧到达的时刻。 |
duration_ms | 请求占用网关的时长,从收到请求直到请求结束。 |
downstream_latency_ms 永远不会大于 duration_ms;对于普通缓冲响应,两者采用相同的处理完成时间口径。这不表示响应头之后没有响应体;响应体交付与访问日志写入时机见下文。对于通常的流式响应,二者之差表示首帧之后的流持续时长,因此请用 downstream_latency_ms 衡量调用方体验,用 duration_ms 衡量连接被占用的时长。
部分路由按设计采用不同口径:
- 在
/a2a和音频转录中继上,downstream_latency_ms本身就覆盖整个流,这也是用量事件中作为调用方等待时间上报的数值。因此它与duration_ms相等,而不是更短。 /v1/audio/speech在上游应答后才把生成的音频转发给调用方,它的duration_ms覆盖整个转发过程,直到最后一个字节。1.4.0 及更早版本的网关则在响应头处结束该时长。- 在
/v1/videos/{id}/content上,由网关从模型服务提供方代理下载的视频,其duration_ms同样覆盖整个转发过程;重定向到模型服务提供方自身 URL 或返回错误时,duration_ms在网关生成响应时结束。1.4.0 及更早版本的网关对所有/v1/videos/{id}/content请求都在响应头处结束该时长。
解读 Token 数量
只要请求产生了 Token 用量,日志行就会携带 prompt_tokens、completion_tokens 和 total_tokens。这覆盖 Chat Completions、流式响应,以 及非流式的 /v1/messages、/v1/embeddings、/v1/responses、/v1/completions、/v1/rerank、/v1/images/*、/v1/audio/*、/v1/decisions 和 /a2a 请求,这些请求的日志行报告与该请求最终用量事件相同的数量。/v1/realtime 日志行携带会话的输入和输出总量。未产生 Token 用量的请求不写 Token 字段,而不是写零;以下日志行同样不携带 Token 字段:/v1/messages/count_tokens、Files、Batches 和 Fine-tuning 的管理调用、/v1/videos、/mcp、认证和路由拒绝、调用方在响应头写出前离开时的 499 日志行,以及会话建立前就失败的 Realtime 会话。
1.7.1 及更早版本的网关只在 Chat Completions、透传路由和流式响应上写 Token 字段。上述其他端点的非流式日志行和 Realtime 日志行都不携带 Token 字段。
日志行上的 total_tokens 是网关计算的含缓存总数:提示、补全、缓存写入和缓存读取 Token 之和。Anthropic 等上游与输入分开上报的缓存 Token 会被加上,而 OpenAI 等上游已计入提示 Token 的缓存读取不会重复计算。限流和 Token 指标使用的也是这个数值。用量事件中的 total_tokens(即 SLS、对象存储和 Datadog 导出器投递的值)则是上游自己上报的总数,上游未上报时该字段不出现。
解读请求体与响应体大小
访问日志会记录每个方向上经过网关的消息体字节数。两个字段都是无符号字节数,1.4.0 及更早版本的网关不会写出它们:
| 字段 | 度量内容 |
|---|---|
request_body_bytes | 网关从调用方读取的请求体字节数。网关不会解压请求体,因此这是线上传输的大小。 |
response_body_bytes | 网关交给其 HTTP 服务器、发往调用方的响应体字节数,包括 data:、event: 行和 [DONE] 等 SSE 帧格式,以及保活心跳帧。响应头、分块传输编码的帧格式和 TLS 不计入。 |
大小未知时,该字段会从日志中省略,而不是写成 0,因为 0 是一个真实的大小。
只有当网关把请求体读到末尾时,request_body_bytes 才会出现。这包括读完请求体后才被拒绝的请求(例如 JSON 格式错误),以及调用方离开前请求体已被读取的 499 日志。以下情况会省略该字段:
- 网关根据
Content-Length在读取请求体之前就拒绝了请求,即proxy.request_body_limit_bytes返回的413; - 路由从不读取请求体,例如大多数
GET请求,以及调用未知 Agent 的/a2a请求; - 调用方在上传之前或上传过程中断开连接;
- 请求打开的是
/v1/realtime会话。
只有两种情况会省略 response_body_bytes:调用方在响应头写出前离开时的 499 日志,以及 /v1/realtime,因为其 WebSocket 会话没有 HTTP 响应体。服务器从未读取响应体的响应(例如对 HEAD 请求的应答)报告 0。调用方在响应中途断开时,该字段统计截至当时已交给服务器的字节数,可能超过调用方实际收到的字节数。
读取语义路由决策
发往语义路由器的请求会记录路由器的决策方式,基于向量嵌入的后端和 TypeSafe jev 后端都是如此。路由器做出决策后,无论请求随后以何种方式结束,这些字段都会出现在该请求的日志行上。发往其他模型的请求的日志行不会携带它们:
| 字段 | 出现条件 | 值 |
|---|---|---|
semantic_route | 由某条路由的目标处理了请求。 | 路由名称。当 proxy.expose_debug_headers 为 true 时,x-aisix-route 响应头会报告同一名称。 |
semantic_score | 路由器计算出了决策。 | 对于向量嵌入路由器,是胜出路由的余弦相似度;没有路由匹配时,是最接近路由的余弦相似度。对于 jev 路由器,是 jev 对其所选路由的置信度。 |
semantic_fallback | 没有路由处理该请求。 | 由默认模型或失败策略处理该请求的原因,取值见下表。 |
semantic_pinned | 请求发送到了其会话固定的路由,没有进行分类。 | 始终为 true。其他行不带该字段。 |
semantic_fallback 的取值如下:
| 值 | 含义 |
|---|---|
no_match | 向量嵌入路由器:没有路由达到其阈值。 |
low_confidence | jev 路由器:jev 选中了某条路由,但置信度低于 min_confidence。 |
empty_prompt | 请求不含可供决策的用户文本,因此未进行决策调用,直接发往默认模型。 |
decision_failed | 向量嵌入调用或 jev 调用失败或超时,并应用了路由器的失败策略,包括策略为 fail 时返回的 503,此时该行携带 error_class="semantic_decision_failed"。 |
target_unavailable | 已选出某条路由,但其目标无法为该调用方提供服务:目标的客户端 IP 允许列表排除了该调用方,或目标不可用而默认模型可用。改由默认模型处理。 |
在 no_match、low_confidence 或 target_unavailable 行上同样会出现 semantic_score,因此调整路由器时,应把它与阈值或 min_confidence 进行比较。没有计算出决策时(例如 empty_prompt、decision_failed,以及所有带 semantic_pinned 的行),该字段不出现。固定目标不可用的请求带有 semantic_pinned=true 和 semantic_fallback="target_unavailable",没有 semantic_route。1.5.0 及更早版本的网关不会写这些字段,1.10.0 之前的网关不会写 semantic_pinned。
识别实际处理请求的目标
网关选定目标后,日志会在 requested_model 旁携带 upstream_model 和 provider_key_id。requested_model 的 含义不变——调用方寻址的条目,对于路由请求即模型组名称——而新增的这一对字段标识实际下发到的目标以及所使用的 Provider Key。如果没有选定目标,例如请求在下发前被拒绝,或在路由解析完成前被放弃,这两个字段会从日志中省略。
寻址模型组的请求还会携带 served_by_model,即实际处理请求的目标名称。它与 x-aisix-served-by 响应头报告的值相同;即使网关不发送该响应头,日志也会记录它。网关只有在 proxy.expose_debug_headers 为 true 时才发送该响应头。
由响应缓存返回的响应同样没有下发到任何目标,此时这对字段上报什么取决于调用方寻址的条目是哪种类型。参见解读缓存判定结果。
解读缓存判定结果
在 /v1/chat/completions 上,日志会上报响应缓存如何处理了该请求:
| 字段 | 取值 |
|---|---|
cache_status | disabled、miss、hit 或 bypass |
cache_hit_layer | exact 或 semantic,仅在命中时出现 |
这两个字段的拼写与用量事件完全一致,因此同一 request_id 的访问日志和用量事件读起来是一致的。凡是没有缓存判定可上报的日志都会省略它们:不做缓存的其他路由,以及在请求产生响应之前就写出的日志。流式请求和被取消请求的日志则从该请求的最终用量事件中取这两个值,因此两者不会出现分歧;由于流式响应从不被缓存,即使环境中启用了缓存策略,这类日志也会上报 cache_status="disabled"。
缓存命中不会联系任何上游,因此其日志中与目标相关的字段只上报在没有下发的情况下该条目仍能声明的内容:
| 缓存命中时的字段 | 直连模型 | 模型组(routing 或 semantic) |
|---|---|---|
upstream_model、provider_key_id | 该条目自身的静态映射。它们是该模型的属性,无论请求是否真的离开过网关都成立——并不代表本次请求到达了模型服务提供方 | 省略。模型组没有自己的映射,而哪个目标产出了所存响应也没有被记录在任何地方 |
provider | 该条目自身的模型服务提供方 | unknown。与上面那对字段不同,它保留这个哨兵值而不是省略,因为它与 Prometheus 的 provider 标签是同一个字符串,而标签不能缺省 |
served_by_model、provider_request_id | 省略 | 省略 |
要把缓存返回的响应与从未到达模型服务提供方的请求区分开,靠的是 cache_status,仅凭目标字段缺失无法判断。被输出安全护栏拦下的缓存命中同样遵守上述全部规则,并且仍然上报 cache_status="hit",即使这条日志最终是 422。
1.2.0 及更早版本的网关完全不写缓存相关字段,并且会把模型组的缓存命中记在该请求的路由策略恰好排在首位的那个目标名下。
该请求的用量事件会上报相同的判定结果,并补充所存响应自身记录的信息,参见用量日志记录了什么。
了解日志写入时机和覆盖范围
无论结果如何,AISIX 对每个请求只写一条访问日志。写入时机决定了这条日志能够携带哪些信息:
| 信号 | 写入时机 | 提供的信息 |
|---|---|---|
| 非流式请求的访问日志 | 响应体已全部交给服务器,或因调用方离开而被丢弃时 | 请求结果及网关解析出的所有字段,包括可用时的 Token 数量和模型服务提供方响应 ID。 |
| 流式请求的访问日志 | 流结束时 | 最终状态和 Token 数量。建模代理流还可以记录 provider_request_id、served_by_model 和路由计数,透传流会将这些字段留空。两者都会记录与最终用量事件相同的错误详情;1.5.0 及更早版本的网关会在透传流上将错误详情留空。 |
| Realtime 会话的访问日志 | WebSocket 会话关闭后 | 会话结果、已解析的请求字段,以及该会话的 Token 总数。 |
| 被取消请求的访问日志 | 调用方在响应头写出前断开时 | 状态 499,以及请求此时已解析出的各项标识,包括已下发的目标。Token 数量、provider_request_id 和路由计数保持为空,因为请求从未产生这些值。 |
provider call completed 日志,以 info 级别写入 | 每个记录了 provider_request_id 的模型服务提供方调用各写入一次 | 该上游尝试的 request_id、attempt_index、is_final_attempt、attempt_kind 和 provider_request_id。 |
| 用量事件 | 支持的代理路径中,每次请求尝试写入一次 | 尝试结果、用量、延迟,以及可用时的模型服务提供方响应 ID。 |
流式请求过去在响应打开时写出日志,因此调用方随后放弃的流会被记为 200,而且日志中没有 Token 数量。现在这两点都由流结束时的单条日志解决。1.2.0 及更早版本的网关仍在响应头处写出该日志。
凡是有响应体的请求,其日志都在响应体处理完毕后才写出,因为只有到那时两个消息体大小才最终确定。日志的内容不变,每个请求仍只有一条日志:流式日志使用请求的最终状态和 Token 数量。1.4.0 及更早版本的网关会在非流式请求的响应就绪时、响应体发送之前就写出日志。所有日志都在最后写出,会带来两个可见的影响:
- 访问日志排在该请求的
provider call completed日志之后。1.4.0 及更早版本的网关可能先写出访问日志。 - 如果部署平台在慢速调用方仍在读取响应体时终止进程(例如
terminationGracePeriodSeconds耗尽),该请求的日志将不会写出。流式响应此前就存在这种情况;非流式响应现在也是如此,1.4.0 及更早版本的网关除外。如何设置该期限,请参见设置平台期限。
追踪模型服务提供方调用尝试
provider_request_id 是模型服务提供方为这次调用给出的 ID,可以用它在模型服务提供方的控制台或支持记录中查找对应调用。有响应对象时,AISIX 取响应对象的 ID,例如 OpenAI 的 chat.completion.id、Anthropic 消息 id、Responses API 的 resp_… 或 Gemini 的 responseId;否则取服务提供方的请求 ID 响应头,按 x-amzn-requestid、x-request-id、request-id、x-ms-request-id、apim-request-id、x-goog-request-id、cf-ray 的顺序取第一个存在的。响应头覆盖了响应本身不带 ID 的调用:每次失败的上游尝试(包括在首个 Token 之前失败的流)、/v1/messages/count_tokens,以及成功的向量嵌入、音频、图像、Rerank 和 Bedrock 调用。重试请求的每条事件携带的是响应该次尝试的那个响应的 ID。
没有可用 ID 时,该字段会被省略而不是留空,包括安全护栏拦截、缓存命中、在下发前被拒绝的请求,以及服务提供方既没有返回响应 ID、也没有返回上述响应头的调用。/v1/realtime 不记录响应头中的 ID。在建模代理路由上,流式响应可在 ID 随首帧到达时携带它,因为日志在流结束时写出;但如果调用方在该帧到达前已离开则不会记录。
失败请求的日志行会写明其尝试的目标所属的服务提供方,与请求指标一致。在下发前就失败的请求不写服务提供方。
访问日志上报的是实际处理该请求的那次尝试的 ID。要查看发生重试或故障转移的请求的其他尝试,请阅读 provider call completed 条目:通过 request_id 将其与访问日志关联,并使用 attempt_index 区分重试与故障转移。这些条目以 info 级别写入,因此需要 log_level: "info"。
重试或故障转移过程中失败的上游尝试还会写入一条 WARN 日志,消息为 routing target attempt failed。该日志行把 request_id 作为独立字段携带,与 target_model、target_attempt、error 和 retryable 并列,因此在任何日志级别下都能与请求关联。在 1.9.0 及更早版本的网关上,日志级别低于 info 时不会写入在其他日志行前加上请求 ID 的请求跨度(Span),此时该字段是唯一的关联方式。
跨系统关联请求
x-aisix-request-id 响应头是关联请求记录的主要键,AISIX 会在每个代理响应中发送它。其他响应头会报告重试时间;当网关开启 proxy.expose_debug_headers 时,还会报告缓存结果和所选目标;其路由覆盖范围请参阅响应头和错误码。
一个请求可能涉及三类标识符,彼此不能替代:
| 标识符 | 分配方 | 用途 |
|---|---|---|
request_id | AISIX;如果 AISIX 接受调用方提供的值,则由调用方分配。以 x-aisix-request-id 返回。 | 查找请求的访问日志和用量事件,包括导出的记录以及控制台 日志 页面中的条目。 |
downstream_request_id | 前置基础设施通过 x-request-id 请求头分配。记录在网关日志中,但不会作为独立的下游 ID 返回。如果 AISIX 接受该值,则以 x-aisix-request-id 返回。 | 在 Ingress Controller、反向代理、服务网格或 CDN 中查找同一个 HTTP 请求。 |
provider_request_id | 模型服务提供方;响应中包含 ID 或请求 ID 响应头的每次上游尝试各有一个。 | 在模型服务提供方控制台中查找该次尝试,或向其支持团队提供该 ID。 |
调查已完成的响应时:
- 从返回给调用方的
x-aisix-request-id值开始。 - 通过
request_id查找对应的访问日志和用量事件。使用attempt_index对重试或故障转移排序。is_final_attempt: true的那一行是最后一行。 - 需要与模型服务提供方一起调查调用时,从相关尝试中读取
provider_request_id。
如果连接在响应头发送前断开,请从前置基础设施提供的 downstream_request_id 开始调查。
匹配前置基础设施
AISIX 会分别记录网络连接、转发请求和解析出的调用方地址:
| 值 | 标识对象 | 匹配对象 |
|---|---|---|
peer | 已接受 TCP 连接的远端,包括其源端口。当受信任的四层负载均衡器在连接开头发送 PROXY protocol 头时,它是该头中的客户端地址和端口。参见客户端 IP 解析。 | 前置代理的连接记录;四层负载均衡器发送 PROXY protocol 头时,则是客户端自身的连接。 |
downstream_request_id | 从 x-request-id 接收的 HTTP 请求 ID。 | 前置代理或 Ingress Controller 的请求日志。 |
| 解析出的调用方地址 | 通过 proxy.real_ip 选择的不带端口的调用方 IP。它以 peer 为起点,并采信受信任的 X-Forwarded-For 请求头。 | 访问控制决策和用量记录。 |
如果存在,peer 和 downstream_request_id 会贯穿请求的访问日志、provider call completed 条目和中间诊断日志。缺失的值会被省略,而不是以空字段记录。
AISIX 会先检查传入的 x-request-id,再将其写入日志。记录该值并不会让它成为网关的 request_id;是否接受该值由 proxy.request_id.accept_headers 单独控制。
诊断未完成或被拒绝的请求
访问日志和相关信号可用于区分请求停止的位置:
| 场景 | AISIX 记录 | 附加信号 |
|---|---|---|
| 调用方在响应头发送前断开 | 状态为 499、error_class="client_disconnected" 且 error="client closed the request before the response head was written" 的访问日志。如果模型、模型服务提供方和已下发的目标已经解析,则日志会包含这些信息 ,但不含 Token 字段。 | 一条状态、类别和消息均相同的用量事件,Token 数量和成本均为零。aisix_proxy_client_cancelled_requests_total 对该请求计数。 |
| 调用方在响应头写出后、尚未读取流内容前断开 | 同样的 499 日志,error="client closed the request before the response body was streamed"。 | 一条取值相同、已投递 Token 为零的用量事件。由于上游已经应答,该事件会标明处理它的目标。该场景同样会被取消计数器统计。 |
| 调用方在流式响应期间断开 | 在流结束时写出的 499 日志,包含 error_class="client_disconnected" 和 error="client closed the request while the response was streaming"。1.5.0 及更早版本的网关在透传路由上会把错误类别和 error 留空。 | 一条状态为 499、error_class="client_disconnected"、包含断开消息及断开前已到达 Token 数量的用量事件。该场景不会增加取消计数器,因为该计数器只记录请求级守卫自己观测到的情况。 |
| 上游在流式响应过程中失败 | 在流结束时写入一行,状态为该失败的状态,例如连接断开为 502、读取超时为 504。该行还会以 error_class 和 error 记录失败;1.5.0 及更早版本的网关在透传路由上会把这两个字段留空。调用方收到的是 200。 | 一条状态相同并包含失败类别和消息的用量事件。参见响应头发出后失败的流。 |
| 超大请求正文被完全排空 | info 级 别的 aisix::body_limit 条目,其中 drain_outcome="completed",因此需要 log_level: "info"。调用方可以收到 413 Content Too Large。 | aisix_proxy_request_body_limit_rejections_total 对该拒绝计数。 |
| 超大正文无法完全排空 | 诊断结果为 cap_reached、timeout 或 client_read_error,调用方通常会看到连接关闭。这些 warn 条目按每种结果每秒最多一条进行限制。 | 拒绝指标会对每次发生计数,包括日志限流器抑制的诊断。 |
正文限制诊断条目还包含 request_id、declared_content_length、configured_limit_bytes 和 drained_bytes。使用 request_id 将其与访问日志关联。
如果调用方在模型解析前断开,访问日志既不包含模型,也不包含模型服务提供方。当调用方寻址的条目是模型组时,其用量事件的 model_id 为空,因为模型组自身的名称永远不会写入该字段;直连模型则会记录自己的标识符。
取消请求只有在已通过认证且所属路由支持用量计量时,才会写入用量事件。认证失败会产生认证指标、诊断日志和未归属的访问日志条目,但不产生用量事件。正文大小限制拒绝也可能在读取凭证之前产生访问日志和请求指标。无法解析的正文会产生拒绝日志和指标,但不产生用量事件。完整边界请参阅用量日志记录了什么。
复用自己的请求 ID
如果服务已经为业务调用生成请求 ID,请将其发送给 AISIX。被接受的值随后会出现在响应头、访问日志、每个用量事件、控制面的请求日志以及发送到上游的 x-aisix-request-id 请求头中。
# 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"
curl -i "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer $AISIX_API_KEY" \
-H "Content-Type: application/json" \
-H "x-aisix-request-id: req_abc123-orders-svc" \
-d '{
"model": "'"$MODEL_ALIAS"'",
"messages": [
{
"role": "user",
"content": "Hello"
}
]
}'
响应会回显相同的值:
HTTP/1.1 200 OK
x-aisix-request-id: req_abc123-orders-svc
重试和故障转移会在每个用量事件中复用已接受的 ID,因此按该值筛选可以返回完整的尝试链。