feat(init): Handle::drain_logs — flush the log pipeline before a fatal exit - #46
Open
nicolasauler wants to merge 1 commit into
Open
feat(init): Handle::drain_logs — flush the log pipeline before a fatal exit#46nicolasauler wants to merge 1 commit into
nicolasauler wants to merge 1 commit into
Conversation
…l exit A fatal error logged right before exit (e.g. a missing required env var at boot) rode out on the best-effort Drop shutdown, whose result is only eprintln'd — and prod scrapes no stderr, so the crash was invisible in Grafana/Sentry. Add Handle::drain_logs(): force_flush() for a truthful ack on the fast path (the SDK caps its wait at 5s), then shutdown_with_timeout(12s) to give a slower export time to finish before the process exits (that call waits past the 10s RPC but discards the result, so force_flush is what carries it). Also stop surfacing the benign AlreadyShutdown from the follow-up Drop. Purely additive — no change to steady-state export, Drop, or SIGTERM behavior.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A fatal error logged right before process exit — e.g. a missing required env var at boot (
env::loadfailing before the server can serve) — was frequently lost.mainlogs the error, then thetrail::Handledrops, andDrop→shutdown()is best-effort: its result is onlyeprintln!'d, and prod ingests logs only via trail's OTLP exporter (no pod-stdout scraping). So a boot crash was invisible in Grafana/Sentry — you only sawCrashLoopBackOff.This adds a way for the exit path to flush the log pipeline and learn whether the record landed.
The change (purely additive)
Handle::drain_logs(&self) -> OTelSdkResult:Why both calls — the two SDK primitives each miss one half, verified against opentelemetry_sdk 0.32.1:
force_flush()propagates the true export result (recv_timeout(..)?), but the SDK hard-codes its wait to 5s.shutdown_with_timeout(t)waitst(can exceed the 10s export RPC), but discards the result (recv_timeout(t).map(|_| Ok(()))) — it returnsOkeven when the export failed (e.g. connection-refused).So:
force_flushfirst for a real acknowledgement on the fast path (the common case — a healthy in-cluster collector ACKs in ms), thenshutdown_with_timeout(12s)to give a slower export time to finish before the process exits. Contract:Ok= exported and acked within 5s;Err= unconfirmed in that window (may still land via the drain) — not proof of loss.Also suppresses the benign
AlreadyShutdownthatDrop'sshutdown()would otherwiseeprintln!afterdrain_logs— an error-shaped line in the exact stderr an operator reads to triage the crash.No behavior change to steady-state export,
Drop, or SIGTERM drain — the 10s OTLP default and the existingshutdown()are untouched. Only a new opt-in method.Consumer
The bipa server will call
drain_logs()on its fatal boot-error branch (separate PR). It pairs with the env two-phase change (bipa#16485) that moves telemetry init ahead of the bulk env parse so the error reaches the pipeline in the first place.Review
Two rounds of adversarial (Fable-5) review folded in: the first version set
.with_timeout(3s)on the exporter — which was backwards (it cancels the export RPC at 3s and regresses delivery fleet-wide, since the batch worker exports on a detached thread the old 5s wait never actually cut); the second flagged thatshutdown_with_timeoutdiscards the result (falseOk). Both are fixed here. Mechanics verified directly against the SDK source.Test plan
cargo check --features init+--all-featuresclean;cargo fmt --checkcleandrain_logsreturnsOk)