@hyperdx/common-utils@0.21.0
Minor Changes
-
5cd7090: Add UI support for configuring an external Prometheus-compatible endpoint on a
connection. Modify Connections model to now have a boolean
isPrometheusEndpointfield and use host for storing the host. -
f40cf68: feat(dashboards): add a background trend sparkline to number tiles
Number tiles can now render a faint line or area sparkline behind the value,
derived from a time-bucketed version of the same query, so the value's trend
over the selected range is visible at a glance. This is handy for SLO /
error-budget tiles where the burn over time matters as much as the current
number. The sparkline inherits the tile's color by default and can be
overridden to any palette token. Configure it under Display Settings >
Background chart on a number tile. Available on builder number tiles (raw SQL
number tiles return a single value with no time dimension to bucket). -
17e1eb1: feat: Add an "external link" row-click action for dashboard table tiles
-
e03971b: refactor(theme): rename chart palette tokens from chart-1..10 to hue-named
(chart-blue, chart-orange, ...) and unify the categorical palette across HyperDX
and ClickStackStored configs from the initial color picker (#2265) keep working.
ChartPaletteTokenSchemastays strict (a plainz.enum, so itsz.input
matchesz.output— wrapping it inz.preprocesswould poison
validateRequest'sreq.bodyinference all the way up to
Dashboard.tiles[i].config.color). Migration of legacychart-1..chart-10
happens at five complementary points so no entry or wire-format path can slip
through, all composing over a single shared walker
(walkRawDashboardTileColorsincommon-utils) so the per-tile traversal
stays in lockstep:- Fetch-time / write-time (React):
normalizeDashboardTileColorsin
packages/app/src/dashboard.tsheals dashboards on read
(useDashboards/fetchLocalDashboards/fetchDashboards) and on write
(useUpdateDashboard/useCreateDashboard). Unresolvable color strings
(stale hexes, hand-edited values, forward-rolled future tokens) are
preserved so the user's chosen value survives a render pass — the strict
server-side schema surfaces a clear error on next save instead of the
normalizer quietly dropping the field. - JSON import:
DBDashboardImportPageruns
normalizeRawDashboardTileColorson the parsed JSON before the strict
DashboardTemplateSchema.safeParse, so templates exported from a
pre-rename deploy import cleanly. - Server-side GET response healing:
getDashboards/getDashboardin
packages/api/src/controllers/dashboard.tsrewrite legacy tile colors on
the way out. Pre-rename Mongo docs are served on the wire as
hue-named tokens so non-React HTTP clients (CI scripts, stale bundle
tabs during a rolling deploy, the external API) can round-trip
GET → PATCH without ever resurrectingchart-Nthrough the strict
schema. - Server-side write shim: the dashboards POST / PATCH routes mount
a request-body preprocessor that rewrites legacy tile colors before
validateRequestrunsChartPaletteTokenSchema. Catches non-React
HTTP callers (stale-bundle tabs during a rolling deploy, CI scripts,
MCP, the upcoming external-API parity work) for a one-release
deprecation window without weakening the schema's input/output equality.
The dashboard provisioner task applies the same shim before parsing
on-disk template files. - Render-time (belt-and-suspenders):
DBNumberChartand
ColorSwatchInputalso callresolveChartPaletteTokenfor tiles
constructed in memory between fetch and save (ChartEditorform
state, unit-test fixtures, hand-rolledTileliterals).
The migration preserves the HyperDX slot ordering from #2265 (slot 1 = brand
green, slot 2 = blue, etc.).ClickStack legacy color caveat: Pre-rename ClickStack used a different slot
ordering than HyperDX (--color-chart-1was brand blue#437eef, not brand
green). The migration map uses HyperDX slot ordering, so any ClickStack
dashboard saved via #2265 withcolor: 'chart-1'will flip from blue to
Observable green after migration. We chose this trade-off deliberately over
branching the legacy map by active theme:LEGACY_CHART_PALETTE_TOKEN_MAPlives
incommon-utils(shared with the API), and migration is one-shot persisted on
next save — theme-branching would couple common-utils to browser DOM state and
still produce wrong results for users whose active theme changed since the
original pick. Affected users can manually re-pick the desired hue via the (now
hue-labeled) color picker.The categorical palette is based on Observable 10, with
chart-blueswapped to
#437eefto match the brand link color
(--click-global-color-text-link-default); all other hues are straight from
Observable 10. The palette resolves identically on both themes — picking
chart-bluealways renders the brand blue. Brand identity for charts moves
entirely into the semantic layer:--color-chart-successand--color-chart-info
resolve to categoricalchart-green(#3ca951) andchart-blue(#437eef) on
both HyperDX and ClickStack, so success fills, info-level logs, and the
matching multi-series slots all read consistently across brands.Internally, JS (
CATEGORICAL_HEX_BY_TOKENinpackages/app/src/utils.ts) is
the source of truth for categorical hues —getColorFromCSSVariableand
getColorFromCSSTokenskipgetComputedStylefor categorical tokens since the
palette is unified across themes. The matching--color-chart-{hue}CSS vars in
_tokens.scssremain as a stylesheet-author affordance (inlinevar()use,
devtools inspection) and a hook for any future per-brand override. Semantic
tokens still resolve throughgetComputedStylebecause they genuinely vary per
theme. - Fetch-time / write-time (React):
Patch Changes
-
1d44098: fix: recover the SELECT-alias map when a query has ClickHouse-specific SQL the parser rejects
chSqlToAliasMapreturned an empty map whenever the rendered query contained
SQL that node-sql-parser's Postgresql dialect cannot parse, for example a
sampling CTE withgreatest(CAST(total / N AS UInt32), 1). An empty alias map
drops theWITHclauses that define the source's select aliases, so filters on
aliased columns (Event Patterns, histogram, alerts) failed withUnknown identifier. It now falls back to parsing only the outer SELECT projection,
which is all the alias map needs, so the aliases are recovered even when the
rest of the statement is unparseable. -
998ea5d: feat: Add option to fit time chart y-axis lower bound
-
ee90738: fix: Add sourceId to MCP Raw SQL Tile schema
-
5c46215: Bump
@clickhouse/client*to1.23.0-head.fae5998.1and fix the type
incompatibility it introduces.In
@clickhouse/client*1.23 each platform package (@clickhouse/client,
@clickhouse/client-web) bundles its own copy of the shared types, so their
ClickHouseSettingstypes — which reference the nominally-comparedSettingsMap
class — are no longer the same type as@clickhouse/client-common's. The shared
processClickhouseSettings()helper produces theclient-commonflavor, so
assigning it into the per-platform clients'query()now requires an explicit
bridge. Guard the existingas ClickHouseSettingsassertions at those
boundaries (node.ts,browser.ts,cli) with a scoped
@typescript-eslint/no-unsafe-type-assertiondisable, matching the existing
"client library type mismatch" pattern. No runtime behavior changes. -
45954c3: Import ClickHouse client types from the platform packages
(@clickhouse/client/@clickhouse/client-web) instead of the deprecated
@clickhouse/client-common. This makes the packages forward-compatible with
@clickhouse/client*1.23 (whereclient-commonis deprecated and each
platform package bundles and re-exports its own copy of the shared types)
without bumping the pinned version. No runtime behavior changes. -
5a1dde4: fix(search): wrap date column values in a type-matching parse/convert expression when building IN/NOT IN filters, so including/excluding a timestamp value no longer fails with "Cannot convert string ... to type DateTime64" or "Type mismatch in IN ... Expected: DateTime. Got: Decimal64". Date column types are now resolved from the query result set, so aliased (
TimestampTime AS time) and computed (toDate(TimestampTime)) DateTime/Date columns are also wrapped correctly when added to filters. -
ae39bc4: fix: Correct filter handling for filter keys with special characters
-
8261b46: fix: inline parametric aggregate function arguments instead of passing as query parameters
-
bf6e1f2: feat(charts): the time-chart series limit is now configured per chart in the Display Settings drawer instead of as a workspace-wide team setting (the team "Time Chart Series Limit" setting is removed). It is disabled by default — charts fetch every series and no
__hdx_series_limitCTE is emitted — and is cleared back to disabled by emptying the field. The control only appears for builder line/bar charts; the limit and its Generated SQL preview now come from the chart's own config. When a limit is set, chunked time-chart queries keep a consistent top-N series set: previously each time-window chunk ranked its own top-N, so charts could render more series than the limit and adjacent windows disagreed; the ranking is now pinned to the newest chunk window for every chunk so the union across chunks equals the limit. -
973d120: fix: polish promql experience across the app
-
677e3f7: fix: Skip rendering empty aggConditions
-
89949b1: Adding filters to dashboard exports. Implemented validation on dashboard imports to catch potential issues with generated JSON or manually tweaked JSON.
-
747352f: feat: add direct_read optimization for filters
-
750b8af: feat(mcp): add denoise option to clickstack_search tool
Add a
denoiseboolean parameter to the MCPclickstack_searchtool that
automatically filters out high-frequency repetitive event patterns from
search results, mirroring the web app's "Denoise Results" feature.When enabled, the tool samples 10k random events, mines patterns using
the Drain algorithm, identifies noisy patterns (>10% of sample), and
filters them out of result rows. Returns filtered rows plus metadata
listing removed patterns with estimated counts.Extracts shared denoise constants (
DENOISE_SAMPLE_SIZE,
DENOISE_NOISE_THRESHOLD) into@hyperdx/common-utilsso the web app
and MCP server use the same values. -
caba7c2: fix: Nudge agents towards macros in raw SQL tiles
-
adac913: refactor(mcp): rename all MCP tool prefixes from
hyperdx_toclickstack_Rename the MCP server name from
hyperdxtoclickstackand update all 19
tool names (e.g.hyperdx_search→clickstack_search), along with
descriptions, prompts, error messages, and test references. -
1a64796: Removing relative imports and using path aliases
-
c74744a: fix: fallback to body or implicit column expression when other empty
-
03f9dd7: feat: add an optional Section field to data sources
Sources can now carry an optional free-text Section label, set from the source
settings form. The value is persisted and returned by GET /api/v2/sources, so
external API consumers can read it. This lays the groundwork for grouping and
searching sources by section in the source selector. -
6e0880a: feat: Add Known Columns List setting for distributed tables
-
81e524c: feat(charts): cap group-by time charts to a top-N series limit to prevent browser memory exhaustion on high-cardinality group-bys. The cap defaults to 100 (the number of series rendered) and is configurable per team via a new "Time Chart Series Limit" setting; series beyond the cap remain available in the series selector.
-
da3caab: Type JSON metadata filter attribute paths before value sampling.
-
55a255a: refactor(metrics): unify AttributesHash to variadic cityHash64 across Map and
JSON metric schemasSum / Gauge / Histogram metric queries now compute AttributesHash as
cityHash64(ScopeAttributes, ResourceAttributes, Attributes)for both
Map(LowCardinality(String), String) and JSON attribute columns. Previously
the Map-schema path wrapped the three maps inmapConcat()before hashing,
and the JSON-schema path used the variadic form; the schema-detection
ClickHouse round-trip and theattrHashExprhelper /isJsonSchema
plumbing are gone.Compatibility:
- Per-row AttributesHash values change for every Map-schema metric row,
but the hash is recomputed inside CTEs on every query — no materialized
view, projection, ALIAS column, or cache persists it, so no downstream
consumer is affected (audit: OSS only). - Cross-scope same-key behaviour shifts: two rows that carry the same
logical key in different attribute scopes (e.g.hostin
ResourceAttributesfor one emission andhostinAttributesfor the
next) now hash distinctly and land in separate series. Previously the
mapConcat path collapsed them into one series. This only matters when an
OTel collector processor promotes attributes across scopes mid-stream;
most SDKs emit attributes in stable scopes. The new behaviour is captured
by an integration test inpackages/api/src/clickhouse/__tests__.
HDX-4466.
- Per-row AttributesHash values change for every Map-schema metric row,