GVFS.Service: defer and retry telemetry pipe attachment#1986
Merged
tyrielv merged 2 commits intoMay 26, 2026
Conversation
a39fe39 to
8b149e2
Compare
8b149e2 to
361e7bc
Compare
GVFS.Service runs as SYSTEM and cannot read the user's global git config (where gvfs.telemetry-pipe is set) at startup. This meant TelemetryDaemonEventListener was never created, and all service telemetry events (PendingUpgradeHandler, etc.) were silently lost. Add two new classes in GVFS.Common.Tracing: - BufferingTelemetryListener: an EventListener that buffers telemetry messages in a bounded ConcurrentQueue, then replays them to a real listener on demand. - DeferredTelemetryAttacher: manages the lifecycle of deferred telemetry pipe attachment. Adds a BufferingTelemetryListener to the tracer, then periodically retries creating the real daemon listener (exponential backoff: 10s, 30s, 1m, 5m steady state). On success, replays buffered messages and stops the timer. Checks HasTelemetryDaemonListener to prevent duplicate listeners when the JsonTracer constructor already attached one. Designed for reuse by both GVFS.Service and GVFS.Mount. TelemetryDaemonEventListener gains a globalConfigPath parameter so callers can read a specific .gitconfig file via --file instead of --global. This lets GVFSService read the logged-on user's config without mutating the process-wide HOME environment variable. GVFSService creates a DeferredTelemetryAttacher at startup and calls TryAttach on session logon events, passing the user's .gitconfig path resolved via RunImpersonated. JsonTracer gains only HasTelemetryDaemonListener (one-liner property) to support the duplicate-listener guard. Assisted-by: Claude Opus 4.6 Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Test BufferingTelemetryListener: buffer and replay, stop after replay, bounded cap, second replay returns zero. Test DeferredTelemetryAttacher: null gitBinRoot handling, retry interval exponential backoff values. Assisted-by: Claude Opus 4.6 Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
361e7bc to
b2c81a1
Compare
KeithIsSleeping
approved these changes
May 26, 2026
Merged
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
GVFS.Service runs as SYSTEM and cannot read the user's global git config at startup, so
TelemetryDaemonEventListenerwas never created and all service telemetry events were silently lost.This PR adds deferred telemetry pipe attachment without modifying
JsonTracer— the logic lives in two new focused classes that are reusable by other processes (e.g. GVFS.Mount).Design
BufferingTelemetryListener(GVFS.Common)An
EventListenersubclass that buffersTraceEventMessageobjects in a boundedConcurrentQueue. When a real listener becomes available,ReplayAndStop()replays buffered messages and switches to no-op mode.DeferredTelemetryAttacher(GVFS.Common)Manages the deferred attachment lifecycle:
BufferingTelemetryListenerto the tracer at constructionTelemetryDaemonEventListener.CreateIfEnabledCallers can also trigger an explicit attach via
TryAttach(gitBinRoot)when conditions change (e.g. user session becomes available).Service integration (GVFSService.Windows.cs)
DeferredTelemetryAttacherat startupSessionLogon: temporarily overrides HOME to the user's profile (serialized with a lock) so git can read.gitconfig, then callsTryAttachFiles changed
GVFS.Common/NativeMethods.cs—WTSGetActiveConsoleSessionIdP/InvokeGVFS.Common/Tracing/BufferingTelemetryListener.cs— newGVFS.Common/Tracing/DeferredTelemetryAttacher.cs— newGVFS.Service/GVFSService.Windows.cs— deferred attach integrationGVFS.UnitTests/Common/JsonTracerDeferredTests.cs— tests for buffering, replay, cap, and retry intervalsTesting