Skip to content

feat: add reverse span links, show span link detail - #3011

Merged
karl-power merged 3 commits into
mainfrom
reverse-span-links
Aug 28, 2026
Merged

feat: add reverse span links, show span link detail#3011
karl-power merged 3 commits into
mainfrom
reverse-span-links

Conversation

@karl-power

@karl-power karl-power commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Span links were only usable from the consumer side: a span showed the links it carries, as bare "Open trace" actions. There was no way to start from a producer span and find the consumer spans that link back to it.

  • New "Linked from" section in the span Overview panel listing spans whose links reference the selected span. Each entry shows the referencing span's name, service, duration, and timestamp, with the same open-trace navigation as forward links.
  • The existing Span Links section now resolves each link's target span and shows the same details instead of a bare "Open trace" action (which remains the fallback when the target can't be found).
  • Since forward and reverse links come in pairs, clicking a link that targets the span you just hopped from pops back to the previous breadcrumb instead of growing the trail forever on A ↔ B hops. SourceFrame gains an optional, source-agnostic originRowId for this.
  • Both lookups run through useQueriedChartConfig bounded to a time window anchored on the selected span, skewed in the direction links point in time: referencing spans run at/after the span (−1h/+24h), linked-to spans ran at/before it (−24h/+1h).

Screenshots or video

Untitled.mov

How to test on Vercel preview

Preview routes: /search

Steps:

  1. Find a span that has some links (search Links.SpanId != [])
  2. Open the span and scroll to the span link section, navigate to the linked span.
  3. Check the reverse linking on the linked to span, as shown in the video.

References

@changeset-bot

changeset-bot Bot commented Aug 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0f36252

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Minor
@hyperdx/api Minor
@hyperdx/otel-collector Minor

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

@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview Aug 28, 2026 9:38am
hyperdx-storybook Ready Ready Preview Aug 28, 2026 9:38am

Request Review

@github-actions github-actions Bot added the review/tier-3 Standard — full human review required label Aug 27, 2026
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

🟡 Tier 3 — Standard

Introduces new logic, modifies core functionality, or touches areas with non-trivial risk.

Why this tier:

  • Diff size: 660 production lines changed (Tier 2 max: < 250)

Review process: Full human review — logic, architecture, edge cases.
SLA: First-pass feedback within 1 business day.

Stats
  • Production files changed: 6
  • Production lines changed: 660 (+ 1009 in test files, excluded from tier calculation)
  • Branch: reverse-span-links
  • Author: karl-power

To override this classification, remove the review/tier-3 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

@greptile-apps

greptile-apps Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds resolved forward span-link details, reverse-link discovery, and breadcrumb-aware navigation between linked spans.

  • Adds bounded ClickHouse lookups for linked and referencing spans.
  • Displays span identity, service, timestamp, and duration in both link directions.
  • Adds breadcrumb pop-back behavior for reciprocal links.
  • Expands unit and end-to-end coverage for linked-span navigation.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/app/src/components/linkedSpans.tsx Adds bounded forward and reverse span queries, result conversion, hooks, and shared metadata rendering.
packages/app/src/components/DBRowOverviewPanel.tsx Integrates resolved forward links and the new reverse-link section into the span overview.
packages/app/src/components/DBRowSidePanel.tsx Adds origin-aware reciprocal-link navigation that returns to the preceding breadcrumb.
packages/app/src/components/SpanLinkedFromSubpanel.tsx Adds the reverse-link list UI with navigation and expandable rows.
packages/app/src/components/SpanLinksSubpanel.tsx Enhances forward links with resolved span metadata while retaining the unresolved fallback.
packages/app/tests/e2e/features/span-links.spec.ts Exercises forward links, reverse links, resolved details, and reciprocal breadcrumb navigation.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Selected span] --> B[Resolve forward links]
  A --> C[Find reverse links]
  B --> D[Span links section]
  C --> E[Linked from section]
  D --> F[Open linked span]
  E --> F
  F --> G{Targets previous span?}
  G -->|Yes| H[Pop breadcrumb]
  G -->|No| I[Push source frame]
Loading

Reviews (4): Last reviewed commit: "edd e2e tests" | Re-trigger Greptile

Comment thread packages/app/src/components/linkedSpans.tsx
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

E2E Test Results

All tests passed • 325 passed • 1 skipped • 1094s

Status Count
✅ Passed 325
❌ Failed 0
⚠️ Flaky 0
⏭️ Skipped 1

Tests ran across 4 shards in parallel.

View full report →

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Deep Review

✅ No critical issues found.

This PR adds reverse span-link discovery, resolves forward-link target details, and adds breadcrumb pop-back navigation for reciprocal A↔B link hops. The SQL construction was independently verified as injection-safe (source-config expressions are SqlString.raw-wrapped per the codebase-wide trust model; runtime trace/span ids and link pairs flow through escaped ? placeholders), the query hooks correctly gate on enabled && config != null, and the navigation pop-back equality logic is sound. No P0/P1 issues. One performance trade-off and a few nits below.

🟡 P2 -- recommended

  • packages/app/src/components/linkedSpans.tsx:149 -- The reverse lookup dispatches a has(Links.SpanId, …) scan on every span-overview open (config is non-null for any trace span with a links expression), and the code comment confirms no ClickHouse index serves it on the default schema, so high-volume deployments pay a multi-partition scan on routine panel opens.
    • Fix: Gate the reverse lookup behind an explicit user action or a cheap existence check, or ship the bloom_filter index the comment describes so granules can be skipped.
    • performance, previous-comments
🔵 P3 nitpicks (3)
  • packages/app/src/components/DBRowOverviewPanel.tsx:368 -- The Span Links panel Box changed from px="md" to ps={contentPx} (padding-left only), diverging from sibling panels that use px and dropping right padding.
    • Fix: Use px={contentPx} for the Span Links and Linked-from panels unless the left-only inset is intentional.
  • packages/app/src/components/linkedSpans.tsx:41 -- Reverse results are capped at MAX_LINKED_SPANS (50) ordered by timestamp with no UI indication when the list is truncated.
    • Fix: Surface a "showing first 50" hint when the cap is hit.
  • packages/app/src/components/DBRowSidePanel.types.ts:50 -- Typo "somtimes" in the originRowId doc comment.
    • Fix: Correct to "sometimes".

Reviewers (7): correctness, performance, security, kieran-typescript, testing, maintainability, previous-comments.

Testing gaps: No unit assertion that runtime traceId/spanId/link-pair values stay parameterized (not SqlString.raw) in getReverseSpanLinksConfig/getLinkedSpansConfig; a regression moving a runtime id into raw interpolation would go uncaught. The prior request for an e2e test is addressed by packages/app/tests/e2e/features/span-links.spec.ts.

pulpdrew
pulpdrew previously approved these changes Aug 27, 2026

@pulpdrew pulpdrew left a comment

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.

LGTM, and seems to work well.

Left a suggestion for another option if we're worried about the performance impact.

Comment thread packages/app/src/components/linkedSpans.tsx Outdated
Comment thread packages/app/src/components/linkedSpans.tsx
Comment thread packages/app/src/components/DBRowSidePanel.tsx
@pulpdrew

Copy link
Copy Markdown
Contributor

One other callout is that it may be good to add an E2E test for this functionality, to prevent regressions in the future.

@pulpdrew pulpdrew left a comment

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.

LGTM, thanks for adding the test!

@karl-power
karl-power merged commit 6b7ca4a into main Aug 28, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review/tier-3 Standard — full human review required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Show span links from the producer side too

2 participants