Skip to content

feat(dashboards): add Replay search action to tiles#2648

Open
xob0t wants to merge 2 commits into
hyperdxio:mainfrom
xob0t:agent/dashboard-replay-search
Open

feat(dashboards): add Replay search action to tiles#2648
xob0t wants to merge 2 commits into
hyperdxio:mainfrom
xob0t:agent/dashboard-replay-search

Conversation

@xob0t

@xob0t xob0t commented Jul 15, 2026

Copy link
Copy Markdown

Summary

Adds a Replay search action to eligible log and trace dashboard tiles.

The action opens Search in a new tab while preserving the tile's source, query, dashboard filters, and time range. It is hidden when the search cannot be reconstructed accurately.

Screenshots or video

image

How to test on Vercel preview

Preview routes: /dashboards

Steps:

  1. Open a dashboard containing a log or trace tile.
  2. Hover over the tile header and select Replay search.
  3. Confirm a new Search tab opens with the tile's query, filters, and time range.
  4. Verify the action is not shown for unsupported tile types such as metrics or SQL.

References

Validation

  • Tested successfully on a self-hosted HyperDX deployment.
  • yarn lint:fix
  • yarn workspace @hyperdx/app lint
  • yarn workspace @hyperdx/app tsc --noEmit

@changeset-bot

changeset-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 16c1741

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 Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

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 Jul 15, 2026

Copy link
Copy Markdown

@xob0t is attempting to deploy a commit to the HyperDX Team on Vercel.

A member of the Team first needs to authorize it.

@xob0t
xob0t marked this pull request as ready for review July 15, 2026 14:21
@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a "Replay search" action to log and trace dashboard tiles. Clicking it opens the Search page in a new tab with the tile's source, query, dashboard filters, and time range pre-populated. The action is correctly hidden for unsupported tile types (metrics, PromQL, raw SQL, multi-series per-condition tiles that cannot be faithfully reconstructed).

  • replaySearchUrl is computed in a useMemo with proper guards for builder config, metric tables, unsearchable sources, and per-series aggConditions that can't be promoted.
  • The button is exposed in both the hover toolbar (icon) and the collapsed kebab menu, with correct dependency arrays in both useMemo hooks.
  • The URL is always built from the dashboard-level dateRange, so when a user zooms into a sub-range inside the fullscreen modal, "Replay search" will open with the wider dashboard range rather than the locally adjusted one.

Confidence Score: 4/5

Safe to merge for the standard dashboard view; the only behavioral gap is that the replay URL does not pick up the fullscreen-modal date range when a user has zoomed in there.

The guards against unsupported tile types are well-structured and consistent with the existing isMetricChartConfig/isSearchableSource logic. The one identified gap — using the dashboard dateRange instead of the fullscreen-local dateRange — affects only users who zoom into a sub-range inside the tile's fullscreen modal before clicking Replay search; the feature works correctly in all other cases.

packages/app/src/DBDashboardPage.tsx — specifically the replaySearchUrl memo and how dateRange is chosen when the tile is in fullscreen mode.

Important Files Changed

Filename Overview
.changeset/dashboard-replay-search.md New changeset entry accurately describing the Replay search feature; no issues.
packages/app/src/DBDashboardPage.tsx Adds replaySearchUrl memo and two UI entry points (hover toolbar icon + collapsed menu item) with correct guards for unsupported configs; the URL is computed from the dashboard dateRange rather than the per-tile fullscreen date range, so the time range passed to search will be wrong when a user has zoomed in via the fullscreen modal.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant Tile as Tile (DBDashboardPage)
    participant useMemo as replaySearchUrl (useMemo)
    participant buildEventsSearchUrl
    participant SearchPage

    User->>Tile: Hover tile header / open kebab menu
    Tile->>useMemo: Evaluate replaySearchUrl
    Note over useMemo: Guards: isBuilderChartConfig?<br/>metricTables == null?<br/>isSearchableSource (Log/Trace)?<br/>per-series aggCondition promotable?
    useMemo->>buildEventsSearchUrl: "{ source, config: queriedConfig, dateRange }"
    buildEventsSearchUrl-->>useMemo: "/search?source=...&where=...&filters=...&from=...&to=..."
    useMemo-->>Tile: "replaySearchUrl (string | null)"
    alt replaySearchUrl is non-null
        Tile-->>User: Show Replay search icon / menu item
        User->>SearchPage: Click opens in new tab with pre-filled query and time range
    else replaySearchUrl is null
        Tile-->>User: Action hidden
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant Tile as Tile (DBDashboardPage)
    participant useMemo as replaySearchUrl (useMemo)
    participant buildEventsSearchUrl
    participant SearchPage

    User->>Tile: Hover tile header / open kebab menu
    Tile->>useMemo: Evaluate replaySearchUrl
    Note over useMemo: Guards: isBuilderChartConfig?<br/>metricTables == null?<br/>isSearchableSource (Log/Trace)?<br/>per-series aggCondition promotable?
    useMemo->>buildEventsSearchUrl: "{ source, config: queriedConfig, dateRange }"
    buildEventsSearchUrl-->>useMemo: "/search?source=...&where=...&filters=...&from=...&to=..."
    useMemo-->>Tile: "replaySearchUrl (string | null)"
    alt replaySearchUrl is non-null
        Tile-->>User: Show Replay search icon / menu item
        User->>SearchPage: Click opens in new tab with pre-filled query and time range
    else replaySearchUrl is null
        Tile-->>User: Action hidden
    end
Loading

Fix All in Claude Code Fix All in Conductor Fix All in Cursor Fix All in Codex

Reviews (1): Last reviewed commit: "fix(dashboards): restrict replay search ..." | Re-trigger Greptile

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

Copy link
Copy Markdown
Contributor

Deep Review

✅ No critical issues found.

This is a focused, additive frontend change: a replaySearchUrl useMemo gates a "Replay search" ActionIcon and Menu.Item on log/trace dashboard tiles. Security is clean (relative /search URL built via URLSearchParams, rel="noopener noreferrer" on both target="_blank" links, no injection/redirect/authz surface). The render-phase notifications.show side effect inside buildEventsSearchUrl was checked and confirmed unreachable on the replay path — the metricTables != null guard aligns with isMetricChartConfig, so no toast fires during render. The gating logic, where/select type handling, undefined guards, and useMemo dependency arrays are all correct, and the new imports resolve.

🟡 P2 -- recommended

  • packages/app/src/DBDashboardPage.tsx:708 -- The canPromoteSingleSeriesCondition gate (select.length === 1 && where.length === 0) re-encodes buildEventsSearchUrl's private promotion invariant, so the two can silently drift and either surface an unfaithful replay or hide a valid one.
    • Fix: Have buildEventsSearchUrl own faithfulness detection (return a discriminated result or export a companion predicate) and consume that in the useMemo instead of duplicating the condition.
    • maintainability, julik-frontend-races
  • packages/app/src/DBDashboardPage.tsx:688 -- The new gating useMemo adds four behavior-changing branches (metric/non-searchable source, non-builder config, non-promotable per-series condition, happy path) with no accompanying test coverage; no test references buildEventsSearchUrl, replaySearchUrl, or the tile-replay-search-button testid.
    • Fix: Extract the eligibility logic into a pure predicate and add unit tests for each branch, including the promotable single-series-condition case versus the multi-condition/condition-plus-where rejection.
    • testing
🔵 P3 nitpicks (2)
  • packages/app/src/DBDashboardPage.tsx:715 -- The URL derives from/to from the fresh top-level dateRange but pulls where/filters/select from queriedConfig, which lags by one render cycle because it is populated in a useEffect; a click within that sub-frame window can open a search mixing a fresh time range with stale filters.
    • Fix: Derive the whole URL (including from/to) from queriedConfig, or withhold the action until queriedConfig reflects the current inputs.
  • packages/app/src/ChartUtils.tsx:967 -- buildEventsSearchUrl performs a notifications.show UI side effect while also being invoked during render via useMemo; the replay path is safe only because the caller's metricTables guard happens to match isMetricChartConfig.
    • Fix: Make buildEventsSearchUrl side-effect-free (return a reason to the caller) so no render-phase caller can trigger a toast regardless of guard alignment.

Reviewers (5): testing, maintainability, security, julik-frontend-races, learnings-researcher.

Testing gaps:

  • No test asserts replaySearchUrl is null for metric/non-searchable sources or non-builder (raw SQL / PromQL) configs.
  • No test covers the non-promotable per-series-condition rejection (multiple conditions, or a condition combined with a non-empty where).
  • No test pins that buildEventsSearchUrl does not call notifications.show on the replay path, the invariant protecting render purity.
  • Coverage note: correctness, kieran-typescript, project-standards, and agent-native reviewers were still executing at synthesis time; the orchestrator's own correctness pass found no material defect, but their dimensions are only partially covered here.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add “Replay search” action to dashboard widgets

1 participant