Summary
sparkline() indexes the 8-element ticks array with a value that can reach 8, yielding undefined for the peak data point. The output then contains the literal string "undefined" wherever the maximum (or values near it) lands. This is reachable from heroku dashboard metrics, which feed fractional (float) values into the function.
Location
const ticks = ['▁','▂','▃','▄','▅','▆','▇','█'] // indices 0..7
const f = Math.floor(lshift(max - min, 8) / (ticks.length - 1)) // lshift(n,8) = n*256
...
const value = ticks[Math.floor(lshift(validValue - min, 8) / f)] // can be ticks[8]
Problem
The index math is not clamped. For range = max - min, f = Math.floor(range * 256 / 7); the peak value maps to Math.floor(range * 256 / f), which exceeds 7 whenever range * 256 is a small multiple of 8 but not of 7.
Concrete failing ranges (max - min):
| range |
range*256 |
f |
max index |
result |
| 0.03125 (=1/32) |
8 |
1 |
8 |
undefined |
| 0.0625 |
16 |
2 |
8 |
undefined |
| 0.125 |
32 |
4 |
8 |
undefined |
| 0.1875 |
48 |
6 |
8 |
undefined |
With integer inputs this never happens (range*256 is a multiple of 256), which is why the existing unit tests pass — they only exercise integers. But src/commands/dashboard.ts builds sparkline points by summing router-latency metric samples (points[j] = (points[j] || 0) + element), and latency values are fractional milliseconds, so float ranges occur in practice.
Trigger / Reproduction
Static analysis finding — behavior derived from source at main (5118f40a); not confirmed by execution:
sparkline([0, 0.03125])
// → '▁' + ticks[Math.floor(256/1)] === '▁undefined'
and via the CLI: heroku dashboard --app <app> where the summed per-hour latency points happen to span one of the failing ranges — the rendered dashboard line shows undefined characters instead of blocks.
Expected Behavior
The tick index should be clamped to the last bucket, e.g.
const idx = Math.min(7, Math.floor(lshift(validValue - min, 8) / f))
so every valid value renders as a block character.
Actual Behavior
Out-of-range indices produce undefined, which stringifies into the returned sparkline.
Impact
Corrupted/ugly output in heroku dashboard for ordinary float-valued metrics; any other consumer of the exported sparkline() utility is affected identically. Purely cosmetic but user-visible and trivially reproducible once the value distribution matches.
Suggested Direction
Clamp the computed index to ticks.length - 1 (and add float-range unit tests such as [0, 1/32], [0, 0.0625]). Alternatively compute the bucket as Math.round((v - min) / range * 7) with an explicit guard for range === 0.
Summary
sparkline()indexes the 8-elementticksarray with a value that can reach 8, yieldingundefinedfor the peak data point. The output then contains the literal string"undefined"wherever the maximum (or values near it) lands. This is reachable fromheroku dashboardmetrics, which feed fractional (float) values into the function.Location
src/lib/utils/sparkline.tssparkline(lines 27–38)Problem
The index math is not clamped. For
range = max - min,f = Math.floor(range * 256 / 7); the peak value maps toMath.floor(range * 256 / f), which exceeds 7 wheneverrange * 256is a small multiple of 8 but not of 7.Concrete failing ranges (
max - min):undefinedundefinedundefinedundefinedWith integer inputs this never happens (
range*256is a multiple of 256), which is why the existing unit tests pass — they only exercise integers. Butsrc/commands/dashboard.tsbuilds sparkline points by summing router-latency metric samples (points[j] = (points[j] || 0) + element), and latency values are fractional milliseconds, so float ranges occur in practice.Trigger / Reproduction
Static analysis finding — behavior derived from source at
main(5118f40a); not confirmed by execution:and via the CLI:
heroku dashboard --app <app>where the summed per-hour latency points happen to span one of the failing ranges — the rendered dashboard line showsundefinedcharacters instead of blocks.Expected Behavior
The tick index should be clamped to the last bucket, e.g.
so every valid value renders as a block character.
Actual Behavior
Out-of-range indices produce
undefined, which stringifies into the returned sparkline.Impact
Corrupted/ugly output in
heroku dashboardfor ordinary float-valued metrics; any other consumer of the exportedsparkline()utility is affected identically. Purely cosmetic but user-visible and trivially reproducible once the value distribution matches.Suggested Direction
Clamp the computed index to
ticks.length - 1(and add float-range unit tests such as[0, 1/32],[0, 0.0625]). Alternatively compute the bucket asMath.round((v - min) / range * 7)with an explicit guard forrange === 0.