feat: Wire heatmap chart into dashboard editor and tile rendering#2107
feat: Wire heatmap chart into dashboard editor and tile rendering#2107alex-fedotyev wants to merge 24 commits intomainfrom
Conversation
- Add Heatmap tab to chart editor form with IconGrid3x3 icon - Create HeatmapSeriesEditor with value expression (Y-axis) and count expression (intensity) inputs - Add heatmap display type to displayTypeToActiveTab mapping - Add heatmap preview rendering in ChartPreviewPanel - Add heatmap tile rendering in DBDashboardPage - Add heatmap validation: single series, required value expression - Constrain heatmap to single series (no Add Series / ratio) Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
E2E Test Results✅ All tests passed • 131 passed • 3 skipped • 1057s
Tests ran across 4 shards in parallel. |
…ormat, reduce chart whitespace - When switching to Heatmap with a trace source, auto-fill value expression with getDurationMsExpression and set numberFormat to duration with factor 0.001 for proper Y-axis labels (4ms, 100ms, 1.2s) - Pass numberFormat from config through to DBHeatmapChart in both ChartPreviewPanel and DBDashboardPage for correct tick formatting - Reduce Stack gap in ChartContainer from default to 4px to minimize whitespace above the chart area Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
…ctivity in editor/dashboard - Add effect to populate duration defaults when source changes while already in heatmap mode (not just when switching to heatmap tab) - Disable drag-to-select and hide 'Click & Drag' prompt in Heatmap when onFilter is not provided (chart editor and dashboard contexts) - Keep hover tooltip with Y/Count values for read-only inspection Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
…ngs button for heatmap - Fill Value field with getDurationMsExpression and Count field with count() when switching to Heatmap with a trace source (visible text, not just behind the scenes) - Add Display Settings button below heatmap editor, same pattern as other chart types, opening ChartDisplaySettingsDrawer for number format configuration Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
…hboards - Extract HeatmapSettingsDrawer into shared component used by both search Event Deltas and chart editor/dashboard contexts - Remove Value/Count fields from the main heatmap editor form — move them into the Heatmap Settings drawer (Scale, Value, Count) - Replace 'Display Settings' button with 'Heatmap Settings' button that opens the same drawer as search Event Deltas gear icon - Pass scaleType (log/linear) from form state through to DBHeatmapChart in preview panel and dashboard tiles - Pre-populate Value with getDurationMsExpression and Count with count() from data source config, editable via Heatmap Settings Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
…artContainer gap - Add padding: [8,0,0,0] to uPlot options to reduce whitespace above the topmost Y-axis tick in heatmap charts - Set lockScroll=false on HeatmapSettingsDrawer to prevent layout shift when opening settings inside a dashboard edit modal - Restore ChartContainer gap to 'xs' (was incorrectly set to 4px affecting all chart types) Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
…ChartContainer changes - Wrap HeatmapSettingsDrawer in Portal so it doesn't participate in the flex layout of the editor form, preventing content shift when opening/closing settings in dashboard edit modal - Revert ChartContainer gap/margin changes to preserve existing spacing for all chart types Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
Pass autoRun to EditTimeChartForm in the dashboard edit modal so saved charts (including heatmaps) render their preview immediately when opened for editing, matching the Chart Explorer behavior. Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
… layout shift Move the HeatmapSettingsDrawer out of HeatmapSeriesEditor and render it at the EditTimeChartForm top level (same pattern as ChartDisplaySettingsDrawer). This prevents any DOM insertion from affecting the flex layout between the settings button and run button when the drawer opens/closes. Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
🟡 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
|
PR Review
✅ Core feature logic (extraction of |
…le form, revert ChartContainer - Extract toHeatmapChartConfig() helper into DBHeatmapChart.tsx, eliminating duplicated config construction and unsafe casts in DBDashboardPage and ChartPreviewPanel - Export HeatmapChartConfig and HeatmapSelectExtras types for typed access to countExpression and heatmapScaleType on select items - Add useEffect to sync HeatmapSettingsDrawer form when defaultValues change (prevents stale closure when source changes while drawer open) - Fully revert ChartContainer to original (no gap change) Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
- Remove export from HeatmapSelectExtras (fixes knip unused export) - Memoize heatmapSettingsDefaults in EditTimeChartForm and DBSearchHeatmapChart to prevent form.reset on every parent render Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
- Increase Y-axis size from 60px to 70px so labels like '1000ms' and '.67min' are not truncated - Add 8px right padding so X-axis labels at the right edge are not clipped by the container overflow Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
- Replace fixed Y-axis size with dynamic measurement that uses
canvas measureText on the actual formatted tick labels + padding
- Add formatDurationMsCompact for axis ticks: shorter units ('m'
instead of 'min'), values under 2min stay as seconds (no '.67min'),
fewer decimal places throughout
- Full formatDurationMs still used in tooltips via the same formatter
Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
- Add gap=8 to X-axis to prevent tick labels from overlapping - Replace IIFE patterns with HeatmapTile and HeatmapPreview components in DBDashboardPage and ChartPreviewPanel Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
…all containers Set space=60 on the X-axis so uPlot allocates at least 60px per tick interval. This prevents labels from being packed together in narrow contexts like the search heatmap (260px height). The fix is in the shared opt constant used by all heatmap renderings. Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
…lipping Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
- Remove 'heatmap' from TABS_WITH_GENERATED_SQL since the heatmap builds its own queries internally (min/max + bucket), so the Generated SQL section would show misleading SQL - Remove stable form object from useEffect dependency array in HeatmapSettingsDrawer Co-authored-by: Alex Fedotyev <alex-fedotyev@users.noreply.github.com>
pulpdrew
left a comment
There was a problem hiding this comment.
Cool stuff, but I have some suggestions.
Also, do we have a followup ticket to update the external API implementation+docs+tests to cover this new visualization type?
| const traceSource = | ||
| tableSource?.kind === SourceKind.Trace && | ||
| tableSource.durationExpression | ||
| ? tableSource | ||
| : undefined; |
| <HeatmapSettingsDrawer | ||
| opened={heatmapSettingsOpened} | ||
| onClose={closeHeatmapSettings} | ||
| connection={tableConnection} | ||
| parentRef={parentRef} | ||
| defaultValues={heatmapSettingsDefaults} | ||
| scaleType={heatmapScaleType} | ||
| onScaleTypeChange={handleHeatmapScaleTypeChange} | ||
| onSubmit={handleUpdateHeatmapSettings} | ||
| /> |
There was a problem hiding this comment.
I understand that we're probably doing it this way because the Event Deltas heatmap uses a drawer for the settings. And that makes sense because it is restricted to Trace sources and a particular use case, which have good defaults.
In the context of the chart editor, the point is to be able to edit the chart, and I think it makes less sense to hide the heatmap settings in a drawer. Particularly because for metric and log sources, the defaults error out and it's not at all clear where I would set a 'value expression' if I'm not already aware that the settings are hidden in display settings.
I'd also suggest that the value and count expressions are not display settings but are just as central to this chart as the series are a part of the line chart or table chart - they should be front and center IMO
| } | ||
|
|
||
| // Validate number and pie charts only have one series | ||
| // Validate number, pie, and heatmap charts only have one series |
There was a problem hiding this comment.
Please update the unit tests to cover the changes in this file
| chartConfigForExplanations?: ChartConfigWithOptTimestamp; | ||
| onSubmit: (suppressErrorNotification?: boolean) => void; | ||
| openDisplaySettings: () => void; | ||
| openHeatmapSettings?: () => void; |
There was a problem hiding this comment.
Does this need to be optional? Looks like it is always provided
| openHeatmapSettings?: () => void; | |
| openHeatmapSettings: () => void; |
| setValue={setValue} | ||
| tableSource={tableSource} | ||
| onSubmit={onSubmit} | ||
| onOpenDisplaySettings={openHeatmapSettings ?? openDisplaySettings} |
There was a problem hiding this comment.
Would we ever want to open the display settings here?
| onOpenDisplaySettings={openHeatmapSettings ?? openDisplaySettings} | |
| onOpenHeatmapSettings={openHeatmapSettings} |
| import { SQLPreview } from './ChartSQLPreview'; | ||
|
|
||
| /** Compact duration labels for axis ticks — fewer decimals, shorter units. */ | ||
| function formatDurationMsCompact(ms: number): string { |
There was a problem hiding this comment.
Thoughts on making this a shared util alongside formatDurationMs in packages/app/src/utils.ts?
There was a problem hiding this comment.
It would also be great if we could add some unit tests here.
| ]; | ||
| setValue('select', heatmapSeries); | ||
| setValue('series', heatmapSeries); | ||
| setValue('series.0.countExpression' as any, 'count()'); |
There was a problem hiding this comment.
We should add countExpression to the SelectItem schema/type so that we don't need a cast here
| setValue('series.0.countExpression' as any, 'count()'); | ||
| if (traceSource) { | ||
| setValue('numberFormat', { | ||
| output: 'duration' as any, |
There was a problem hiding this comment.
This is not needed. Casting as any will hide any future type errors, and should be avoided when possible.
| output: 'duration' as any, | |
| output: 'duration', |
| setValue('select', heatmapSeries); | ||
| setValue('series', heatmapSeries); | ||
| setValue('series.0.countExpression' as any, 'count()'); | ||
| setValue('numberFormat', { output: 'duration' as any, factor: 0.001 }); |
There was a problem hiding this comment.
This cast is not needed
| setValue('numberFormat', { output: 'duration' as any, factor: 0.001 }); | |
| setValue('numberFormat', { output: 'duration', factor: 0.001 }); |
| defaultValues: HeatmapSettingsValues; | ||
| scaleType: HeatmapScaleType; | ||
| onScaleTypeChange: (v: HeatmapScaleType) => void; | ||
| onSubmit: (v: HeatmapSettingsValues) => void; |
There was a problem hiding this comment.
Would it make sense to combine scaleType into HeatmapSettingsValues instead of treating them separately here and having to handle both handleHeatmapScaleTypeChange and handleUpdateHeatmapSettings in the parent component?
Heatmap charts require trace data (duration expression) to work properly. Non-trace sources would error out with no guidance. Instead of adding complex error messaging, filter the source dropdown to only show trace sources when heatmap display type is selected.
|
Pushed a587ca2 — restricts the data source picker to trace sources only when heatmap display type is selected. This addresses:
The Still working through the remaining review items (removing |

What
Wires the existing
DBHeatmapChartcomponent andDisplayType.Heatmapenum into the chart editor, dashboard tile rendering, and unifies display settings across all heatmap contexts (search Event Deltas, chart editor, dashboards).Why
Users should be able to create and view heatmap charts from the chart editor and dashboards, alongside existing chart types. Heatmaps visualize distributions over time (e.g., latency distributions) and were previously only available in the search Event Deltas view.
Changes
Shared Display Settings Drawer (
HeatmapSettingsDrawer.tsx):DBSearchHeatmapChart.tsxinto a reusable componentdefaultValuesmemoized at call sites to prevent unnecessary form resetsChart Editor (
EditTimeChartForm,ChartEditorControls,HeatmapSeriesEditor):IconGrid3x3icongetDurationMsExpression(source)andcount()when a Trace source is selected (on tab switch or source change)numberFormat: { output: 'duration', factor: 0.001 }for proper Y-axis labelsHeatmapContainer)Dashboard Tiles (
DBDashboardPage):HeatmapTilecomponent rendersDBHeatmapChartviatoHeatmapChartConfig()helperautoRunpassed toEditTimeChartFormin dashboard edit modal so saved charts preview immediatelynumberFormatandscaleTypepassed through from saved configChart Preview (
ChartPreviewPanel):HeatmapPreviewcomponent renders heatmap in the chart editor preview areaHeatmap UX improvements (
DBHeatmapChart.tsx):ctx.measureText()— measures actual formatted tick labelsformatDurationMsCompact):minstead ofmin, values under 2min stay as seconds, fewer decimalsgap: 10+space: 60prevents label overlap in narrow containerspadding: [8, 8, 0, 4]prevents label clipping at edgesonFilteris not provided (editor/dashboard); hover tooltip still shows for inspectiononFilteris wiredConfig helper (
toHeatmapChartConfig):HeatmapChartConfigformatHeatmapChartConfigtype fromDBHeatmapChart.tsx