Repository navigation
fix(opentelemetry): Convert OpenTelemetry performance.now() timestamps - #25790
Conversation
OpenTelemetry numeric time inputs are always milliseconds, either since the epoch or since the performance time origin. Interpret them as such for spans created by the SentryTracerProvider, instead of applying the Sentry API's seconds-or-milliseconds heuristic. Fixes #25743 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
size-limit report 📦Compared: 1660b32 (PR test merge using develop at 408951e) Against: 408951e (develop) · base run #63898 ✅ Baseline matches: this diff contains only this PR's changes.
|
| if (childSpan.isRecording()) { | ||
| childSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' }); | ||
| childSpan.end(endTimestamp); | ||
| // `endTimestamp` is in seconds, but provider spans read numbers as OpenTelemetry milliseconds |
There was a problem hiding this comment.
it is super unlikely, I guess, that this is actually the case, because we don't really support otel in browser, and idle spans are only really used in browser.
so we could also decide to ignore this case here 🤔
There was a problem hiding this comment.
Yea seems reasonable to me to ignore it here.
Optional E2E testsSome optional checks were not successful. They do not block the merge. 4 not successful, 61 successful. See the run.
Successful checks
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7a5b50f. Configure here.
| childSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' }); | ||
| // NOTE: This deliberately does not work for OTEL-provider spans (which use ms timestamps) | ||
| // We do not really support OTEL in the browser, which is the only place that uses idle spans | ||
| childSpan.end(endTimestamp); |
There was a problem hiding this comment.
Stale provider span cancel test
Medium Severity
This test still expects a tracer-provider child to share the idle span end time, but the cancel path now passes the seconds endTimestamp through unchanged. Provider spans interpret that number as relative milliseconds, so the assertion no longer matches the intended behavior. Testing conventions require tests to cover the newly added behavior.
Triggered by project rule: PR Review Guidelines for Cursor Bot
Reviewed by Cursor Bugbot for commit 7a5b50f. Configure here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>


Why: OpenTelemetry numeric time inputs are always milliseconds, either since the epoch or relative to the performance time origin (
performance.now()). We passed them straight intospanTimeInputToSeconds, which treats numbers as seconds, soperformance.now()start/end times produced 1970-dated spans with durations inflated 1000×. This can't be fixed by detecting the unit inspanTimeInputToSecondsitself: Sentry seconds (~1.8e9) and relative milliseconds overlap after ~21 days of process uptime. Within OTel semantics the split is unambiguous though — epoch milliseconds are > 1e12 for any date after 2001, whileperformance.now()needs ~30 years of uptime to get there.So
otelTimeInputToSecondsapplies OTel semantics, used bySentryTracerforstartTimeand bySentrySpanforend/addEvent/updateStartTimeon spans marked viaspanIsTracerProviderSpan. It's a separate function instead of a flag onspanTimeInputToSecondsso non-tracing bundles stay unchanged (+0 B on@sentry/browser, ~+70–80 B gzipped on tracing bundles).How to review: Start with
otelTimeInputToSecondsinspanUtils.ts. Idle spans still cancel unfinished children with a seconds timestamp, which provider spans would read as relative milliseconds. I left that alone on purpose: idle spans only exist in the browser, where we don't really support OTel.Unsure about:
addEventkeeps treating a falsy time as "now" (startTime || undefined), soaddEvent(name, attrs, 0)on a provider span doesn't meanperformance.now()zero. Kept for backwards compatibility. We don't really care aboutaddEventtoo much, so I'd argue it's fine to keep it and not think too much about this.Based on the work by @MathurAditya724 in #25744 — thank you!
Closes #25743
Co-authored-by: Aditya Mathur 57684218+MathurAditya724@users.noreply.github.com