count_distinct aggFn on metric tiles ignores valueExpression, always counts distinct metric Values
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 9.9k
- Forks
- 471
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 117
Description
Bug Description
When using count_distinct as the aggFn on a metric tile, the valueExpression is ignored. The generated SQL always counts distinct values of the metric's float Value column rather than the specified attribute expression.
Steps to Reproduce
- Create a dashboard tile with
displayType: "number"and a metric select usingcount_distinctwith avalueExpressionpointing to an attribute:{ "displayType": "number", "source": "Metrics", "select": [ { "aggFn": "count_distinct", "valueExpression": "Attributes['name']", "metricName": "argocd_app_info", "metricType": "gauge" } ] } - Observe the number displayed — for an info metric (where
Valueis always1.0), the tile shows1or2instead of the actual count of distinct attribute values.
Expected Behavior
The tile should display the count of distinct values of Attributes['name'] across all time series for the metric — i.e., the number of distinct applications reported by argocd_app_info.
Direct ClickHouse query gives the correct answer:
SELECT uniqExact(Attributes['name'])
FROM default.otel_metrics_gauge
WHERE MetricName = 'argocd_app_info'
AND TimeUnix >= now() - INTERVAL 1 HOUR
-- returns 53
Actual Behavior
The generated SQL uses count(DISTINCT LastValue) where LastValue = last_value(Value) — the gauge's numeric value — not the attribute expression:
-- Generated by HyperDX
...
Bucketed AS (
SELECT
...,
last_value(Value) AS LastValue, -- <-- always the float metric value
any(Attributes) AS Attributes
FROM Source
GROUP BY AttributesHash, __hdx_time_bucket2
)
SELECT count(DISTINCT LastValue) -- <-- counts distinct 1.0, 0.0, etc.
FROM Bucketed
Result: 2 (distinct float values) instead of 53 (distinct app names).
Root Cause
In packages/common-utils/src/core/renderChartConfig.ts, translateMetricChartConfig unconditionally overwrites valueExpression with 'LastValue' for gauge metrics before passing the select config to SQL generation:
select: [
{
..._select,
valueExpression: 'LastValue', // overwrites user-provided Attributes['name']
aggCondition: '',
},
]
The original valueExpression from the user config is never used in metric query translation.
Additional Context
- The zod schema (
externalDashboardSelectItemSchemainpackages/api/src/utils/zod.ts) accepts and even requiresvalueExpressionfor non-countaggFns on metrics — so the intent to support this exists, but the query translator doesn't honour it. - The UI currently has no input for
valueExpressionon metric tiles, which makes sense given it's ignored — but fixing the translator would enable useful aggregations like counting distinct label values. - Confirmed present in v2.27.0. No prior issue or fix found.
Suggested Fix
For count_distinct (and potentially other aggFns where valueExpression refers to an attribute), use the user-provided expression instead of hardcoding 'LastValue':
// In translateMetricChartConfig for gauge metrics:
const effectiveValueExpression =
_select.aggFn === 'count_distinct' && _select.valueExpression
? _select.valueExpression
: 'LastValue';
select: [
{
..._select,
valueExpression: effectiveValueExpression,
aggCondition: '',
},
]
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/common-utils/src/core/renderChartConfig.ts at translateMetricChartConfig and inspect how gauge select items are translated before SQL generation. Reproduce the count_distinct metric configuration from the issue, preserve its attribute valueExpression, and verify the generated query counts distinct attribute values rather than LastValue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- clickhouse, sql, typescript
- Domain
- analytics, backend, data
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100