Skip to content

feat(traces): Disable links to traces older than 30 days#112377

Draft
nsdeschenes wants to merge 39 commits intomasterfrom
nd/EXP-647/chore-traces-disable-links-to-old-traces-app-wide
Draft

feat(traces): Disable links to traces older than 30 days#112377
nsdeschenes wants to merge 39 commits intomasterfrom
nd/EXP-647/chore-traces-disable-links-to-old-traces-app-wide

Conversation

@nsdeschenes
Copy link
Copy Markdown
Contributor

@nsdeschenes nsdeschenes commented Apr 7, 2026

Trace data has a 30-day retention window. When users click trace links for data older than 30 days, they land on broken/empty trace waterfall pages. This PR disables those links across the entire frontend, showing muted text with a tooltip instead.

Foundation:

  • Moved isPartialSpanOrTraceData() from explore/tables/tracesTable/utils to a shared utils/trace/isOlderThan30Days module with proper timestamp normalization (seconds vs milliseconds detection)
  • Created a reusable DisabledTraceLink component (and DisabledTraceLinkTooltip variant) that renders muted text with a tooltip explaining the 30-day limit, optionally linking to similar recent events
  • Added a projectEventRedirect guard so navigating directly to an old event URL via the redirect view doesn't land on a broken page

~50 files updated across all trace link surfaces:

  • Issue details ("View Full Trace", trace timeline tooltip)
  • Discover table (trace and event ID columns)
  • Dashboards (errors+transactions and spans widgets)
  • Explore (logs, metrics samples, field renderers)
  • Insights modules (web vitals, mobile, agents, span samples)
  • Performance (transaction events, tags heatmap, trace drawer)
  • Profiling (headers, flamegraph, profile events table)
  • Event details (span evidence, profile evidence, statistical detector)

Fixes EXP-647

@linear-code
Copy link
Copy Markdown

linear-code bot commented Apr 7, 2026

@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Apr 7, 2026
Comment thread static/app/views/performance/transactionSummary/transactionEvents/eventsTable.tsx Outdated
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Apr 7, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.

Comment thread static/app/views/insights/pages/agents/components/drawer.tsx
Comment thread static/app/views/explore/tables/tracesTable/utils.tsx Outdated
Comment thread static/app/components/profiling/flamegraph/flamegraphDrawer/profileDetails.tsx Outdated
nsdeschenes and others added 14 commits April 8, 2026 07:38
Move the 30-day trace age check from explore/tables/tracesTable/utils
to a shared location at utils/trace/isOlderThan30Days. Add timestamp
normalization to correctly handle both seconds and milliseconds.

Create a reusable DisabledTraceLink component that renders muted text
with a tooltip for links to traces older than 30 days.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…surfaces

Add 30-day age checks to trace and span links across issue details,
discover, dashboards, logs, agents, transaction summary, and trace
drawer. Links to traces older than 30 days now render as disabled
text with a tooltip instead of broken clickable links.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…samples surfaces

Add 30-day age checks to trace links in insights modules (web vitals,
mobile, agents), span samples tables, span summary sample list, metrics
samples, and trace drawer span attributes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… event surfaces

Add 30-day age checks to trace links in profiling headers, flamegraph,
profile events table, span evidence key-value list, profile event
evidence, and statistical detector event display.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The constant is only used internally within the module. Removing the
export fixes the knip unused-export warning.

Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
Accept undefined in isPartialSpanOrTraceData to match callers that
pass number | undefined timestamps. Add missing disabled prop to
DropdownItemProps in tagsHeatMap and pass it through to MenuItem.

Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
The isPartialSpanOrTraceData check was using the current span's
timestamp to decide whether to disable links to other traces. Span
links connect to external traces that may have completely different
ages, so a recent span could correctly link to an old trace while an
old span could incorrectly have its links disabled even when the
target traces are still within retention.

Since TraceItemResponseLink does not carry the linked trace's
timestamp, we cannot determine the target's age. Remove the check
so links are always clickable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e view

The trace view already has the trace loaded, so the trace ID
attribute link in the span details drawer should always be clickable.
The isPartialSpanOrTraceData check was incorrectly disabling the link
based on the current span's age.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract the shared MinimapContainer block into a variable and
conditionally wrap it with a Link, removing ~15 lines of
duplicated JSX that could drift apart during future edits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move DisabledTraceLink from components/links/ to components/explore/
where it better fits with other explore-related components.

Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
The isOld check ran before the isIssue check, preventing issue event
links from being generated for events older than 30 days. Issue event
links (/issues/{id}/events/{eventId}/) do not depend on trace data
and should always be available regardless of age.

Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
The 'View in Full Trace' button was disabled for traces older than 30 days
but provided no explanation to the user. Wrap the button in a Tooltip that
shows 'Trace data is only available for the last 30 days', matching the
pattern used in other disabled trace links in this PR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the isPartialSpanOrTraceData re-export from tracesTable/utils since
fieldRenderers.tsx was still importing from that indirection. Update
fieldRenderers.tsx to import directly from the canonical location
(sentry/utils/trace/isOlderThan30Days) and fix the Tooltip import in
drawer.tsx to use @sentry/scraps/tooltip.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
nsdeschenes and others added 2 commits April 8, 2026 07:44
Move isOld check and traceViewLink computation into the id key
branch where they are actually used. The SPAN_DESCRIPTION branch
never references traceViewLink, so computing it there was wasted
work and required a non-null assertion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use the event timestamp when profile evidence omits trace timing and
block Discover transaction IDs once trace data ages out. Normalize
numeric string timestamps so the 30-day guard behaves consistently.

Co-Authored-By: GPT-5.4 <noreply@openai.com>
Made-with: Cursor
@nsdeschenes nsdeschenes force-pushed the nd/EXP-647/chore-traces-disable-links-to-old-traces-app-wide branch from 0666dda to 3354073 Compare April 8, 2026 11:03
nsdeschenes and others added 6 commits April 8, 2026 09:13
Wrap the disabled old-trace ID cell in the same overflow container as the
other web vitals table states so narrow columns still ellipsize consistently.

Co-Authored-By: GPT-5.4 <noreply@openai.com>
Made-with: Cursor
Prevent navigation to trace details for events older than 30 days
in both projectEventRedirect and discover eventDetails pages.
Shows a retention message instead of redirecting.
Disable the "View Full Trace" button with a tooltip and hide the
issues trace waterfall overlay when events are older than 30 days.
Use DisabledTraceLink in trace drawer attributes, span links, and
trace summary sections when data is older than 30 days.
Disable trace column links in discover transactionsTable, EAP sampled
events table, and transaction summary link generators when data is
older than 30 days.
Use >= instead of > for the retention check so data at exactly 30 days
is conservatively marked as old, preventing broken links in the boundary
window. Expand test coverage from 3 to 10 cases including ISO strings,
numeric types, boundary, undefined, and future timestamps. Extract IIFE
in profileDetails to a local variable for readability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread static/app/views/performance/transactionSummary/utils.tsx Outdated
nsdeschenes and others added 3 commits April 8, 2026 11:21
location.query.timestamp can be string | string[], but isPartialSpanOrTraceData
expects string | number | undefined. Extract and normalize the value
before passing it to the function.

Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
…imestamp

Move the `isOld` computation outside the `.flatMap()` loop in
traceSpanLinks since `node.value.start_timestamp` is constant across
iterations. Add JSDoc to `normalizeTimestamp` documenting expected
input formats and known edge case with pure numeric date strings.
- Add DisabledTraceLink fallback in ProfileEventDetails for old transactions
- Add tooltip to disabled dropdown items in tagsHeatMap
- Remove redundant && guard before isPartialSpanOrTraceData calls since
  the utility already returns false for undefined
Comment thread static/app/views/discover/eventDetails.tsx
Comment thread static/app/components/profiling/profileEventsTable.tsx
nsdeschenes and others added 2 commits April 8, 2026 11:55
Events with a groupID and eventID redirect to the issue event page,
so the old-trace check should not block them. Extract the redirect
condition into a variable and gate the error screen accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@example.com>
Replace plain container with DisabledTraceLink for trace IDs when the
transaction timestamp indicates old/partial data, consistent with the
app-wide pattern for disabling links to old traces.

Refs EXP-647
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
nsdeschenes and others added 2 commits April 8, 2026 12:08
…ates

In the Web Vitals detail panel, the disabled trace link was showing
the span ID (row.id) while the active link showed the trace ID
(row.trace), causing the same column to display different identifiers
depending on data age.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
nsdeschenes and others added 3 commits April 8, 2026 13:12
…k disable feature

TransactionEventBuilder defaulted startTimestamp to 0 (epoch), which isPartialSpanOrTraceData correctly identifies as old data (>30 days), disabling the 'View Full Trace' button. Add dateCreated with a current timestamp so the isOld check sees a recent event, leaving startTimestamp and endTimestamp unchanged for duration calculations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fc10990. Configure here.

await userEvent.hover(button);
expect(
await screen.findByText('Trace data is only available for the last 30 days')
).toBeInTheDocument();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Test expects wrong tooltip text from DisabledTraceLinkTooltip

Medium Severity

The tests assert the tooltip text is "Trace data is only available for the last 30 days", but the DisabledTraceLinkTooltip component actually renders "Trace is older than 30 days" (from disabledTraceLink.tsx line 35). The component wrapping the LinkButton in eventTraceView.tsx and profileEventEvidence.tsx uses DisabledTraceLinkTooltip, so these tests will fail due to the string mismatch.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit fc10990. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant