feat(traces): surface span links in the trace viewer#2463
feat(traces): surface span links in the trace viewer#2463alex-fedotyev wants to merge 5 commits into
Conversation
🦋 Changeset detectedLatest commit: fb97673 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🟡 Tier 3 — StandardIntroduces new logic, modifies core functionality, or touches areas with non-trivial risk. Why this tier:
Review process: Full human review — logic, architecture, edge cases. Stats
|
Greptile SummaryThis PR surfaces OpenTelemetry span links in the trace viewer. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (5): Last reviewed commit: "fix(traces): keep span-link row keys uni..." | Re-trigger Greptile |
E2E Test Results✅ All tests passed • 240 passed • 1 skipped • 1060s
Tests ran across 4 shards in parallel. |
|
Pushed a follow-up commit (4416036) with an alternative to the nested-drawer "Open trace" on a span link, so we can validate the navigation approach together. What it does: instead of opening each linked trace in a new stacked drawer (which builds a tower once you follow a chain of links), it reuses the inline-split trace panel from #2402 and navigates trace to trace in the same flyout, with a back stack and a breadcrumb of the spans you followed. Back pops a level; a breadcrumb crumb jumps straight to any level. The linked span auto-focuses on arrival. Scope: one optional Known gaps if we go this way: the Overview-tab "Open trace" still uses the drawer, there is no unit test yet for the nav stack, and no e2e for the multi-hop flow. I will fill those in once we pick a direction. To try it: open a trace whose span carries outgoing links, click "Open trace", and follow a couple of hops. |
|
Heads up on direction. #2541 reworks the side panel into a single drawer with a shared cross-source navigation stack (its new "View Trace" action pushes onto it) plus a shared breadcrumb component. That replaces the stacked/nested drawer pattern this PR's "Open trace" currently relies on. Rather than ship navigation that #2541 then has to unwind, I'm going to rebuild "Open trace" on that shared stack: following a span link becomes a push of the linked span's trace frame, the same way "View Trace" works for logs. That reuses the breadcrumb trail, URL persistence, and back/jump behavior for free, and lets me drop the in-place trace-nav code in DBTracePanel and the nested-drawer path entirely. The Span Links display section and the schema auto-detection stay as they are. Sequencing: let #2541 land first, then rebase this onto it and swap in the push call. I'll hold the navigation rewire until then. The display and schema parts are reviewable on their own in the meantime. |
Show a "Span Links" section in the span detail when a span carries outgoing OpenTelemetry links. Each link renders as a compact row: an "Open trace" action, the trace state and attributes as chips, and the full Trace and Span IDs on hover. A link with neither state nor attributes collapses to a single line, and links past the first five sit behind a "Show more" toggle. "Open trace" opens the linked trace in the existing nested side panel with breadcrumb back navigation, the same flow the Surrounding Context tab uses, so it stacks above the trace drawer in both the search and direct-trace entry points. The Links column is auto-detected from the standard OTel trace schema and read through a guarded select, so nothing changes for sources that do not have it. This is a display-only field, so no source configuration UI and no external API contract are added. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rebase onto #2541 (single-drawer navigation) and replace the nested-drawer "Open trace" path with a push onto the same cross-source stack "View Trace" uses. Deletes the DBTracePanel in-place-nav prototype, the setOpenedLink nested panel, the breadcrumbPath/onBreadcrumbClick threading, and the DirectTraceSidePanel z-index seed that only existed to support the nested drawer. Adds onOpenLinkedTrace to RowSidePanelContext, computed in DBRowSidePanelInner from the same traceIdExpression/spanIdExpression used for "View Trace", and consumed by RowOverviewPanel -> SpanLinksSubpanel. Also fixes a restricted-import lint violation in SpanLinksSubpanel.test.tsx (parent-relative import instead of the @/ alias) hit while touching the file. Co-Authored-By: Claude <noreply@anthropic.com>
4416036 to
aa6f19d
Compare
Span-link "Open trace" hops now label their breadcrumb with the landed span name once the destination row loads, instead of a "Trace <id>" fallback. The name is resolved into a small in-memory store keyed by the hop's row id; the shared side-panel navigation hook is untouched and the "View Trace" hop keeps its existing label. Address review feedback on the span-links section: - Gate the "Span Links" section on at least one valid link, so a non-empty but all-malformed Links array no longer opens an empty section. The validity check is now one exported getValidSpanLinks helper reused by both the subpanel and the overview gate. - Remove a dead null-guard in SpanLinksSubpanel (the memoized list is always an array). Tests: getValidSpanLinks unit cases, a breadcrumb-label integration test that drives the real panel tree through an Open-trace hop, and the existing span-link suites. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Pushed 086ead9 on top of the rebase onto main. Breadcrumb labels: a span-link "Open trace" hop now shows the landed span name (for example Both review threads are addressed in the same commit: the dead null-guard is gone, and the "Span Links" section now gates on at least one valid link through a shared Validation: the eslint warning gate, |
Deep Review✅ No critical issues found. No P0/P1 issues. The core navigation and SQL wiring are sound: 🟡 P2 -- recommended
🔵 P3 nitpicks (3)
Reviewers (7): correctness, testing, security, maintainability, api-contract, agent-native, learnings-researcher. Testing gaps:
Coverage note: 4 selected reviewers (adversarial, kieran-typescript, julik-frontend-races, project-standards) did not return before synthesis; findings above reflect the 7 completed reviewers. |
Address Greptile review on #2463. A span can carry two links to the same destination span (same TraceId and SpanId, different attributes). The row key was TraceId-SpanId, which collides in that case, so React warns and can drop a row. Add the list index to the key; the span-link list is append-only and never reordered, so the index stays stable across renders. Adds a regression test that renders two links to the same destination span and asserts both rows render with no duplicate-key warning. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Pushed fb97673 for the remaining review note. Span-link rows now key on The |
Summary
Span links are the OpenTelemetry way of pointing from one span to a span in a different trace: a producer/consumer hop, the source records behind a batch, a retried request. HyperDX ingests them in the standard
Linkscolumn but never surfaced them, so in fan-out and batch flows the related spans just showed up as orphans.This adds a "Span Links" section to the span detail. It renders only when the span actually has links. Each link is a compact row:
"Open trace" jumps to the linked trace in place, through the same cross-source navigation #2541 introduced: the trace opens in the same panel, the breadcrumb trail picks up the hop, and back and the URL both reflect it. A span link is really the same kind of jump as the existing "View Trace" action (log to trace), just keyed off the link's trace and span ids instead of the current row's, so it reuses that mechanism directly instead of adding a second one.
The
Linkscolumn is auto-detected from the standard OTel trace schema and read through a guarded select, so sources without it are untouched and the rest of the row-detail panel keeps working. This is a display-only field, so it adds no source-configuration UI and no external API surface.Replaces #2440
Fresh branch replacing #2440, which I'm closing. That branch's history got tangled during a rebase. This one ships the same feature with a clean diff and trims the scope to what a display-only field actually needs: it drops the source-form field, the onboarding default, and the external-API and OpenAPI entries that the earlier draft threaded through.
Rebased onto #2541
This branch tried two navigation approaches while #2541 (single-drawer navigation) was still in review: a nested drawer, then a separate in-place flyout prototype for feedback. Now that #2541 shipped a shared mechanism for exactly this, jumping across sources in place with one breadcrumb trail, I rebased onto it and dropped both. "Open trace" is just another caller of that mechanism now, the same as "View Trace": it pushes the linked trace onto the shared stack instead of opening a second drawer.
Test plan
make ci-lintandmake ci-unitpass: full app suite, common-utils.Implements #1593