Altinity / Altinity/altinity-sql-browser
Add FlameGraph panel for hierarchical profiling results
Nessuno ha ancora preso questa issue.
- Lingua principale
- TypeScript
- Stelle
- 8
- Fork
- 2
- Merge medio
- 1h 34m
- PR unite (30g)
- 6
Descrizione
Summary
Add a first-class FlameGraph panel for hierarchical profiling results, suitable for ClickHouse system.trace_log queries and other stack/call-tree datasets.
Adopt Grafana's flat nested-set result contract and use d3-flame-graph as the preferred implementation path, behind a SQL Browser-owned adapter and panel lifecycle wrapper. Do not embed Grafana's React component or replace Chart.js solely for this feature.
Research
Grafana
Grafana has a built-in Flame graph visualization and an independently published @grafana/flamegraph component.
Grafana's data contract is a flat table in depth-first order with these fields:
| Field | Meaning |
|---|---|
level |
Zero-based stack depth |
value |
Inclusive sample count or duration |
self |
Exclusive sample count or duration |
label |
Frame/function name |
color |
Optional explicit color |
This is attractive for SQL results because the browser does not need a nested JSON object. Rows can stream as an ordinary table and be validated deterministically.
Grafana supports:
- flame-graph and table views;
- zooming into a frame;
- text search/highlighting;
- tooltips with inclusive and self values;
- optional sandwich-style/profile navigation in profiling integrations.
Sources:
- https://grafana.com/docs/grafana/latest/visualizations/panels-visualizations/visualizations/flame-graph/
- https://github.com/grafana/grafana/tree/main/packages/grafana-flamegraph
The published Grafana component is not a suitable direct dependency for this project. It pulls in React, Grafana UI/data packages, Emotion, lodash, and other runtime dependencies. SQL Browser is a vanilla, single-file application with no third-party network requests, so importing that package would be disproportionate.
Apache Superset
Apache Superset does not currently register a built-in FlameGraph visualization in its main visualization preset. Its built-in hierarchical alternatives include Tree, Sunburst, Treemap, Graph, and Sankey, mostly through ECharts.
Superset's architecture allows a FlameGraph to be added as a custom visualization plugin, but it is not an out-of-the-box chart type.
Sources:
- https://superset.apache.org/docs/configuration/visualization-plugins/
- https://github.com/apache/superset/blob/master/superset-frontend/src/visualizations/presets/MainPreset.ts
d3-flame-graph
d3-flame-graph is the preferred renderer to prototype before writing a custom SVG implementation.
It is a purpose-built Apache-2.0 FlameGraph component with:
- SVG rendering;
- click-to-zoom and reset;
- search and match highlighting;
- tooltips;
- inverted/icicle orientation;
- self-value support;
- custom color mapping;
- an explicit
destroy()lifecycle; - ESM output and modular D3 dependencies.
Source:
Its input is a nested tree rather than Grafana's flat rows:
{
"name": "root",
"value": 100,
"children": [
{
"name": "functionA",
"value": 70
}
]
}
SQL Browser therefore owns a pure, tested adapter from the flat result contract into the nested d3-flame-graph hierarchy. The adapter remains independent of the renderer and can support a native implementation later.
The dependency does not remove SQL Browser's responsibility for:
- schema and hierarchy validation;
- keyboard focus and navigation;
- accessible frame labels;
- theme integration;
- result-size limits;
- resize and teardown integration;
- safe tooltip content;
- bundle-size review.
Do not import the full monolithic d3 package. Use only the dependency graph required by d3-flame-graph and record the resulting production bundle increase.
Implications for SQL Browser
The current application uses Chart.js for ordinary bar/line/area/pie charts and has a closed panel configuration union. Flame graphs are not a natural Chart.js chart type. Implement this as a dedicated panel arm rather than forcing it into the existing chart-family abstraction or replacing Chart.js.
Proposed v1 design
Add an explicit panel configuration:
{
"panel": {
"cfg": {
"type": "flamegraph",
"level": "level",
"value": "value",
"self": "self",
"label": "label",
"color": "color"
}
}
}
color should be optional. Role fields should use column names, not indexes, matching the Logs panel's resilience to reordered result schemas.
Required result contract
Rows must be in depth-first traversal order.
Required columns:
level: non-negative integer;value: finite non-negative number;self: finite non-negative number;label: string.
Optional:
color: CSS-compatible color string.
Validation rules:
- first row must start at level 0;
- depth may increase by at most one between adjacent rows;
self <= value;- child spans must fit within their parent's inclusive value;
- malformed input produces a panel diagnostic and falls back safely rather than throwing.
The exact sibling-width accounting should follow Grafana's nested-set transform semantics so Grafana-compatible SQL output renders equivalently.
Flat-row adapter
Implement a pure transform that:
- resolves configured column names;
- validates every row and depth transition;
- constructs the nested hierarchy expected by
d3-flame-graph; - preserves inclusive and self values separately;
- handles or explicitly rejects multiple roots;
- produces deterministic diagnostics with result-row paths;
- never mutates the result rows.
The renderer must consume only the validated adapter output, never raw query rows.
Rendering recommendation
Use d3-flame-graph for the v1 renderer, wrapped by the existing panel registry and lifecycle:
- mount into a panel-owned host;
- map validated tree nodes into the library's data shape;
- provide SQL Browser-owned tooltip formatting;
- expose click-to-zoom and reset/breadcrumb controls;
- wire text search and matching-frame emphasis;
- derive a deterministic theme-aware palette when
coloris absent; - update dimensions through the existing panel resize lifecycle;
- call
destroy()and remove all wrapper listeners/observers on repaint or teardown.
Add an accessibility wrapper because mouse interaction alone is insufficient:
- keyboard-focusable visible frames or an equivalent navigable frame list;
- Enter/Space to zoom;
- Escape or a dedicated control to reset one level;
- accessible labels containing frame name, inclusive value, self value, and percentage;
- visible focus indication in light and dark themes.
A native SVG renderer remains the fallback if the prototype fails the bundle, lifecycle, performance, accessibility, or styling gates.
Prototype decision gate
Before completing full integration, create a focused prototype and record:
- minified and compressed production bundle increase;
- frame-count performance at representative sizes;
- responsiveness inside Workbench and Dashboard tiles;
- cleanup behavior across repeated renders;
- keyboard/accessibility gaps and wrapper cost;
- theme and print/export compatibility.
Proceed with d3-flame-graph unless one of these is materially unacceptable. Do not replace Chart.js as part of this issue.
UX scope
V1 should include:
- FlameGraph entry in the panel picker;
- explicit column-role controls;
- zoom into frame and reset/breadcrumb navigation;
- text search/highlighting;
- tooltip showing label, inclusive value, self value, and percentage of the current root;
- empty, loading, invalid-schema, and result-too-large states;
- Workbench and Dashboard rendering through the shared panel registry;
- read-only Dashboard behavior without write-back callbacks.
Out of scope for v1:
- differential flame graphs;
- left-heavy/sandwich comparison;
- profile backend integration or Pyroscope API support;
- automatic querying of
system.trace_log; - automatic FlameGraph detection. It should be an explicit panel type initially;
- replacement of Chart.js for existing chart panels.
Performance and safety
Define and test a maximum rendered frame count. Suggested initial behavior:
- render up to a documented cap;
- display a clear truncation/aggregation message above the cap;
- avoid one SQL Browser event listener per rectangle where possible;
- destroy all library, tooltip, search, and resize state through the panel lifecycle;
- never evaluate labels or color strings as HTML;
- sanitize or reject invalid explicit colors;
- do not expose raw result values through unsafe DOM insertion.
Acceptance criteria
- Query Spec schema and generated types include
panel.cfg.type = "flamegraph"with name-based roles. - The panel registry, picker, resolver, cloning, normalization, validation, and fallback paths recognize the new type.
- A pure adapter converts valid Grafana-style flat nested-set rows into the nested renderer model.
- The adapter reports deterministic diagnostics for missing, renamed, malformed, negative, non-finite, or structurally invalid data without throwing.
- A valid result renders the expected hierarchy through
d3-flame-graph. - Click zoom, reset/breadcrumb navigation, search highlighting, and tooltips work in Workbench and Dashboard.
- Multiple roots are either supported explicitly or rejected with a clear diagnostic; choose and document one behavior.
- SQL Browser adds keyboard navigation, accessible frame labels, and visible focus behavior beyond the library defaults.
- The renderer is usable in light and dark themes.
- Rendering is bounded for large profiles and cleanup leaves no listeners, observers, SVG state, or tooltips behind.
- Repeated repaint and resize cycles do not duplicate controls or event handlers.
- Unit tests cover transform, validation, role resolution, lifecycle, and renderer integration at repository coverage thresholds.
- Browser tests cover zoom, search, tooltip, keyboard operation, Dashboard rendering, teardown, and resize on Chromium, Firefox, and WebKit.
- The PR records the exact
d3-flame-graphversion, license, dependency tree, and production bundle-size impact. - No React, Grafana UI packages, full
d3bundle, ECharts, or replacement chart framework is added. - If the dependency fails the prototype decision gate, the PR documents the result before switching to a native SVG renderer.
Suggested implementation sequence
- Pure Grafana-compatible flat-row parser, validator, and nested-tree adapter.
- Small
d3-flame-graphprototype with bundle/performance/lifecycle measurements. - Schema/type and panel-registry integration.
- Panel lifecycle wrapper, tooltip, zoom, reset, and resize integration.
- Search plus SQL Browser-owned keyboard accessibility.
- Dashboard lifecycle, truncation, teardown, and cross-browser tests.
- Add a documented ClickHouse profiling query example after validating it against supported server versions.
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia individuando lo schema di Query Spec e i tipi generati, il registro e il selettore dei pannelli, il resolver, la normalizzazione, la validazione e il ciclo di vita condiviso dei pannelli menzionati nell’issue. Prototipa prima il puro adattatore per righe piatte, quindi esegui i test unitari e browser del repository; il lavoro è completato quando viene superata l’intera checklist di accettazione, inclusi accessibilità, rendering vincolato, teardown e revisione del bundle.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- clickhouse, d3js, typescript
- Ambito
- databases, frontend
- Tipo di issue
- Funzionalità
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Tranquilla
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 28/100