Skip to content

fix: Request end up prematurely because of client disconection - #2

Merged
hcastc00 merged 1 commit into
mainfrom
fix/finish-reason
Sep 9, 2026
Merged

fix: Request end up prematurely because of client disconection#2
hcastc00 merged 1 commit into
mainfrom
fix/finish-reason

Conversation

@hcastc00

@hcastc00 hcastc00 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Retain streaming usage and add privacy-conscious diagnostics

Summary

Streaming completions could reach clients before trailing provider usage was
consumed, allowing clients that close on finish_reason or [DONE] to interrupt
usage collection. The OpenAI-compatible parser also missed usage on some delta
shapes. Successful requests could consequently reach metering without token
counts, while generation completed logs gave no indication of the missing usage.

This change retains usage through stream finalization and adds diagnostics to
trace provider receipt, parser forwarding, and metering outcomes without logging
prompt or response content.

Changes

  • Preserve usage on text, role, tool, reasoning, and empty deltas.
  • Drain upstream after completion before sending finish_reason and [DONE],
    with a five-second finalization timeout. Request cancellation still cancels
    upstream work; finalization also includes the metering call triggered at EOF.
  • Log missing usage, interrupted streams, finalization timeouts, client write
    failures, and metering acceptance or failure with correlation IDs and usage
    counts. Metering acceptance does not prove a nonzero credit deduction.
  • Add OpenAI-compatible and Tinfoil provider stream summaries distinguishing
    [DONE], bare EOF, cancellation, parser anomalies, and usage forwarding.
    Debug logs add chunk metadata for usage and finish signals.
  • Disable application log sampling so repeated messages from distinct requests
    are not silently dropped during bursts.

Privacy

Diagnostics omit raw SSE, prompts, generated text, tool arguments, and credentials.
Request summaries use fixed metadata keys, numeric/boolean settings, and counts;
tool names, stop strings, schemas, and arbitrary stream options are omitted.
Generation and HTTP error logs omit error messages and arbitrary upstream metadata,
which may echo private request contents, while retaining numeric upstream status.
Unknown finish reasons are logged as unknown. Correlation IDs remain visible.

Validation

  • go test ./... passes, including privacy regression tests for request summaries,
    provider errors that echo prompts, tool arguments, and unexpected finish reasons.
  • Local HTTP streaming regressions cover clients closing on completion signals,
    trailing usage, and providers that omit usage.
  • Diagnostic tests cover cancellation, deadlines, malformed SSE, metering failure,
    correlation fields, severity, and preservation of accounting outcomes.
  • git diff --check passes.

Limits

The timeout bounds finalization but cannot recover usage a provider never sends.
Missing usage is reported without replaying requests or estimating charges.
Historical missing usage and existing logs are not repaired. Log delivery and
retention still depend on deployment, and disabling sampling increases log volume.

See streaming usage diagnostics for event
meanings, Loki queries, and how to distinguish possible provider omission from an
interrupted stream.

@hcastc00
hcastc00 merged commit 7e1daa3 into main Sep 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant