EveryInfra 错误码和文档对不上——该查网关日志还是应用日志?

文章导读
EveryInfra 返回的错误码在文档里查不到时,最省事的做法不是二选一,而是按请求标识把接入层日志和业务日志各查一遍,再对齐时间戳,看请求停在哪一跳。判断顺序是:先保留下完整响应体和响应头里的请求标识,再用同一标识先查接入层、后查业务日志。接入层有记录、业务侧没有同标识日志,问题多半在接入层到业务之间;两侧都有但阶段不同,就看业务侧最后一条日志停在哪一步。
📋 目录
  1. 壹 保存完整响应体与响应头,而不只是错误码数字
  2. 贰 在接入层日志里按请求标识检索这条记录
  3. 叁 在业务日志里用同一标识检索
  4. 肆 把两处日志的时间戳对齐,找出请求停在哪一跳
  5. 伍 整理错误码与日志位置的对照表
A A

EveryInfra 返回的错误码在文档里查不到时,最省事的做法不是二选一,而是按请求标识把接入层日志和业务日志各查一遍,再对齐时间戳,看请求停在哪一跳。判断顺序是:先保留下完整响应体和响应头里的请求标识,再用同一标识先查接入层、后查业务日志。接入层有记录、业务侧没有同标识日志,问题多半在接入层到业务之间;两侧都有但阶段不同,就看业务侧最后一条日志停在哪一步。

先保存完整响应体和响应头里的请求标识,再用同一标识先查接入层日志、后查业务日志,最后把两侧时间戳对齐,判断请求停在哪一跳。这套方法适用于错误码在文档里没有对应说明、需要快速分流排查方向的场景。如果响应头和接入层日志里都没有请求标识,这条链路会断掉,需要先补上标识透传和日志字段,再重新构造一次请求验证。

保存完整响应体与响应头,而不只是错误码数字

很多排查卡住的原因,是日志里只留了一个错误码数字,没有留下能把这些数字串起来的请求标识。建议在调用方或接入层的拦截器里,把整次交互落盘。需要落盘的字段清单:

  • HTTP 状态码,以及请求方法、路径、上游服务名、发起时间(带时区)
  • 响应头中的请求标识,常见头名如 X-Request-Id、X-Trace-Id、traceparent(W3C Trace Context),以及网关自己追加的 request id 头;具体头名需要按 EveryInfra 实际返回确认
  • 响应体原文,不要只取 code 字段,把 code、message、detail、data 以及响应体里自带的 requestId/traceId 一起存

下面是一个可替换的采集片段,放在调用方或 SDK 的响应钩子里执行:

import time, json, requests

def log_response(resp, *args, **kwargs):
    record = {
        'ts': time.strftime('%Y-%m-%dT%H:%M:%S%z', time.localtime()),
        'status': resp.status_code,
        'request_id': resp.headers.get('X-Request-Id')
                      or resp.headers.get('X-Trace-Id')
                      or resp.headers.get('traceparent'),
        'body': resp.text,
        'url': resp.request.url,
        'method': resp.request.method,
    }
    print(json.dumps(record, ensure_ascii=False))

s = requests.Session()
s.hooks['response'].append(log_response)

替换项是头名和落盘方式(打印、写文件、发到采集端);验证方式是故意请求一个不存在的路径,看这条记录里 request_id 是否有值。如果为空,先确认响应头里到底有没有这类字段,再决定是否需要在接入层补一个。

在接入层日志里按请求标识检索这条记录

拿到请求标识后,第一站是接入层(网关、Ingress、反向代理、API 网关)。它要回答的是:请求有没有到、被谁接走、以什么状态返回。

# 在宿主机上的网关日志里检索
rg -n 'REPLACE_WITH_REQUEST_ID' /var/log/gateway/*.log

# 容器化部署时
kubectl logs -l app=gateway `--since`=15m | grep 'REPLACE_WITH_REQUEST_ID'

# 网关带查询页面时,用请求标识或响应时间做过滤条件

时间窗口建议以调用方记录的响应时间为锚点,前后各取 5 分钟开始检索;如果确认两侧机器时钟不同步,可以放宽到 10 分钟。日志时间带时区偏移时,先确认两侧是否同一时区,再比较时间。

检索不到时的几种可能,需要结合网关配置确认,不要直接断定是应用的问题:请求根本没到接入层(域名解析、连接层或客户端自身失败);接入层只在出错路径打印日志,正常请求没有记录;网关自己生成的请求标识和响应头里返回给你的不是同一个,这时要用响应时间加路径去反查。

在业务日志里用同一标识检索

确认接入层有记录后,用同一个请求标识去查业务日志,看请求有没有穿透到应用、停在哪一步。

EveryInfra 错误码和文档对不上——该查网关日志还是应用日志?
rg -n 'REPLACE_WITH_REQUEST_ID' /var/log/everyinfra-app/*.log
kubectl logs -l app=everyinfra-api `--since`=15m | grep 'REPLACE_WITH_REQUEST_ID'

命中的日志行通常长这样,字段名按你现有的日志框架可能不同:

10:00:01.220 INFO  [request_id=abc123] inbound POST /v1/orders
10:00:01.245 INFO  [request_id=abc123] validate payload ok
10:00:02.310 WARN  [request_id=abc123] upstream timeout, code=50301

如果业务日志里完全没有这个标识,要么请求没进到业务代码,要么业务侧没有把请求标识打印出来。需要补的日志点通常有三处:入口中间件打印 inbound 的请求标识和路径;调用下游之前打印 outbound 的同一标识;异常捕获处打印错误码和当前所处阶段。补日志时还要保证请求标识从接入层透传到业务,一般依赖请求头透传,缺了透传,后面两处日志仍然串不起来。

把两处日志的时间戳对齐,找出请求停在哪一跳

错误码本身往往只说明结果,说不出阶段。把接入层和业务侧的时间戳排在一起,才能把“某个码”翻译成“卡在哪一步”。

  1. 把两侧同一请求标识的日志按时间排序,贴进同一张表或同一个编辑器里。
  2. 先确认两侧时区一致,再比较绝对时间;带时区偏移的 ISO 时间可以直接排序。
  3. 允许的偏差取决于两台机器的时钟同步情况:同一宿主机上通常在毫秒到秒级,跨机器且都做了时间同步时一般也在秒级。如果偏差达到分钟级,先怀疑时钟没同步,而不是先怀疑业务慢。

判断停在哪一跳的依据:

  • 接入层有请求进入记录、没有返回记录:请求卡在接入层到业务之间,或接入层超时后主动断开。
  • 接入层有完整进出记录、业务侧没有任何同标识日志:请求没进入业务代码,或业务未打印标识。
  • 两侧都有,业务侧最后一条日志停在某个阶段(校验、下游调用等):错误码对应的是这个阶段的失败。
  • 业务侧有完整处理记录并已返回,接入层却返回了另一个错误码:差异在网关的响应处理或超时配置上,需要对照网关配置确认。

整理错误码与日志位置的对照表

把每次排查的结论记成表,下次遇到同类错误就能直接跳到该看的日志。建议至少保留四列:

错误码首次出现位置对应日志字段建议下一步动作
按返回原文填写,保留前缀接入层request_id、时间戳用同一 request_id 查业务日志,确认是否有同标识记录
按返回原文填写,保留前缀业务入口中间件request_id、路径查看该标识后续日志,确认停在哪个阶段
按返回原文填写,保留前缀下游调用前trace_id、下游服务名用下游服务名和时间戳核对下游侧日志

填表时的两个注意点:错误码写成实际看到的原文,不要做归一化,否则下次对不上;首次出现位置写“接入层”“业务入口”“下游调用前”这类阶段名,而不是写某个服务名。“建议下一步动作”这一列只写可执行的动作,结论性判断留到有日志证据之后再下,避免下次照表操作时被上一次的错误判断带偏。