fix(tracing): flush local trace on SIGTERM and fix span-duration fragmentation - #6692
Merged
Conversation
bug-ops
enabled auto-merge (squash)
July 28, 2026 13:05
…mentation Local trace files written by the local telemetry backend were left as unterminated JSON when the process was killed via pkill's default SIGTERM, since foreground CLI/TUI mode had no SIGTERM handling and the Chrome trace FlushGuard never dropped. init_tracing now shares the guard between the normal drop path and a new SIGTERM listener via a take-once cell, installed only on invocation paths that don't already own SIGTERM (--daemon, serve-sessions, scheduler serve each have their own graceful shutdown). Also switches build_chrome_layer to TraceStyle::Async, since the previous Threaded style fired on_enter/on_exit on every poll of an async span, fragmenting any span with an internal await into hundreds of short on-CPU slices instead of one continuous wall-clock duration. Closes #6683 Closes #6682
bug-ops
force-pushed
the
fix/6683-local-trace-truncation
branch
from
July 28, 2026 13:06
307ec50 to
6b9aec3
Compare
This was referenced Jul 28, 2026
bug-ops
added a commit
that referenced
this pull request
Jul 28, 2026
log_guard (the rolling-file WorkerGuard) relied on Drop to flush buffered log writes, the same as chrome_guard before #6692 fixed it. A SIGTERM without a handler skips Drop entirely, discarding whatever lines were still in the async writer's channel (reproduced 6/6 with a tight self-kill race, losing 127-939 lines per run). Generalizes the take-once-cell + SIGTERM-listener pattern from #6692 into an unconditional LogGuardCell, since file logging (unlike Chrome tracing) is not gated behind the profiling feature. Both TracingGuards::drop and spawn_sigterm_flush_task now take-and-flush whichever cell(s) are still Some. Extracts should_install_sigterm_flush_task as a pure, unit-tested gate so a mis-wire of owns_sigterm_elsewhere no longer silently regresses in default builds. Closes #6693
bug-ops
added a commit
that referenced
this pull request
Jul 28, 2026
log_guard (the rolling-file WorkerGuard) relied on Drop to flush buffered log writes, the same as chrome_guard before #6692 fixed it. A SIGTERM without a handler skips Drop entirely, discarding whatever lines were still in the async writer's channel (reproduced 6/6 with a tight self-kill race, losing 127-939 lines per run). Generalizes the take-once-cell + SIGTERM-listener pattern from #6692 into an unconditional LogGuardCell, since file logging (unlike Chrome tracing) is not gated behind the profiling feature. Both TracingGuards::drop and spawn_sigterm_flush_task now take-and-flush whichever cell(s) are still Some. Extracts should_install_sigterm_flush_task as a pure, unit-tested gate so a mis-wire of owns_sigterm_elsewhere no longer silently regresses in default builds. Closes #6693
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
localtelemetry backend were left as unterminated JSON when the process was killed viapkill's defaultSIGTERM, since foreground CLI/TUI mode had noSIGTERMhandling and the Chrome traceFlushGuardnever dropped.init_tracingnow shares the guard between the normal drop path and a newSIGTERMlistener via a take-once cell, installed only on invocation paths that don't already ownSIGTERM(--daemon,serve-sessions,scheduler serveeach have their own graceful shutdown).build_chrome_layertoTraceStyle::Async, since the previousThreadedstyle firedon_enter/on_exiton every poll of an async span, fragmenting any span with an internal.awaitinto hundreds of short on-CPU slices instead of one continuous wall-clock duration..claude/rules/continuous-improvement.mdto pairAsync-styleb/eevents byidwith a LIFO stack (that file is untracked/gitignored, so this change does not appear in the diff).Closes #6683
Closes #6682
Test plan
cargo +nightly fmt --checkcargo clippy --profile ci --workspace --all-targets --features "desktop,ide,server,chat,pdf,scheduler,testing" -- -D warningscargo clippy --profile ci --workspace --all-targets --features full -- -D warningscargo nextest run --config-file .github/nextest.toml --features full -E 'binary(zeph) and test(tracing_init)'(19/19 passed, 4 new/rewritten tests including a genuine concurrent-take race test and first coverage forTraceStyle::Async)fullfeature setsgitleaks protect --stagedtelemetry.backend = "local", killed withpkill -TERM -f "target/.*zeph"(the issue's exact repro) — resulting trace file parses cleanly withjq '.', no truncation.awaitno longer fragments into hundreds of on-CPU slices underTraceStyle::Async