26 Jan 2026 01:10 PM
27 Jan 2026 12:27 PM
Hi,
You’re right — Solution 1 works, but it becomes hard to maintain because you’re grouping by many boolean expressions (true/false), which doesn’t scale when you have 100+ dimension values.
You can try this:
I couldn’t properly validate this against your specific metric (metric.count.numbers) in your environment, so I used a built-in CPU metric as an example.
timeseries {
v = avg(dt.host.cpu.usage, scalar: true)
}, by: { Dimension }
| fieldsAdd d = toLong(Dimension)
| fieldsAdd bucket =
if(isNull(d), "NON_NUMERIC",
else: if(d == 0, "0",
else: if(d >= 1 and d <= 3, "1–3",
else: if(d >= 4 and d <= 18, "4–18",
else: if(d > 18 and d <= 32, "19–32",
else: if(d >= 100, "100+",
else: "33–99"
)
)
)
)
)
)
| summarize sum = sum(v), by: { bucket }
| sort bucket ascFor real usage, replace the metric and Dimension with the actual metric key and dimension name from your dataset.
And your second question, why does asLong(Dimension) return null.
Because asLong() typically does not perform a string-to-long conversion. It behaves more like a cast/interpretation and returns a value only if the input is already compatible with a numeric type.
Since your dimension values are strings ("0", "1", …), asLong(Dimension) can evaluate to null.
Use toLong(Dimension) instead — it performs the actual conversion and allows numeric range comparisons (>=, <=) for bucketing.
27 Jan 2026 04:08 PM - edited 27 Jan 2026 04:09 PM
I usually use coalesce() funtion to construct these (switch/case)/(case/when) statements. Less brackets to type, no need for else: and easier to maintain:
| fieldsAdd bucket = coalesce(
if(d == 0, "0"),
if(d >= 1 and d <= 3, "1–3"),
if(d >= 4 and d <= 18, "4–18"),
if(d > 18 and d <= 32, "19–32"),
if(d > 33 and d <= 99, "33–99"),
if(d >= 100, "100+"),
"NONUMERIC"
)
In case set of possible vales are not numbers which can be organized in ranges, instead of OR operator in() function will provide much shorter syntax:
if(in(Dimension, {"dog","cat","frog"}), "pets"),
Featured Posts