Skip to content

fix: use TimeProvider for span end time in BrighterTracer (#4087)#4088

Merged
iancooper merged 2 commits intoBrighterCommand:masterfrom
thomhurst:fix/4087-tracer-end-time-timeprovider
Apr 26, 2026
Merged

fix: use TimeProvider for span end time in BrighterTracer (#4087)#4088
iancooper merged 2 commits intoBrighterCommand:masterfrom
thomhurst:fix/4087-tracer-end-time-timeprovider

Conversation

@thomhurst
Copy link
Copy Markdown
Contributor

Summary

Fixes #4087.

BrighterTracer.EndSpan disposed the Activity without setting an explicit end time, so Activity.Stop (called from Dispose) fell back to raw DateTime.UtcNow and ignored the injected TimeProvider. Span start times use _timeProvider.GetUtcNow(), but end times did not — under any non-system TimeProvider (e.g. FakeTimeProvider in tests) the start used simulated time and the end used real wall clock, so Activity.Duration was wildly wrong (often hundreds of days off, depending on how far the simulated clock was from real time).

Change

src/Paramore.Brighter/Observability/BrighterTracer.csEndSpan now calls span.SetEndTime(_timeProvider.GetUtcNow().UtcDateTime) before Dispose(). Activity.Stop honours the explicit end time when one has been set, so the duration is now (end via TimeProvider) - (start via TimeProvider) and is correct under both TimeProvider.System (production) and any custom provider (tests, deterministic replay, scheduling integration).

EndSpans flows through EndSpan, so it is covered without further change.

Test plan

  • New test BrighterTracerEndSpanTimeProviderTests.When_Ending_A_Span_Duration_Reflects_TimeProvider creates a span under FakeTimeProvider, advances by 5s, ends the span, and asserts Duration == TimeSpan.FromSeconds(5).
  • Confirmed RED before the fix: failed with Expected 00:00:05, Actual 115.13:19:00… (wall-clock leak).
  • Confirmed GREEN after the fix.
  • Full Observability suite still passes (61 passed, 2 pre-existing skips, 0 failures) on net9.0.

Notes

The issue also called out an optional secondary fix — moving the now snapshot to immediately before StartActivity in each Create*Span method so tag-construction overhead (JsonSerializer.Serialize(...) for Header/Body) is excluded from span start. That is acknowledged in the issue as "negligible in production" and is not addressed here to keep this change minimal and focused on the correctness bug. Happy to follow up in a separate PR if desired.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@iancooper iancooper added 3 - Done Bug .NET Pull requests that update .net code V10.X labels Apr 26, 2026
Copy link
Copy Markdown
Member

@iancooper iancooper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, and thanks for the test

…mmand#4087)

`BrighterTracer.EndSpan` disposed the Activity without setting an
explicit end time, so `Activity.Stop` fell back to raw `DateTime.UtcNow`
and ignored the injected `TimeProvider`. Under any non-system
TimeProvider (e.g. `FakeTimeProvider` in tests) span start used
simulated time but end used wall clock, so `Activity.Duration` was
meaningless.

Set the end time explicitly via `_timeProvider.GetUtcNow()` before
disposing. `EndSpans` flows through `EndSpan` and is covered.
@thomhurst thomhurst force-pushed the fix/4087-tracer-end-time-timeprovider branch from 7d6378f to 8d1856f Compare April 26, 2026 14:12
codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Copy Markdown

@codescene-delta-analysis codescene-delta-analysis Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gates Passed
4 Quality Gates Passed

See analysis details in CodeScene

Quality Gate Profile: Clean Code Collective
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

@iancooper iancooper merged commit 6275b53 into BrighterCommand:master Apr 26, 2026
27 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3 - Done Bug .NET Pull requests that update .net code V10.X

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BrighterTracer span end time ignores TimeProvider — durations broken under FakeTimeProvider

2 participants