A streamed turn logs nothing when it ends, so it cannot be diagnosed afterwards #268
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A non-streaming request closes its journal trail with everything an
operator needs:
A streamed request logs nothing at all. No token counts, no
finish_reason, no duration. The trail simply stops after prefill, andwhether the turn finished cleanly, hit its output cap, or was abandoned
by a disconnecting client is unrecoverable from the journal.
Streaming is the path essentially every interactive client uses, so the
requests we can least reconstruct are the ones most likely to go wrong.
What it cost
This is not theoretical — it is the single largest reason the 2026-08-19
investigation (#267) took a morning:
lines, when the batch-engine decode path simply emits none per token.
The daemon was healthy and decoding both times. One of those wrong
conclusions was published as a root-cause analysis and had to be
retracted.
stopped. Whether it exhausted
max_newor ended some other way couldnot be answered from the server at all — only guessed from file
timestamps and an
in_flightcount dropping.Absence of logging is being read as absence of work, by humans and by
machines, and it is correct to read it that way — nothing distinguishes
"quiet because finished" from "quiet because wedged".
Fix
Emit the same completion line the non-streaming path emits, at the end
of a streamed turn:
prompt_tokens,completion_tokens,reasoning_tokens,finish_reason, and elapsed time.It should fire on every terminal outcome, not just clean completion —
stop,length, tool-call finish, admission rejection, and clientdisconnect. The disconnect case matters most: an abandoned request runs
to completion holding its permit and the TP pool lock, and today that
happens silently.
The
InferenceEvent::Finishvariant already carriesreason / prompt_tokens / completion_tokens / reasoning_tokens / timing,so the data is in hand at the right moment — this is a logging call at
the point the projection already handles
Finish, not newinstrumentation.
Worth logging the request's peak
in_flightor its admission wait too,so a slow turn can be attributed to contention versus generation without
correlating against
/healthpolls after the fact.Related: #267 (the investigation this obstructed), #98 (the batch engine
whose decode path is silent), #137 (metrics — the aggregate view; this is
the per-request view that no metric can replace).