Skip to content

Draft: Explore as search-first visualization (prototype) - #2985

Draft
elizabetdev wants to merge 41 commits into
mainfrom
elizabet/search-view-switcher
Draft

Draft: Explore as search-first visualization (prototype)#2985
elizabetdev wants to merge 41 commits into
mainfrom
elizabet/search-view-switcher

Conversation

@elizabetdev

Copy link
Copy Markdown
Contributor

What this is trying to do

This is a prototype of Explore: one place to search telemetry and, when the question needs a shape, turn that search into a chart — without becoming a second dashboard editor.

Search today is a results table. Charts live on dashboards, behind a different mental model (tiles, display settings, formula rows). The bet here is that people start with “what happened?” and only sometimes need “show me that as a number / time series / pie.” Explore should feel like Search first, visualization second.

Product intent

  • List is the default. Event views (list, patterns, deltas) stay one click away. Chart types should not compete with reading logs.
  • Visualization is opt-in. A split Visualize control enters the last chart (time series by default). Visualize as is a menu for number, grouped table, bar, pie, treemap — types that mostly matter when you are about to pin something to a dashboard.
  • The query is the product. Multi-series cards (alias, per-series where, add/remove) and formula cards (A / B, click-to-insert letters) change what you asked. Tile chrome (colors, fill-nulls, number format) stays on Add to dashboard / the tile editor.
  • Handoff, not duplication. Add to dashboard should carry the series + formulas you already built, so Explore is the scratchpad and the dashboard is the saved artifact.

What is explicitly not the goal

  • Shipping a polished replacement for Search or Chart Explorer.
  • Matching the tile editor’s formula row / As Ratio / display-settings rail on this page.
  • A final information architecture — the view switcher, SQL mode, and series/formula cards are here to try the model, not freeze it.

Test plan

Prototype only; treat this as a walkthrough, not a merge checklist.

  • Open Explore from nav, run a log search, confirm List is the default
  • Visualize → time series; Visualize as → number / pie; List still feels like the home view
  • Add a second series + a formula (A / B) via letter chips; Run; Add to dashboard keeps both
  • Metric source and SQL mode only show Visualize controls (no List)
  • Existing Search page is unchanged

Made with Cursor

elizabetdev and others added 30 commits July 19, 2026 19:25
…r/pie/treemap/heatmap/patterns)

- Add global DisplayType.Treemap + DBTreemapChart renderer (recharts), wired into
  Chart Explorer tabs/preview and raw-SQL/query-param maps
- Unify search analysisMode into a single URL-backed view switcher with legacy
  aliasing (results->list, delta->heatmap, pattern->patterns)
- Add inline aggregation config strip (aggFn/value/groupBy/topN) with smart defaults
- Refactor DBSearchPage render into a per-view switch; hide histogram for aggregated
  views; move mode selection out of the filter sidebar into a top toolbar

Co-authored-by: Cursor <cursoragent@cursor.com>
- SearchColumnPicker: checklist dropdown (search + All/None + Apply) that replaces
  the SELECT SQL editor for the List view; commits the comma-separated select string
- SearchSortMenu: structured sort control replacing ORDER BY. Value/Name + direction
  for aggregated views (table/bar/pie/treemap); column + direction for List; revert
- Thread agg sort state (sort/sortDir) through useSearchAggConfig into the aggregated
  view config (aliases the metric as "Value" for stable ordering)

Co-authored-by: Cursor <cursoragent@cursor.com>
…h toolbar

Remove the SELECT and ORDER BY SQL editors from the top query bar now that the
Columns picker and Sort menu cover the common cases. Keep a power-user escape
hatch: a List-view 'Advanced' popover in the results toolbar still exposes the
raw SELECT and ORDER BY editors for expressions/aliases/multi-column ordering.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…nput

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Allow metric sources in the search page source selector. Since metrics
have no raw rows, the view switcher hides List / Event deltas / Event
patterns for metric sources and only offers the aggregated chart views
(time series, number, summary table, bar, pie, treemap), auto-switching
away from List when a metric source is chosen.

The aggregation bar swaps the free-text value expression for the metric
name/type picker (MetricNameSelect) and drops count-style agg fns.
aggViewChartConfig now carries metricTables + metric select fields, and
holds off querying until a metric name is picked (showing a prompt
instead of the 'no query support for metric type=gauge' error).

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the original search experience intact at /search (restored from
main) and move the in-progress view-switcher redesign to a new /explore
page, surfaced in the nav with an "Experimental" badge.

- Restore DBSearchPage.tsx to the main version so /search is unchanged
- Add DBExplorePage.tsx (the redesign) with /explore routes and
  self-navigation pointed at /explore
- Re-add the analysis-mode Tabs in DBSearchPageFilters, guarded on
  setAnalysisMode so the old page keeps them and Explore stays clean
- Support a configurable nav badge (badgeLabel/badgeColor) and add the
  Explore nav link with an "Experimental" badge

Co-authored-by: Cursor <cursoragent@cursor.com>
…ands

Restructure the experimental Explore page toolbar into three bands per the
new wireframes:

- Context band: source selector, "Saved views" button (opens the saved
  searches flyout), a save-status pill (Unsaved/Saved/edited), contextual
  Save / Save as... actions, an Alerts dropdown, and an overflow menu.
- Query band: query input with an expand/collapse toggle plus time picker,
  Live, and Run controls.
- Results band: a combined stats line (result count, scanned rows, elapsed)
  above the view switcher and Sort / Columns / generated-SQL / export row.

Extract ExploreContextBand and ExploreResultsToolbar into a dedicated
components/Explore folder, and add the SavedSearchesFlyout used by the
context band.

Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce ExploreQueryEditor, a self-contained query editor card for the
experimental Explore page, so the Explore layout can evolve without touching
the shared SearchWhereInput used by the Search page.

- Bordered card with SQL/Lucene language tabs on the left and the time picker,
  Live, Run, and expand toggle in the header on the right.
- Reuses the existing SQL (CodeMirror) and Lucene (autocomplete) editors for
  the body.
- Default the Explore query language to SQL.
- Add an opt-in showLineNumbers prop to SQLInlineEditor (default off) and
  enable it for the Explore SQL editor.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the reuse-based Explore query editor with a CodeMirror-backed
QueryEditor so both SQL and Lucene get line numbers and syntax highlighting
in a single unified editor.

- Add a presentational QueryEditor (SQL via the app's ClickHouse dialect,
  Lucene via a small custom StreamLanguage highlighter), theme-aware, with
  Enter-to-submit and Tab-to-complete.
- ExploreQueryEditor now wraps QueryEditor with react-hook-form wiring, the
  ClickHouse field list for autocomplete, and the syntax-reference modal.
- Add @codemirror/language dependency.

Co-authored-by: Cursor <cursoragent@cursor.com>
Remove the top header block (breadcrumbs, editable title, created/updated
byline) from the Explore page and surface the Favorite toggle and Tags
control inside the context band instead, so all saved-view controls live in
the new toolbar structure.

Co-authored-by: Cursor <cursoragent@cursor.com>
The @uiw basicSetup only registers CodeMirror's defaultHighlightStyle as a
fallback, so identifiers and operators stayed uncolored and the editor looked
unhighlighted. Add an explicit, high-priority HighlightStyle shared by SQL and
Lucene with mid-tone colors that read on both light and dark backgrounds.

- Add @lezer/highlight dependency.

Co-authored-by: Cursor <cursoragent@cursor.com>
Two focused UX improvements to the Explore query editor:

- Open the field/variable completion list as soon as the editor is focused,
  so users can discover available fields without knowing exact names.
- Enter now submits the query and keeps the caret in the editor, so the query
  can be tweaked while results load instead of losing focus on submit.

Co-authored-by: Cursor <cursoragent@cursor.com>
… toolbar

- Add an "Add to dashboard" button for chart-tile views that opens the shared
  SaveToDashboardModal with the current aggregation rendered as a tile config.
- Move "Show generated SQL" and "Export" into a 3-dots overflow menu.
- Make the results controls (Sort, Columns, Add to dashboard, overflow) all
  consistent bordered secondary buttons so they no longer feel lost.

Co-authored-by: Cursor <cursoragent@cursor.com>
Surface Error/Warning counts as clickable pills in the Explore results
toolbar for log sources, backed by a parallel grouped-count query.
Clicking a pill scopes the search to (or clears) that severity via a new
`setIncludedValues` filter mutator, which sets a column's included set to
an OR-set of values in one update.

Collapse the results/scanned-rows/elapsed line into a single compact
"<N> results · <N> scanned · <N>ms" stat with abbreviated scanned rows,
and color the severity pills with the shared semantic status tokens.

Also rename the aggregated table view to "Grouped table" and add a save
icon to the "Save view" button.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add a chart-explorer-style Builder | SQL toggle to the Explore query bar. In
SQL mode the query bar becomes a full raw-SQL editor (sqlTemplate + macros)
and results render as a user-selectable chart display type, reusing the
existing raw-SQL config/execution pipeline. SQL mode is URL-only for now and
is not persisted to saved searches (Save is disabled with a tooltip).

Co-authored-by: Cursor <cursoragent@cursor.com>
Render the error/warning severity summary as secondary toolbar buttons with
status icons and a count chip (matching the Columns/Sort controls), tinting
with the semantic status color only while active. Treat a bucket as active via
a subset test so both severities can be filtered at once.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Auto-expand the builder query editor (remove the manual expand toggle
  and line numbers; grow with content up to a max height, then scroll)
- Drive SQL-mode chrome off the live editor toggle so builder-only
  controls (histogram, severity, sort/columns, agg controls) hide the
  instant you switch to SQL, while query execution still waits for Run
- Unify the Builder/SQL switch and SQL/Lucene toggle into a single
  three-way control (SQL | Lucene | Advanced)

Co-authored-by: Cursor <cursoragent@cursor.com>
Merge the read-only stats line and the view/actions line into one row: the
view switcher, severity pills, and result/scanned-row/elapsed stats sit on the
left, while add-to-dashboard and the overflow menu stay pinned right. A
shape-the-view row now appears only when the active view exposes controls
(aggregation on the left; columns / sort on the right).

- Partition the view switcher into raw vs chart views separated by a divider so
  the icon strip reads as two related clusters.
- Let the toolbar's left cluster wrap gracefully so the severity pills and stats
  are never pushed under the actions on narrow layouts.
- Flatten the query editor so the mode toggle, editor, and filters no longer sit
  inside a card.

Co-authored-by: Cursor <cursoragent@cursor.com>
… focus

Keep the sidebar as a single Filters heading, leave Experimental in sentence case, and defer CodeMirror autocomplete so focus no longer updates the editor mid-cycle.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the one-line aggregation bar with series cards so Explore chart views can author multiple series, per-series Where, and aliases. Share those cards with the tile editor and move display settings into a persistent Tile settings rail.

Co-authored-by: Cursor <cursoragent@cursor.com>
elizabetdev and others added 2 commits August 24, 2026 12:12
Letter-ref formulas (A / B) now sit on the same card chrome as series, persist in the URL, and export with Add to dashboard.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep List as the primary results view and move chart types behind a split Visualize control with a type menu, instead of a row of chart icons.

Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot

changeset-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: babe5c8

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

This PR includes changesets to release 4 packages
Name Type
@hyperdx/app Minor
@hyperdx/common-utils Patch
@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 24, 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 26, 2026 4:06pm
hyperdx-storybook Ready Ready Preview Aug 26, 2026 4:06pm

Request Review

@greptile-apps

greptile-apps Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The prototype adds a search-first Explore page that can transition from event results into aggregated visualizations and hand its query configuration to dashboards.

  • Adds Explore routes and search, SQL, filtering, saved-search, live-tail, series, formula, and visualization workflows.
  • Extends shared chart, filter, dashboard, and query models for the new visualization and comparison capabilities.
  • Adds supporting unit and end-to-end coverage and updates application dependencies and theme variants.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/app/src/DBExplorePage.tsx Introduces the Explore page orchestration for source selection, query state, event results, visualization, saved searches, live tail, and dashboard handoff.
packages/app/src/components/Explore/ExploreQueryEditor.tsx Adds the Explore query-editing surface for search filters and raw SQL.
packages/app/src/components/Search/searchViews.tsx Defines Explore result-view selection and display-type mapping.
packages/common-utils/src/filters.ts Extends shared filter handling to support the comparison behavior used by Explore.
packages/api/src/routers/external-api/v2/utils/dashboards.ts Handles unsupported treemap configurations explicitly during external dashboard conversion.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  User[User] --> Explore[Explore search]
  Explore --> Query[Search filters or raw SQL]
  Query --> Results[Event results]
  Results --> Views[Patterns, deltas, or visualization]
  Views --> Series[Series and formulas]
  Series --> Dashboard[Add to dashboard]
Loading

Reviews (4): Last reviewed commit: "feat(app): make Explore SQL-only and fol..." | Re-trigger Greptile

@@ -0,0 +1,3421 @@
import {

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.

P2 Oversized Explore page component

This new 3,421-line page combines query assembly, URL synchronization, saved-search handling, live-tail behavior, visualization rendering, and dashboard handoff despite the repository's 300-line file limit, making these flows substantially harder to review, test, and maintain safely. Please decompose the page into focused modules.

Context Used: CLAUDE.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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

@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

E2E Test Results

All tests passed • 0 passed • 0 skipped • 109s

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

Tests ran across 4 shards in parallel.

View full report →

Adding DisplayType.Treemap broke API exhaustiveness checks. Drop treemap
tiles from the external API until that schema exists, and raise the app
eslint warning cap for the new Explore files.

Co-authored-by: Cursor <cursoragent@cursor.com>
elizabetdev and others added 2 commits August 25, 2026 15:02
SQL and Lucene used to share one string with no warning on switch.
Default logs/traces to Search, snapshot before SQL/Raw, and let
filters be added as chips without typing a query.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep facet filters inside the query input as Lucene/SQL pills, including
one-sided comparisons like Slow spans, instead of a chip strip below it.

Co-authored-by: Cursor <cursoragent@cursor.com>
elizabetdev and others added 4 commits August 25, 2026 22:27
SQL WHERE as a peer tab asked people to pick a dialect before they had a
question. Search (Lucene + filter pills) and Raw SQL are the two modes
that map to real intent, so the middle option is gone: leaving Raw SQL
restores the last search instead of landing on a SQL WHERE clause, and
the Lucene/SQL converters that only existed to bridge the two dialects
go with it. Stored `whereLanguage: 'sql'` is still honoured so existing
saved searches keep running.

Also drops syntax highlighting from the Search editor. The workspace
resolves more than one @lezer/highlight copy, so the Lucene
StreamLanguage tree hands highlightTree a NodeProp where it expects a
Tag[] and throws "tags is not iterable" on the first typed token.

Co-authored-by: Cursor <cursoragent@cursor.com>
…hrome

Replace the Search | Raw SQL toggle with a SQL button that folds a full
statement editor out under the search box, closed by default. configType
already distinguished a query derived from the search from one the user owns,
so the generated/edited states map straight onto it: opening the panel changes
nothing, the first keystroke hands the query over, and Reset hands it back.
Every existing SQL-mode branch keeps working untouched.

The search box now reaches raw SQL. Only filter pills used to compile into
$__filters and the search text was silently dropped; it now rides along as a
filter, so searching keeps working after SQL takes over, and the panel warns
when an edit removes the macro. Switching can no longer destroy the search, so
useExploreQueryMode -- which existed only to confirm and clipboard it first --
is gone, along with the filter-to-Lucene/SQL helpers the old toolbar preview
needed. Generated templates are no longer persisted to the URL, since they are
derived from the search.

Also cut three rows of chrome above the results: Add filter moves into the
search field, the example chips, helper paragraph, in-field Search badge and
duplicate Show SQL toggle are removed, Columns / Sort fold into the results
row, and the view switcher labels only the view you are on.

Co-authored-by: Cursor <cursoragent@cursor.com>
The switcher was a hand-rolled row of Buttons and ActionIcons approximating a
segmented control. Mantine's SegmentedControl is already themed with exactly
that look, so use it and inherit the styling instead of maintaining a copy.
Inactive segments stay icon-only with a visually-hidden label, so the row still
pays for one label rather than one per view.

The chart type moves out of the switcher into its own pill built as a field with
a left addon: "As" is a fixed part of the frame, not something you press, and
the addon fill is what says so. It is always visible now, so the chart type is
legible and changeable from any view. In chart-only modes (metric sources, SQL)
the switcher would have rendered a single segment, so only the As pill shows.

Input addons had no shade of their own in either theme. Light mode had the field
tinted and the addon pure white; that is now inverted, with the field brightest
and anything attached to it stepping down into grey. Dark mode matched the addon
to the border, which read flat, so it drops below it.

Co-authored-by: Cursor <cursoragent@cursor.com>
The Explore search box only ever compiled to a SQL WHERE clause, but a
language toggle plus a remembered localStorage preference could silently
strand someone in Lucene with no hint of why their query stopped parsing.
Drop the choice: the bar is SQL, and its addon opens the syntax reference.

The raw-SQL editor moves out of the field to a toggle beside Live Tail,
labelled "Query editor" rather than "SQL" — it holds the whole statement,
$__filters and eventually PromQL included, so naming it after one language
described neither what it contains nor what the bar beneath it does.

Sharing that row: "Add filter" is icon-only and can now express >, >=, <
and <= against numeric fields; the chart-type picker appears only while a
chart is actually on screen; and the pattern expression takes that same
slot when Patterns is showing, instead of sitting between the chart and
the table it governs.

Co-authored-by: Cursor <cursoragent@cursor.com>
packages/app asked for @codemirror/language on ^6.12.4 while every other
CodeMirror package in the tree — lang-sql, codemirror, and the @uiw basic
setup that supplies the highlighter — asked for ^6.0.0 and landed on 6.10.1.
Both ranges are satisfiable, so Yarn installed two copies. That package owns
the Language facet and HighlightStyle, so the SQL parser registered its tree
in one copy while the highlighter searched the other, found nothing, and
rendered plain text without complaint. The same split is what made Lucene's
StreamLanguage throw `tags is not iterable` earlier on this branch; the crash
and the missing colour were one bug.

Align the range with its siblings in the same file. That collapses the tree to
a single copy and keeps the peer requirement satisfied, which deleting the
now-unused entry would not have. The syntaxHighlighting: false workaround in
the query bar can go with it, and the comment blaming duplicate
@lezer/highlight copies was aiming one package off.

The full-statement editor also gains line numbers and the shared code
background, so it reads as a code block rather than a tall text field.

Co-authored-by: Cursor <cursoragent@cursor.com>
@greptile-apps

greptile-apps Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review (101 files, 100 file limit).

Bypass the limit by tagging @greptile-apps to review.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant