#17349

feat(logs): distinguish generation rate from end-to-end throughput

Openmorpheus9393opened 2d ago

Environment

  • OmniRoute 3.8.52, image digest sha256:90f903d7e9245973dc23f7f0a3afc0c63502c9bd25961097843361689df6474b
  • Dashboard -> Logs, green speed column (second-to-last data column, left of the duration column)

Summary

The per-request speed column on the Logs page appears to be computed as tokens_out / (duration - ttft_ms). When an upstream buffers its response (first token arrives late, the rest streams in a burst), duration - ttft_ms collapses towards zero and the column displays physically impossible throughputs. Observed on DeepSeek v4.1 Flash: 12,709 and 5,146 "TPS", while the true end-to-end throughput of the same requests is 85-230 TPS.

On the pre-3.8.52 build (digest sha256:90358c971b44e9f135edac557352658ddbdb5b6d11fc5e42f732688e5dbac981) the same column read systematically low on identical traffic, so this looks like an unannounced semantics change between releases.

Verified against call_logs - 14/14 recent rows match the formula exactly

timestamp (UTC)tokens_outdurationttft_mscolumn showsTO/duration (end-to-end)TO/(duration-ttft)
2026-10-20T22:01:24.845Z1,0047.2 s7,11212,709139.612,708.9
2026-10-20T22:00:55.176Z1,0196.8 s6,5605,146150.85,146.5
2026-10-20T22:03:06.245Z6,64229.1 s19,470692228.5692.5
2026-10-20T22:00:49.326Z5,15424.9 s18,412788206.6788.4
2026-10-20T22:00:34.517Z1372.6 s2,44685152.6850.9

All rows: model cb/deepseek-v4.1-flash via a custom openai-compatible-chat-* connection, status 200. The remaining 9 rows of the window match the same identity to +/-1 (rounding).

Repro SQL

SELECT timestamp, tokens_out, duration, ttft_ms,
       ROUND(tokens_out * 1000.0 / duration, 1)                   AS tps_end_to_end,
       ROUND(tokens_out * 1000.0 / MAX(duration - ttft_ms, 1), 1) AS tps_column_formula
FROM call_logs
WHERE model LIKE '%deepseek-v4.1-flash%' AND status = 200
ORDER BY timestamp DESC LIMIT 14;

Why this misleads

  • duration - ttft is only the post-first-token window. For buffered / non-incremental upstreams it shrinks to tens of milliseconds, so the quotient measures a burst rate, not throughput.
  • Rows with ttft ~= 0 display correct-looking values, which masks the defect in casual inspection.
  • The column has no unit tooltip and no sanity clamp; values above ~2-3k TPS are beyond any current frontier model, yet they are shown unmarked.

Expected behaviour

Either

  1. show end-to-end throughput tokens_out / duration and label the column accordingly, or
  2. keep the generation-phase rate but clamp / fall back, e.g. when duration - ttft_ms < 500 or shown > 5 x (tokens_out / duration), fall back to the end-to-end value; and persist the displayed value in call_logs (e.g. tps_display) so the metric is auditable.

Note

Whichever semantics is intended, please document the change in the changelog: operators comparing dashboards across 3.8.51 -> 3.8.52 currently see the same traffic reported ~10-90x faster.

Activity

1
diegosouzapw2d ago

The formula you identified matches the current implementation: this column measures the gateway-observed post-first-token rate, excluding TTFT. That is an intentional contract, and the development branch already has a tooltip showing TTFT and the measurement window.

Your buffered-response examples expose an important limitation: a high post-first-token delivery rate is not evidence that the upstream model generated tokens at that speed. The proposed improvement is to distinguish it explicitly from end-to-end throughput. We are keeping this open as a presentation/contract enhancement; the choice of which metric is primary is still pending. An arbitrary TPS cap or silently switching formulas under the same label would hide the distinction rather than explain it. Acceptance should include very short delivery windows, reasoning-token accounting and missing/invalid timing data.