AMR · Production performance / 2026.10.21

CPU 花在了哪里?
大请求体的重复 JSON 处理是首要热点

两台生产 Pod 的 CPU profile 给出一致证据:输入预处理与诊断摘要值得优先优化。当前内存容量有余量,GC 不是本次采样中最大的 CPU 消耗项。

2 × 30s CPU · 1 × 30s 分配增量 · 5 天趋势
两份 CPU 样本:JSON 三个扫描函数 flat 合计
52–55%
stateInString + checkValid + skip
诊断摘要 Summarize 的累计 CPU 占比
≈ 19%
两个 Pod:18.98% / 18.70%
5 天归一化:CPU / 百万总 Token
+26%
1.17 → 1.48 CPU 秒;尚未完成版本归因

01 / 结论与证据边界

优先优化请求体处理,尤其是重复解析和诊断字段提取。
生产 profile 已证明这些函数消耗大量 CPU;具体节省比例必须通过修改后的基准与生产对照验证,不能把热点占比直接当成可节省比例。

已验证

  • 当前更接近 CPU 的 HPA 目标,内存容量没有成为主要约束。
  • 两台 Pod 的 JSON 扫描热点一致,输入准备路径约占 46–50% 的累计 CPU。
  • 诊断摘要会扫描完整请求体;正常 LLM 字段会触发元数据解析的 fallback。
  • 30 秒采样分配约 7.52 GiB,主要来自解码缓冲、RawMessage 复制及协议序列化。

尚未证明

  • 哪次发布造成了过去 5 天单位成本上涨。
  • 上述热点中有多少可以安全消除;本次未实施代码优化。
  • GC 的完整总占比:5.4% 指后台标记路径,不包含所有 GC assist / sweep 成本。
  • 所有模型和流量时段都具有相同热点占比。

02 / CPU 与内存容量

资源快照:北京时间 2026-10-21 20:06,15 个 Pod;CPU 为最近 5 分钟平均。

每 Pod 指标平均使用最高使用HPA 目标硬上限
CPU1.11 核1.24 核1.20 核4 核
内存 working set0.78 GiB1.07 GiB2 GiB4 GiB

CPU 平均使用量约为 HPA 目标的 93%;内存约为目标的 39%。CPU 目标来自 request 1.5 核 × 80%;内存目标来自 request 2 GiB × 100%。HPA 按整体利用率决策,并非某一个 Pod 到达阈值就立即扩容。

当前 throttled period 比例每 Pod 为 0–0.17%。过去 5 天全体 CPU 的 5 分钟均值最高约 22.8 核,throttled period 比例最高约 10.2%(不是损失 CPU 时间占比)。单容器内存观测峰值 2.71 GiB;OOM 原因指标无返回记录,不等同于证明历史从未 OOM。

03 / 最近 5 天:工作量不能完全解释成本增长

10011513010/17: 100.010/18: 107.210/19: 117.810/20: 119.210/21: 122.310/17: 100.010/18: 104.910/19: 112.010/20: 116.410/21: 126.310/1710/1810/1910/2010/21
CPU / LLM 请求 CPU / 总 Token

首个窗口 = 100;悬停圆点查看指数。

请求量 +149%,CPU +205%

单位 LLM 请求 CPU:201 → 246 ms(+22%)。单位总 Token CPU:1.17 → 1.48 秒/百万(+26%)。

单独按输出归一化:189 → 264 秒/百万输出 Token(+40%)。输入 Token 占总量超过 99%,总 TPM 更接近输入侧工作量,但缓存 Token 数仍不等同于实际 JSON 字节数。

窗口结束LLM 请求/s总 TPM / 百万CPU 核CPU ms/请求CPU s/百万 Token内存 GiB分配 MB/请求
10/1721.46220.94.312011.174.3941.6
10/1835.15369.97.572151.236.3847.8
10/1936.47395.08.632371.317.6953.5
10/2031.61333.47.572401.367.0250.0
10/2153.45532.713.132461.4810.4150.6

每行是截至当天 20:06 的前 24 小时。小时级 rate[1h] 取 24 个非重叠窗口,先汇总分子分母再相除;内存为小时快照均值。所有曲线覆盖 121 个点,无缺失。LLM 请求是开始的逻辑模型调用;Token 在结束时记账,窗口边界可能有错位。全体 Link CPU 包含后台工作和非 LLM 开销,因此这是摊销成本,不是独占 LLM 的函数计时。

接口限定 /v1/chat/completions、/v1/responses、/v1/messages。总 Token = input_total + output,input_total 已含缓存读写,未重复叠加子分类。完成请求计数的长窗口查询返回 502,因此采用已验证的 started counter;HTTP LLM 接口计数另行查询作交叉核对。

下载归一化数据

04 / 生产 CPU profile:两台 Pod 交叉验证

版本 f5f2e15a3f0d63229c5e50b9841d333f6ff2d06e;Go build ID a0e9f56ca6f682f9942261fa425ac2ac2557cc95。使用已有 loopback pprof,通过临时端口转发采集;未修改生产配置、未重启 Pod,转发已关闭。

样本Pod 尾缀开始时间(北京时间)时长采样 CPU 时间
A8cb4j20:17:0130 秒28.82 秒(约 0.96 核)
Bj4qk220:18:3830 秒35.66 秒(约 1.19 核)

20:19 附近的 5 分钟指标显示,两台 Pod 约 5.1 / 5.0 LLM 请求/s,输入约 88.2 万 / 81.2 万 Token/s,输出约 4516 / 4508 Token/s。它们是采样附近的流量背景,并非精确 30 秒窗口的计数。

样本 A 样本 B
prepareRequest(含子调用)
45.9% / 49.8%
thinkingdiag.Summarize
19.0% / 18.7%
prepareTargetBody
18.1% / 21.1%
newChatRequest
14.1% / 16.6%
GC 后台标记
5.4% / 5.5%
streamBifrost
4.9% / 3.9%
这些累计占比有父子调用重叠,不能相加。例如 prepareRequest 包含部分 Summarize 和 prepareTargetBody;上方 52–55% 指三个不同函数的 flat 占比之和,可相加。

JSON Unmarshal 累计占比为 52.7% / 55.3%;Decoder.Decode 为 19.3% / 20.6%。这些入口也不应直接相加。相比之下,streamBifrost 约 3.9–4.9%,所以本次证据不支持首先调整流式 Flush。

05 / 三个具体优化方向

消除元数据提取的重复整包解析 优先验证

prepareRequest 的目标结构只有 model、provider_id、stream,却调用 DisallowUnknownFields()。正常请求包含 messages、tools 或 input,于是走 map[string]any fallback,再解析一次全部内容。

源码行级 profile:A 的第一次解码 2.17s,fallback 1.80s;合计 13.8%。B 分别为 2.60s、2.07s;合计 13.1%。这是整条双解析路径的成本,不能假设全部都可消除。

方向:一次提取所需元数据,避免为无关 messages/tools 构造通用对象树。必须保留字段类型、重复键、null、非法 JSON、尾随内容与错误响应的兼容语义;不能仅删一行后直接上线。

生产版本源码 · handlers/openai.go:1489–1506

诊断摘要复用字段,减少大字段扫描与复制 ≈19% CPU

thinkingdiag.Summarize 为读取少量 thinking/reasoning 控制字段,将整个 body 解码成 map[string]json.RawMessage。RawMessage 避免构建全部对象树,但仍需扫描并复制大字段。Inbound、Normalized、Outbound 会重复执行这一工作。

CPU 为 19.0% / 18.7%;分配增量约 605 MiB(7.86%)。方向:复用已有解析结果,或者只提取白名单字段;避免为了诊断复制 messages/tools。若采用采样,需明确丢失哪些诊断覆盖,不能静默削弱错误分析能力。

生产版本源码 · thinkingdiag/summary.go:36 · collector.go:34

合并请求规范化与适配步骤 后续结构优化

prepareTargetBody 累计 CPU 18–21%,newChatRequest 14–17%。分配 profile 中,两条路径各占约 17.7%(与其它累计路径存在重叠)。

方向:共享解析后的请求表示,合并 reasoning/default/compatibility 处理,在必要边界才序列化。优先修改 Link internal;若确需改 vendored Bifrost,按仓库要求记录补丁原因、验证和维护方案。

不要首先用增大 GOMEMLIMIT、放宽 HPA 或全局替换 JSON 库代替消除重复工作。

06 / 分配证据与验证计划

Pod A 的 allocs?seconds=30 增量 profile:实际时长 30.17 秒,采样估算分配约 7.52 GiB,约 255 MiB/s。这是累计分配量,不是活跃 heap,也不代表泄漏。分配数据有采样误差与 GC 记账滞后。

直接分配位置(flat)分配占比
encoding/json.Decoder.refill19.53%
json.RawMessage.UnmarshalJSON15.90%
sonic.frozenConfig.Unmarshal12.41%
sonic EncodeJsonMarshaler7.37%
bytes.growSlice6.81%
io.ReadAll6.09%
  1. 构造不同体积的合成请求:小请求、长上下文、工具 schema、Responses/Messages,建立处理吞吐与 allocs/op 基线。
  2. 先修复元数据双解析和诊断摘要重复扫描;分别测试,确认 CPU/op、bytes/op 改善。
  3. 验证错误语义、reasoning 转换、工具调用、流式中断、计费结果和诊断白名单保持正确。
  4. 用同版本、同模型构成、相近请求大小的对照流量验证 CPU/请求、CPU/输入字节、TTFT、错误率及分配率,再评估容量收益。
本次 profile 来自 20:07 后创建的新版本 Pod;5 天趋势跨多个版本。证据能够定位当前热点,尚不能把 +26% 的历史单位成本增长归因到某次提交。缺少旧版本同负载 profile、请求字节/chunk 分布和受控 A/B,是当前归因边界。

附录 / 可复核证据

源码分析已使用生产镜像对应提交,而非工作区未提交版本。以下是符号化摘要,不包含请求内容、凭据或原始 heap 转储。CPU 占比均相对于对应样本总 CPU 时间。

CPU 样本 A · flat 排名
File: gateway
Build ID: a0e9f56ca6f682f9942261fa425ac2ac2557cc95
Type: cpu
Time: 2026-10-21 20:17:01 CST
Duration: 30s, Total samples = 28.82s (96.06%)
Showing nodes accounting for 24.46s, 84.87% of 28.82s total
Dropped 746 nodes (cum <= 0.14s)
      flat  flat%   sum%        cum   cum%
     5.48s 19.01% 19.01%      5.52s 19.15%  encoding/json.stateInString
     5.04s 17.49% 36.50%      6.93s 24.05%  encoding/json.checkValid
     4.58s 15.89% 52.39%      7.48s 25.95%  encoding/json.(*decodeState).skip
     1.78s  6.18% 58.57%      3.34s 11.59%  encoding/json.(*Decoder).readValue
     1.58s  5.48% 64.05%      1.58s  5.48%  internal/runtime/syscall/linux.Syscall6
     1.32s  4.58% 68.63%      1.32s  4.58%  runtime.memmove
     0.61s  2.12% 70.75%      1.01s  3.50%  encoding/json.unquoteBytes
     0.49s  1.70% 72.45%      0.49s  1.70%  runtime.memclrNoHeapPointers
     0.38s  1.32% 73.77%      0.38s  1.32%  runtime.futex
     0.37s  1.28% 75.05%      0.40s  1.39%  encoding/json.(*decodeState).rescanLiteral
     0.34s  1.18% 76.23%      0.60s  2.08%  encoding/json.appendCompact
     0.25s  0.87% 77.10%      0.25s  0.87%  runtime.madvise
     0.24s  0.83% 77.93%      0.27s  0.94%  unicode/utf8.DecodeRune (inline)
     0.16s  0.56% 78.49%      0.28s  0.97%  runtime.tryDeferToSpanScan
     0.15s  0.52% 79.01%      0.21s  0.73%  encoding/json.stateInStringEsc
     0.15s  0.52% 79.53%      0.26s   0.9%  runtime.scanObjectsSmall
     0.13s  0.45% 79.98%      0.26s   0.9%  encoding/json.stateEndValue
     0.13s  0.45% 80.43%      0.20s  0.69%  runtime.(*unwinder).resolveInternal
     0.11s  0.38% 80.81%      0.70s  2.43%  encoding/json.structEncoder.encode
     0.10s  0.35% 81.16%      0.19s  0.66%  runtime.pcvalue
     0.06s  0.21% 81.37%      1.03s  3.57%  decode_
     0.06s  0.21% 81.58%      0.19s  0.66%  runtime.mapassign_faststr
     0.06s  0.21% 81.78%      0.77s  2.67%  runtime.markroot
     0.06s  0.21% 81.99%      0.15s  0.52%  runtime.wbBufFlush1
     0.05s  0.17% 82.17%      0.49s  1.70%  runtime.mallocgcSmallScanNoHeader
     0.05s  0.17% 82.34%      0.23s   0.8%  runtime.scanObject
     0.05s  0.17% 82.51%      0.16s  0.56%  runtime.scanblock
     0.04s  0.14% 82.65%      0.29s  1.01%  runtime.mallocgcSmallNoscan
     0.03s   0.1% 82.76%      1.19s  4.13%  runtime.mallocgc
     0.03s   0.1% 82.86%      0.40s  1.39%  runtime.scanSpan
     0.03s   0.1% 82.96%      0.29s  1.01%  runtime.selectgo
     0.02s 0.069% 83.03%      0.59s  2.05%  encode_struct { *openai.Alias; Messages [...]schemas.ChatTool "json:\"tools,omitempty\""; Reasoning *schemas.ChatReasoning "json:\"reasoning,omitempty\""; ReasoningEffort *string "json:\"reasoning_effort,omitempty\"" }
     0.02s 0.069% 83.10%      0.16s  0.56%  gcWriteBarrier
     0.02s 0.069% 83.17%      1.41s  4.89%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).streamBifrost
     0.02s 0.069% 83.24%      0.25s  0.87%  runtime.(*mcache).refill
     0.02s 0.069% 83.31%      0.18s  0.62%  runtime.(*mcentral).cacheSpan
     0.02s 0.069% 83.38%      0.58s  2.01%  runtime.findRunnable
     0.02s 0.069% 83.45%      0.36s  1.25%  runtime.makeslice
     0.02s 0.069% 83.52%      0.31s  1.08%  runtime.netpoll
     0.02s 0.069% 83.59%      0.25s  0.87%  runtime.newobject
     0.02s 0.069% 83.66%      0.64s  2.22%  runtime.scanstack
     0.02s 0.069% 83.73%      0.64s  2.22%  runtime.schedule
     0.02s 0.069% 83.80%      0.51s  1.77%  runtime.slicebytetostring
     0.01s 0.035% 83.83%      0.63s  2.19%  bytes.(*Buffer).ReadFrom
     0.01s 0.035% 83.87%      0.16s  0.56%  bytes.(*Buffer).grow
     0.01s 0.035% 83.90%      0.71s  2.46%  crypto/tls.(*Conn).Read
     0.01s 0.035% 83.93%      0.68s  2.36%  crypto/tls.(*Conn).readRecordOrCCS
     0.01s 0.035% 83.97%      0.42s  1.46%  encode_schemas.Alias
     0.01s 0.035% 84.00%      0.52s  1.80%  encode_schemas.ChatToolFunction
     0.01s 0.035% 84.04%      0.25s  0.87%  encoding/json.(*Decoder).Token
     0.01s 0.035% 84.07%      1.69s  5.86%  encoding/json.(*decodeState).arrayInterface
     0.01s 0.035% 84.11%      0.97s  3.37%  github.com/bytedance/sonic.frozenConfig.Marshal
     0.01s 0.035% 84.14%      1.06s  3.68%  github.com/bytedance/sonic/internal/decoder/api.(*Decoder).Decode
     0.01s 0.035% 84.18%      1.06s  3.68%  github.com/bytedance/sonic/internal/decoder/jitdec.Decode
     0.01s 0.035% 84.21%      0.82s  2.85%  github.com/bytedance/sonic/internal/decoder/jitdec.decodeJsonUnmarshaler
     0.01s 0.035% 84.25%      1.04s  3.61%  github.com/bytedance/sonic/internal/decoder/jitdec.decodeTypedPointer
     0.01s 0.035% 84.28%      0.77s  2.67%  github.com/go-chi/chi/v5/middleware.(*httpFancyWriter).Flush
     0.01s 0.035% 84.32%      1.62s  5.62%  github.com/maximhq/bifrost/core/providers/openai.HandleOpenAIChatCompletionStreaming.func2
     0.01s 0.035% 84.35%      0.31s  1.08%  github.com/maximhq/bifrost/core/providers/utils.ProcessAndSendResponse
     0.01s 0.035% 84.39%      0.80s  2.78%  internal/poll.(*FD).Write
     0.01s 0.035% 84.42%      0.81s  2.81%  net.(*conn).Write
     0.01s 0.035% 84.46%      0.69s  2.39%  net/http/internal.(*chunkedReader).Read
     0.01s 0.035% 84.49%      0.28s  0.97%  runtime.(*mcache).nextFree
     0.01s 0.035% 84.52%      0.17s  0.59%  runtime.(*unwinder).next
     0.01s 0.035% 84.56%      0.29s  1.01%  runtime.futexwakeup
     0.01s 0.035% 84.59%      0.37s  1.28%  runtime.growslice
     0.01s 0.035% 84.63%      0.70s  2.43%  runtime.markroot.func1
     0.01s 0.035% 84.66%      0.30s  1.04%  runtime.notewakeup
     0.01s 0.035% 84.70%      0.63s  2.19%  runtime.park_m
     0.01s 0.035% 84.73%      0.19s  0.66%  runtime.ready
     0.01s 0.035% 84.77%      0.26s   0.9%  runtime.scanframeworker
     0.01s 0.035% 84.80%      0.22s  0.76%  runtime.startm
     0.01s 0.035% 84.84%      0.17s  0.59%  runtime.stealWork
     0.01s 0.035% 84.87%      1.30s  4.51%  syscall.RawSyscall6
         0     0% 84.87%      0.68s  2.36%  bufio.(*Reader).ReadSlice
         0     0% 84.87%      0.68s  2.36%  bufio.(*Reader).fill
         0     0% 84.87%      0.72s  2.50%  bufio.(*Scanner).Scan
         0     0% 84.87%      0.79s  2.74%  bufio.(*Writer).Flush
         0     0% 84.87%      0.63s  2.19%  crypto/tls.(*Conn).readFromUntil
         0     0% 84.87%      0.68s  2.36%  crypto/tls.(*Conn).readRecord (inline)
         0     0% 84.87%      0.62s  2.15%  crypto/tls.(*atLeastReader).Read
         0     0% 84.87%      0.52s  1.80%  encode_*schemas.Alias
         0     0% 84.87%      0.34s  1.18%  encode_*schemas.OrderedMap
         0     0% 84.87%      5.57s 19.33%  encoding/json.(*Decoder).Decode
         0     0% 84.87%      0.44s  1.53%  encoding/json.(*Decoder).refill
         0     0% 84.87%      0.39s  1.35%  encoding/json.(*RawMessage).UnmarshalJSON
         0     0% 84.87%      7.97s 27.65%  encoding/json.(*decodeState).array
         0     0% 84.87%      1.46s  5.07%  encoding/json.(*decodeState).literalInterface
         0     0% 84.87%      9.78s 33.93%  encoding/json.(*decodeState).object
         0     0% 84.87%      1.66s  5.76%  encoding/json.(*decodeState).objectInterface
         0     0% 84.87%     10.45s 36.26%  encoding/json.(*decodeState).unmarshal
         0     0% 84.87%     10.45s 36.26%  encoding/json.(*decodeState).value
         0     0% 84.87%      1.66s  5.76%  encoding/json.(*decodeState).valueInterface
         0     0% 84.87%      0.98s  3.40%  encoding/json.(*encodeState).marshal
         0     0% 84.87%      0.97s  3.37%  encoding/json.(*encodeState).reflectValue
         0     0% 84.87%      0.28s  0.97%  encoding/json.Compact
         0     0% 84.87%      1.05s  3.64%  encoding/json.Marshal
         0     0% 84.87%     15.19s 52.71%  encoding/json.Unmarshal
         0     0% 84.87%      0.43s  1.49%  encoding/json.addrMarshalerEncoder
         0     0% 84.87%      0.63s  2.19%  encoding/json.arrayEncoder.encode
         0     0% 84.87%      0.61s  2.12%  encoding/json.condAddrEncoder.encode
         0     0% 84.87%      0.26s   0.9%  encoding/json.mapEncoder.encode
         0     0% 84.87%      0.25s  0.87%  encoding/json.marshalerEncoder
         0     0% 84.87%      0.24s  0.83%  encoding/json.ptrEncoder.encode
         0     0% 84.87%      0.63s  2.19%  encoding/json.sliceEncoder.encode
         0     0% 84.87%      1.09s  3.78%  encoding/json.unquote (inline)
         0     0% 84.87%         1s  3.47%  github.com/bytedance/sonic.Unmarshal (inline)
         0     0% 84.87%      0.39s  1.35%  github.com/bytedance/sonic.UnmarshalString (inline)
         0     0% 84.87%         1s  3.47%  github.com/bytedance/sonic.frozenConfig.Unmarshal
         0     0% 84.87%      1.07s  3.71%  github.com/bytedance/sonic.frozenConfig.UnmarshalFromString
         0     0% 84.87%      0.97s  3.37%  github.com/bytedance/sonic/internal/encoder.Encode
         0     0% 84.87%      0.96s  3.33%  github.com/bytedance/sonic/internal/encoder.encodeInto
         0     0% 84.87%      0.96s  3.33%  github.com/bytedance/sonic/internal/encoder.encodeIntoCheckRace (inline)
         0     0% 84.87%      0.28s  0.97%  github.com/bytedance/sonic/internal/encoder/prim.Compact
         0     0% 84.87%      0.81s  2.81%  github.com/bytedance/sonic/internal/encoder/prim.EncodeJsonMarshaler
         0     0% 84.87%      0.96s  3.33%  github.com/bytedance/sonic/internal/encoder/x86.EncodeTypedPointer
         0     0% 84.87%     15.15s 52.57%  github.com/go-chi/chi/v5.(*ChainHandler).ServeHTTP
         0     0% 84.87%     15.15s 52.57%  github.com/go-chi/chi/v5.(*Mux).Mount.func1
         0     0% 84.87%     15.18s 52.67%  github.com/go-chi/chi/v5.(*Mux).ServeHTTP
         0     0% 84.87%     15.16s 52.60%  github.com/go-chi/chi/v5.(*Mux).routeHTTP
         0     0% 84.87%     15.13s 52.50%  github.com/go-chi/chi/v5/middleware.RealIP.func1
         0     0% 84.87%     15.15s 52.57%  github.com/go-chi/chi/v5/middleware.Recoverer.func1
         0     0% 84.87%     15.13s 52.50%  github.com/go-chi/chi/v5/middleware.RequestID.func1
         0     0% 84.87%      4.06s 14.09%  github.com/maximhq/bifrost/core.(*Bifrost).handleProviderStreamRequest
         0     0% 84.87%      4.15s 14.40%  github.com/maximhq/bifrost/core.(*Bifrost).requestWorker
         0     0% 84.87%      4.05s 14.05%  github.com/maximhq/bifrost/core.(*Bifrost).requestWorker.func3
         0     0% 84.87%      4.06s 14.09%  github.com/maximhq/bifrost/core.executeRequestWithRetries[go.shape.chan *github.com/maximhq/bifrost/core/schemas.BifrostStreamChunk]
         0     0% 84.87%      0.57s  1.98%  github.com/maximhq/bifrost/core/providers/openai.(*OpenAIChatRequest).MarshalJSON
         0     0% 84.87%      0.64s  2.22%  github.com/maximhq/bifrost/core/providers/openai.(*OpenAIChatRequest).UnmarshalJSON
         0     0% 84.87%      3.99s 13.84%  github.com/maximhq/bifrost/core/providers/openai.(*OpenAIProvider).ChatCompletionStream
         0     0% 84.87%      4.08s 14.16%  github.com/maximhq/bifrost/core/providers/openai.HandleOpenAIChatCompletionStreaming
         0     0% 84.87%      1.86s  6.45%  github.com/maximhq/bifrost/core/providers/openai.doOpenAICompatibleStreamingRequest
         0     0% 84.87%      0.69s  2.39%  github.com/maximhq/bifrost/core/providers/utils.(*chunkedBody).Read
         0     0% 84.87%      0.76s  2.64%  github.com/maximhq/bifrost/core/providers/utils.(*defaultSSEDataReader).ReadDataLine
         0     0% 84.87%      0.71s  2.46%  github.com/maximhq/bifrost/core/providers/utils.(*idleTimeoutReader).Read
         0     0% 84.87%      0.69s  2.39%  github.com/maximhq/bifrost/core/providers/utils.(*streamBody).Read
         0     0% 84.87%      2.25s  7.81%  github.com/maximhq/bifrost/core/providers/utils.CheckContextAndGetRequestBody
         0     0% 84.87%      1.86s  6.45%  github.com/maximhq/bifrost/core/providers/utils.DoStreamingRequest
         0     0% 84.87%      0.56s  1.94%  github.com/maximhq/bifrost/core/providers/utils.MarshalProviderRequest
         0     0% 84.87%      0.58s  2.01%  github.com/maximhq/bifrost/core/providers/utils.MarshalSorted (inline)
         0     0% 84.87%      1.65s  5.73%  github.com/maximhq/bifrost/core/providers/utils.MergeExtraParamsIntoJSON
         0     0% 84.87%      0.16s  0.56%  github.com/maximhq/bifrost/core/schemas.(*BifrostContext).Value
         0     0% 84.87%      0.37s  1.28%  github.com/maximhq/bifrost/core/schemas.(*ChatParameters).UnmarshalJSON
         0     0% 84.87%      0.20s  0.69%  github.com/maximhq/bifrost/core/schemas.(*ChatStreamResponseChoiceDelta).UnmarshalJSON
         0     0% 84.87%      0.29s  1.01%  github.com/maximhq/bifrost/core/schemas.(*ChatTool).UnmarshalJSON
         0     0% 84.87%      0.15s  0.52%  github.com/maximhq/bifrost/core/schemas.(*OrderedMap).UnmarshalJSON
         0     0% 84.87%      0.28s  0.97%  github.com/maximhq/bifrost/core/schemas.(*ToolFunctionParameters).UnmarshalJSON
         0     0% 84.87%      0.54s  1.87%  github.com/maximhq/bifrost/core/schemas.ChatTool.MarshalJSON
         0     0% 84.87%      0.71s  2.46%  github.com/maximhq/bifrost/core/schemas.MarshalSorted (inline)
         0     0% 84.87%      1.83s  6.35%  github.com/maximhq/bifrost/core/schemas.ObserveProviderRequestBody
         0     0% 84.87%      0.37s  1.28%  github.com/maximhq/bifrost/core/schemas.OrderedMap.MarshalJSON
         0     0% 84.87%      0.48s  1.67%  github.com/maximhq/bifrost/core/schemas.ToolFunctionParameters.MarshalJSON
         0     0% 84.87%      0.77s  2.67%  github.com/maximhq/bifrost/core/schemas.Unmarshal (inline)
         0     0% 84.87%      0.15s  0.52%  github.com/maximhq/bifrost/core/schemas.normalizeSingleReasoningDetails
         0     0% 84.87%      4.06s 14.09%  github.com/nexu-io/vela/services/link/internal/bifrostengine.(*BifrostEngine).ChatCompletionStream
         0     0% 84.87%      0.19s  0.66%  github.com/nexu-io/vela/services/link/internal/bifrostengine.(*BifrostEngine).MessagesStream
         0     0% 84.87%      0.17s  0.59%  github.com/nexu-io/vela/services/link/internal/bifrostengine.(*BifrostEngine).Responses
         0     0% 84.87%      0.48s  1.67%  github.com/nexu-io/vela/services/link/internal/bifrostengine.(*BifrostEngine).ResponsesStream
         0     0% 84.87%      0.53s  1.84%  github.com/nexu-io/vela/services/link/internal/bifrostengine.enablePromptCachingChat
         0     0% 84.87%      0.15s  0.52%  github.com/nexu-io/vela/services/link/internal/bifrostengine.enablePromptCachingResponses
         0     0% 84.87%      4.07s 14.12%  github.com/nexu-io/vela/services/link/internal/bifrostengine.newChatRequest
         0     0% 84.87%      0.64s  2.22%  github.com/nexu-io/vela/services/link/internal/bifrostengine.newResponsesRequest
         0     0% 84.87%      0.16s  0.56%  github.com/nexu-io/vela/services/link/internal/bifrostengine.normalizeChatReasoningAlias
         0     0% 84.87%      0.37s  1.28%  github.com/nexu-io/vela/services/link/internal/bifrostengine.normalizeChatStop
         0     0% 84.87%      0.68s  2.36%  github.com/nexu-io/vela/services/link/internal/bifrostengine.promptCacheKey
         0     0% 84.87%      1.06s  3.68%  github.com/nexu-io/vela/services/link/internal/bifrostengine.validateDeepSeekChatCustomTools
         0     0% 84.87%      0.16s  0.56%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).admitProviderRequest
         0     0% 84.87%     11.74s 40.74%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).handleChatCompletions
         0     0% 84.87%      4.06s 14.09%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).handleChatCompletions.func1
         0     0% 84.87%      0.49s  1.70%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).handleMessages
         0     0% 84.87%      2.83s  9.82%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).handleResponses
         0     0% 84.87%      0.48s  1.67%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).handleResponses.func1
         0     0% 84.87%     13.24s 45.94%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).prepareRequest
         0     0% 84.87%      0.19s  0.66%  github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).streamAnthropicMessages.func1
         0     0% 84.87%      0.16s  0.56%  github.com/nexu-io/vela/services/link/internal/handlers.(*admissionPipeline).Admit
         0     0% 84.87%      1.89s  6.56%  github.com/nexu-io/vela/services/link/internal/handlers.applyPublicModelReasoningEffort
         0     0% 84.87%      4.73s 16.41%  github.com/nexu-io/vela/services/link/internal/handlers.awaitStreamEstablishment[go.shape.*uint8].func1
         0     0% 84.87%      1.58s  5.48%  github.com/nexu-io/vela/services/link/internal/handlers.normalizeRequestBody
         0     0% 84.87%      5.23s 18.15%  github.com/nexu-io/vela/services/link/internal/handlers.prepareTargetBody
         0     0% 84.87%      0.25s  0.87%  github.com/nexu-io/vela/services/link/internal/handlers.requestLogSummary
         0     0% 84.87%      1.76s  6.11%  github.com/nexu-io/vela/services/link/internal/providercompat.Adapter.PrepareDefaultReasoning
         0     0% 84.87%      4.06s 14.09%  github.com/nexu-io/vela/services/link/internal/runtimeconfig.(*leasedEngine).ChatCompletionStream
         0     0% 84.87%      0.19s  0.66%  github.com/nexu-io/vela/services/link/internal/runtimeconfig.(*leasedEngine).MessagesStream
         0     0% 84.87%      0.17s  0.59%  github.com/nexu-io/vela/services/link/internal/runtimeconfig.(*leasedEngine).Responses
         0     0% 84.87%      0.48s  1.67%  github.com/nexu-io/vela/services/link/internal/runtimeconfig.(*leasedEngine).ResponsesStream
         0     0% 84.87%     15.13s 52.50%  github.com/nexu-io/vela/services/link/internal/server.newRouter.ServerRequestMiddleware.func5.1
         0     0% 84.87%     15.16s 52.60%  github.com/nexu-io/vela/services/link/internal/server.newRouter.Timeout.func6.1
         0     0% 84.87%     15.16s 52.60%  github.com/nexu-io/vela/services/link/internal/server.newRouter.accessLog.func7.1
         0     0% 84.87%     15.15s 52.57%  github.com/nexu-io/vela/services/link/internal/server.newRouter.func3.Auth.1.1
         0     0% 84.87%     15.08s 52.32%  github.com/nexu-io/vela/services/link/internal/server.newRouter.func3.metrics.2.1
         0     0% 84.87%     15.16s 52.60%  github.com/nexu-io/vela/services/link/internal/server.newRouter.rejectNewRequestsWhileDraining.func8.1
         0     0% 84.87%     15.10s 52.39%  github.com/nexu-io/vela/services/link/internal/server.normalizeClientRequestID.func1
         0     0% 84.87%      1.76s  6.11%  github.com/nexu-io/vela/services/link/internal/thinkingdiag.(*Collector).Normalized
         0     0% 84.87%      1.83s  6.35%  github.com/nexu-io/vela/services/link/internal/thinkingdiag.(*Collector).ObserveProviderRequestBody
         0     0% 84.87%      1.87s  6.49%  github.com/nexu-io/vela/services/link/internal/thinkingdiag.New
         0     0% 84.87%      5.47s 18.98%  github.com/nexu-io/vela/services/link/internal/thinkingdiag.Summarize
         0     0% 84.87%      0.66s  2.29%  internal/poll.(*FD).Read
         0     0% 84.87%      1.43s  4.96%  internal/poll.ignoringEINTRIO (inline)
         0     0% 84.87%      0.29s  1.01%  internal/runtime/syscall/linux.EpollWait
         0     0% 84.87%      0.66s  2.29%  net.(*conn).Read
         0     0% 84.87%      0.66s  2.29%  net.(*netFD).Read
         0     0% 84.87%      0.80s  2.78%  net.(*netFD).Write
         0     0% 84.87%      0.76s  2.64%  net/http.(*chunkWriter).flush
         0     0% 84.87%     15.03s 52.15%  net/http.(*conn).serve
         0     0% 84.87%      0.76s  2.64%  net/http.(*response).Flush
         0     0% 84.87%      0.76s  2.64%  net/http.(*response).FlushError
         0     0% 84.87%     15.18s 52.67%  net/http.HandlerFunc.ServeHTTP
         0     0% 84.87%      0.76s  2.64%  net/http.checkConnErrorWriter.Write
         0     0% 84.87%     15.03s 52.15%  net/http.serverHandler.ServeHTTP
         0     0% 84.87%      0.68s  2.36%  net/http/internal.(*chunkedReader).beginChunk
         0     0% 84.87%      0.68s  2.36%  net/http/internal.readChunkLine
         0     0% 84.87%      0.27s  0.94%  runtime.(*pageAlloc).scavenge
         0     0% 84.87%      0.27s  0.94%  runtime.(*pageAlloc).scavenge.func1
         0     0% 84.87%      0.27s  0.94%  runtime.(*pageAlloc).scavengeOne
         0     0% 84.87%      0.27s  0.94%  runtime.(*scavengerState).init.func2
         0     0% 84.87%      0.27s  0.94%  runtime.(*scavengerState).run
         0     0% 84.87%      0.27s  0.94%  runtime.bgscavenge
         0     0% 84.87%      1.56s  5.41%  runtime.gcBgMarkWorker
         0     0% 84.87%      1.51s  5.24%  runtime.gcBgMarkWorker.func2
         0     0% 84.87%      1.51s  5.24%  runtime.gcDrain
         0     0% 84.87%      0.73s  2.53%  runtime.gcDrainMarkWorkerDedicated (inline)
         0     0% 84.87%      0.78s  2.71%  runtime.gcDrainMarkWorkerIdle (inline)
         0     0% 84.87%      0.19s  0.66%  runtime.goready (inline)
         0     0% 84.87%      0.28s  0.97%  runtime.mallocgcLarge
         0     0% 84.87%      0.67s  2.32%  runtime.mcall
         0     0% 84.87%      0.17s  0.59%  runtime.memclrNoHeapPointersChunked
         0     0% 84.87%      0.15s  0.52%  runtime.send
         0     0% 84.87%      0.25s  0.87%  runtime.sysUnused (inline)
         0     0% 84.87%      0.25s  0.87%  runtime.sysUnusedOS
         0     0% 84.87%      2.52s  8.74%  runtime.systemstack
         0     0% 84.87%      0.23s   0.8%  runtime.wakep
         0     0% 84.87%      0.15s  0.52%  runtime.wbBufFlush
         0     0% 84.87%      0.15s  0.52%  runtime.wbBufFlush.func1
         0     0% 84.87%      0.64s  2.22%  syscall.Read (inline)
         0     0% 84.87%      1.43s  4.96%  syscall.Syscall
         0     0% 84.87%      0.79s  2.74%  syscall.Write (inline)
         0     0% 84.87%      0.64s  2.22%  syscall.read
         0     0% 84.87%      0.79s  2.74%  syscall.write
CPU 样本 B · flat 排名
File: gateway
Build ID: a0e9f56ca6f682f9942261fa425ac2ac2557cc95
Type: cpu
Time: 2026-10-21 20:18:38 CST
Duration: 30s, Total samples = 35.66s (118.86%)
Showing nodes accounting for 30.19s, 84.66% of 35.66s total
Dropped 737 nodes (cum <= 0.18s)
Showing top 20 nodes out of 218
      flat  flat%   sum%        cum   cum%
     7.51s 21.06% 21.06%      7.58s 21.26%  encoding/json.stateInString
     6.31s 17.69% 38.75%      9.11s 25.55%  encoding/json.checkValid
     5.85s 16.40% 55.16%      9.98s 27.99%  encoding/json.(*decodeState).skip
     2.52s  7.07% 62.23%      4.24s 11.89%  encoding/json.(*Decoder).readValue
     1.68s  4.71% 66.94%      1.68s  4.71%  internal/runtime/syscall/linux.Syscall6
     1.32s  3.70% 70.64%      1.32s  3.70%  runtime.memmove
     0.98s  2.75% 73.39%      1.54s  4.32%  encoding/json.unquoteBytes
     0.80s  2.24% 75.63%      1.01s  2.83%  encoding/json.appendCompact
     0.64s  1.79% 77.43%      0.64s  1.79%  runtime.memclrNoHeapPointers
     0.51s  1.43% 78.86%      0.53s  1.49%  encoding/json.(*decodeState).rescanLiteral
     0.44s  1.23% 80.09%      0.47s  1.32%  unicode/utf8.DecodeRune (inline)
     0.32s   0.9% 80.99%      0.53s  1.49%  runtime.tryDeferToSpanScan
     0.27s  0.76% 81.74%      0.29s  0.81%  encoding/json.stateInStringEsc
     0.24s  0.67% 82.42%      0.24s  0.67%  runtime.futex
     0.22s  0.62% 83.03%      0.22s  0.62%  runtime.madvise
     0.18s   0.5% 83.54%      0.30s  0.84%  runtime.(*unwinder).resolveInternal
     0.12s  0.34% 83.88%      0.40s  1.12%  runtime.scanObjectsSmall
     0.10s  0.28% 84.16%      0.30s  0.84%  encoding/json.stateEndValue
     0.09s  0.25% 84.41%      1.02s  2.86%  decode_
     0.09s  0.25% 84.66%      0.29s  0.81%  runtime.selectgo
30 秒分配增量 · alloc_space
File: gateway
Build ID: a0e9f56ca6f682f9942261fa425ac2ac2557cc95
Type: alloc_space
Time: 2026-10-21 20:18:22 CST
Duration: 30.17s, Total samples = 7702.92MB 
Showing nodes accounting for 7309.14MB, 94.89% of 7702.92MB total
Dropped 493 nodes (cum <= 38.51MB)
Showing top 25 nodes out of 151
      flat  flat%   sum%        cum   cum%
 1504.54MB 19.53% 19.53%  1507.08MB 19.57%  encoding/json.(*Decoder).refill
 1225.07MB 15.90% 35.44%  1225.07MB 15.90%  encoding/json.(*RawMessage).UnmarshalJSON
  955.88MB 12.41% 47.85%  1343.75MB 17.44%  github.com/bytedance/sonic.frozenConfig.Unmarshal
  567.55MB  7.37% 55.21%  1007.31MB 13.08%  github.com/bytedance/sonic/internal/encoder/prim.EncodeJsonMarshaler
  524.55MB  6.81% 62.02%   524.55MB  6.81%  bytes.growSlice
  469.18MB  6.09% 68.11%   469.18MB  6.09%  io.ReadAll
  414.51MB  5.38% 73.50%      648MB  8.41%  encoding/json.unquote (inline)
  300.71MB  3.90% 77.40%   300.71MB  3.90%  github.com/bytedance/sonic/internal/rt.GrowSlice
  233.49MB  3.03% 80.43%   233.49MB  3.03%  encoding/json.unquoteBytes
  212.89MB  2.76% 83.19%   212.89MB  2.76%  github.com/bytedance/gopkg/lang/dirtmake.Bytes
  164.91MB  2.14% 85.34%   976.11MB 12.67%  decode_
  155.54MB  2.02% 87.35%   830.04MB 10.78%  encoding/json.(*decodeState).objectInterface
  136.39MB  1.77% 89.12%   136.39MB  1.77%  github.com/valyala/bytebufferpool.(*ByteBuffer).Set
  125.74MB  1.63% 90.76%   305.47MB  3.97%  encoding/json.Marshal
   91.04MB  1.18% 91.94%   316.65MB  4.11%  github.com/maximhq/bifrost/core/providers/openai.HandleOpenAIChatCompletionStreaming.func2
      57MB  0.74% 92.68%    71.50MB  0.93%  encoding/json.(*scanner).error (inline)
   46.03MB   0.6% 93.28%    46.03MB   0.6%  decode_value
   41.02MB  0.53% 93.81%    41.02MB  0.53%  github.com/maximhq/bifrost/core/providers/utils.GetBifrostResponseForStreamResponse (inline)
      18MB  0.23% 94.04%   118.52MB  1.54%  encoding/json.(*Decoder).Token
   15.50MB   0.2% 94.24%   119.57MB  1.55%  github.com/maximhq/bifrost/core/schemas.(*ChatStreamResponseChoiceDelta).UnmarshalJSON
   14.08MB  0.18% 94.43%   835.12MB 10.84%  encoding/json.(*decodeState).arrayInterface
      14MB  0.18% 94.61%   652.50MB  8.47%  encoding/json.(*decodeState).literalInterface
    9.50MB  0.12% 94.73%   534.05MB  6.93%  bytes.(*Buffer).grow
       7MB 0.091% 94.82%    65.99MB  0.86%  encoding/json.mapEncoder.encode
       5MB 0.065% 94.89%  1134.29MB 14.73%  github.com/bytedance/sonic/internal/encoder.encodeInto
源码行级归因 · prepareRequest
Total: 28.82s
ROUTINE ======================== github.com/nexu-io/vela/services/link/internal/handlers.(*OpenAIHandler).prepareRequest in internal/handlers/openai.go
         0     13.24s (flat, cum) 45.94% of Total
         .          .   1464:func (h *OpenAIHandler) prepareRequest(runtime *catalog.Runtime, endpoint string, r *http.Request) ([]byte, requestMeta, domain.Principal, domain.ResolvedModel, *requestError) {
         .          .   1465:	correlationRequestID, _ := requestcorrelation.ClientRequestID(r.Header.Get(requestIDHeader))
         .          .   1466:	requestID := correlationRequestID
         .          .   1467:	if requestID == "" {
         .          .   1468:		requestID = uuid.NewString()
         .          .   1469:	}
         .          .   1470:	meta := requestMeta{RequestID: requestID, ExecutionID: uuid.NewString(), CorrelationRequestID: correlationRequestID, Endpoint: endpoint}
         .          .   1471:
         .          .   1472:	principal, ok := requestctx.PrincipalFromContext(r.Context())
         .          .   1473:	if !ok {
         .          .   1474:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusInternalServerError, code: "internal_error", message: "missing authenticated principal"}
         .          .   1475:	}
         .          .   1476:
         .      140ms   1477:	body, err := io.ReadAll(io.LimitReader(r.Body, h.maxRequestBodyBytes+1))
         .          .   1478:	if err != nil {
         .          .   1479:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusBadRequest, code: "invalid_request", message: "failed to read request body", detail: err.Error()}
         .          .   1480:	}
         .          .   1481:	if int64(len(body)) > h.maxRequestBodyBytes {
         .          .   1482:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusRequestEntityTooLarge, code: "request_too_large", message: "request body exceeds configured limit", rawBody: body}
         .          .   1483:	}
         .          .   1484:
         .          .   1485:	if endpoint == "/v1/chat/completions" || endpoint == "/v1/responses" || endpoint == anthropicMessagesEndpoint {
         .      1.87s   1486:		meta.thinking = thinkingdiag.New(body)
         .          .   1487:	}
         .          .   1488:
         .          .   1489:	var payload struct {
         .          .   1490:		Model      string `json:"model"`
         .          .   1491:		ProviderID string `json:"provider_id"`
         .          .   1492:		Stream     bool   `json:"stream"`
         .          .   1493:	}
         .          .   1494:	decoder := json.NewDecoder(bytes.NewReader(body))
         .          .   1495:	decoder.DisallowUnknownFields()
         .      2.17s   1496:	if err := decoder.Decode(&payload); err != nil {
         .          .   1497:		var generic map[string]any
         .      1.80s   1498:		if err2 := json.Unmarshal(body, &generic); err2 != nil {
         .          .   1499:			return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusBadRequest, code: "invalid_json", message: "request body must be valid JSON", detail: err.Error(), rawBody: body}
         .          .   1500:		}
         .          .   1501:		model, _ := generic["model"].(string)
         .          .   1502:		providerID, _ := generic["provider_id"].(string)
         .          .   1503:		stream, _ := generic["stream"].(bool)
         .          .   1504:		payload.Model = model
         .          .   1505:		payload.ProviderID = providerID
         .          .   1506:		payload.Stream = stream
         .          .   1507:	}
         .          .   1508:	meta.RequestedModel = payload.Model
         .          .   1509:	meta.RequestedProviderID = payload.ProviderID
         .          .   1510:	meta.Stream = payload.Stream
         .          .   1511:	if payload.Model == "" {
         .          .   1512:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusBadRequest, code: "invalid_model", message: "model is required", rawBody: body}
         .          .   1513:	}
         .          .   1514:	selectedProvider := payload.ProviderID
         .       40ms   1515:	if endpoint == anthropicMessagesEndpoint && deepseeksearch.PublicModel(payload.Model) && deepseeksearch.Requested(body) {
         .          .   1516:		if payload.Stream {
         .          .   1517:			return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusBadRequest, code: deepseeksearch.StreamingUnsupportedCode, message: deepseeksearch.StreamingUnsupportedMessage, rawBody: body}
         .          .   1518:		}
         .          .   1519:		if selectedProvider != "" && selectedProvider != deepseeksearch.ProviderID {
         .          .   1520:			return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusBadRequest, code: "unsupported_tool", message: "DeepSeek native web search requires the official DeepSeek provider", rawBody: body}
         .          .   1521:		}
         .          .   1522:		selectedProvider = deepseeksearch.ProviderID
         .          .   1523:	}
         .          .   1524:	resolved, err := h.resolveRequestModel(runtime, payload.Model, selectedProvider, requestKindForEndpoint(endpoint), routeSelectionKey(principal, meta.RequestID), &meta)
         .          .   1525:	if err != nil {
         .          .   1526:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusNotFound, code: "model_not_found", message: err.Error(), rawBody: body}
         .          .   1527:	}
         .          .   1528:	setExplicitZeroCostUsageModel(r.Context(), resolved, &meta)
         .          .   1529:	if err := enforcePublicModelMembershipEntitlement(runtime, principal.Membership, entitlementPublicModelID(runtime, resolved, &meta, requestKindForEndpoint(endpoint)), requestKindForEndpoint(endpoint)); err != nil {
         .          .   1530:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, err
         .          .   1531:	}
         .          .   1532:	if h.admissionPipeline == nil {
         .          .   1533:		if economicsErr := h.applyRequestEconomics(r.Context(), &principal, &meta, requestKindForEndpoint(endpoint)); economicsErr != nil {
         .          .   1534:			return nil, meta, domain.Principal{}, domain.ResolvedModel{}, economicsErr
         .          .   1535:		}
         .          .   1536:	}
         .          .   1537:	if err := applyRequestRole(r, principal, &meta, requestKindForEndpoint(endpoint)); err != nil {
         .          .   1538:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, err
         .          .   1539:	}
         .          .   1540:	if err := applyProviderQueueMetadata(&meta, resolved); err != nil {
         .          .   1541:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, err
         .          .   1542:	}
         .          .   1543:	meta.shadow = h.shadow.Capture(shadowOrigin(meta, principal), runtime, valueOrEmpty(meta.PublicModelID), endpoint, meta.Stream, body)
         .      5.23s   1544:	normalizedBody, notes, err := prepareTargetBody(endpoint, resolved, meta.PublicModel, body)
         .          .   1545:	if err != nil {
         .          .   1546:		return nil, meta, domain.Principal{}, domain.ResolvedModel{}, &requestError{status: http.StatusBadRequest, code: "invalid_request", message: "failed to prepare provider request", detail: err.Error(), rawBody: body}
         .          .   1547:	}
         .          .   1548:	if len(notes) > 0 && h.logger != nil {
         .          .   1549:		h.logger.Info("request normalized",
         .          .   1550:			"request_id", meta.RequestID,
         .          .   1551:			"endpoint", endpoint,
         .          .   1552:			"requested_model", meta.RequestedModel,
         .          .   1553:			"public_model_id", valueOrEmpty(meta.PublicModelID),
         .          .   1554:			"route_id", valueOrEmpty(meta.RouteID),
         .          .   1555:			"provider_id", resolved.Provider.ID,
         .          .   1556:			"provider_name", resolved.Provider.Name,
         .          .   1557:			"provider_kind", resolved.Provider.Kind,
         .          .   1558:			"model_id", resolved.BackendModel.ID,
         .          .   1559:			"model", resolved.BackendModel.ExternalName,
         .          .   1560:			"bifrost_model", resolved.BackendModel.BifrostModel,
         .          .   1561:			"server_side_queue_enabled", meta.QueueEnabled,
         .          .   1562:			"server_side_queue_wait_timeout_seconds", meta.QueueWaitTimeoutSec,
         .          .   1563:			"notes", notes,
         .      230ms   1564:			"request", requestLogSummary(body),
         .          .   1565:		)
         .          .   1566:	}
         .      1.76s   1567:	meta.thinking.Normalized(normalizedBody, notes)
         .          .   1568:	body = normalizedBody
         .          .   1569:	meta.NormalizationNotes = notes
         .          .   1570:	meta.RequestBodyBytes = len(body)
         .          .   1571:
         .          .   1572:	return body, meta, principal, resolved, nil
指标来源:生产 Grafana / Prometheus;选择器 namespace=nexu、pod=amr-link-.*、container=link。CPU:rate(container_cpu_usage_seconds_total[1h]);请求:rate(gateway_model_requests_started_total[1h]);Token:rate(gateway_model_tokens_total[1h]);分配:rate(go_memstats_alloc_bytes_total[1h])。均先对 workload 求和,再进行窗口汇总和归一化。