Giuliano Mega acdc0fc325
feat: add metrics collector endpoint to libstorage (#1454)
Co-authored-by: Marcin Czenko <marcin.czenko@pm.me>
2026-06-18 20:10:08 +00:00

149 lines
4.0 KiB
Nim

import std/json
import std/times
import pkg/unittest2
import pkg/metrics
import ../../library/logosmetrics
declareCounter myCounter, "Parts Counter", ["part_type"]
declareGauge myGauge, "My gauge"
declareHistogram myHistogram, "My histogram", buckets = [0.0, 1.0, 2.0]
# A badly-behaved collector that emits label/labelValue arrays of differing
# lengths.
type BadCollector = ref object of Gauge
method collect(collector: BadCollector, output: MetricHandler) =
output(
name = "bad_metric",
value = 1.0,
labels = ["label1", "label2"],
labelValues = ["value1"],
timestamp = Time(),
)
output(
name = "bad_metric",
value = 1.0,
labels = ["label1", "label2"],
labelValues = ["value1", "value2"],
timestamp = Time(),
)
suite "Metrics":
test "should serialize Nim metrics to Logos Metrics format":
myCounter.inc(labelValues = ["screws"])
myCounter.inc(labelValues = ["washers"])
myGauge.set(42.0)
myHistogram.observe(1)
myHistogram.observe(2)
myHistogram.observe(3)
myHistogram.observe(4)
myHistogram.observe(5)
let metrics =
defaultRegistry.toJson(includeOnly = @["myCounter", "myGauge", "myHistogram"])
# Remove "created" metrics as we can't pin those down.
var filteredMetrics = %*{"metrics": @[]}
for metric in metrics["metrics"]:
if metric["name"].getStr() != "myCounter_created" and
metric["name"].getStr() != "myHistogram_created":
filteredMetrics["metrics"].add(metric)
check filteredMetrics ==
%*{
"metrics": [
{
"name": "myCounter_total",
"type": "counter",
"help": "Parts Counter",
"value": 1.0,
"labels": {"part_type": "screws"},
},
{
"name": "myCounter_total",
"type": "counter",
"help": "Parts Counter",
"value": 1.0,
"labels": {"part_type": "washers"},
},
{
"name": "myGauge",
"type": "gauge",
"help": "My gauge",
"value": 42.0,
"labels": {},
},
{
"name": "myHistogram_sum",
"type": "histogram",
"help": "My histogram",
"value": 15.0,
"labels": {},
},
{
"name": "myHistogram_count",
"type": "histogram",
"help": "My histogram",
"value": 5.0,
"labels": {},
},
{
"name": "myHistogram_bucket",
"type": "histogram",
"help": "My histogram",
"value": 0.0,
"labels": {"le": "0.0"},
},
{
"name": "myHistogram_bucket",
"type": "histogram",
"help": "My histogram",
"value": 1.0,
"labels": {"le": "1.0"},
},
{
"name": "myHistogram_bucket",
"type": "histogram",
"help": "My histogram",
"value": 2.0,
"labels": {"le": "2.0"},
},
{
"name": "myHistogram_bucket",
"type": "histogram",
"help": "My histogram",
"value": 5.0,
"labels": {"le": "+Inf"},
},
]
}
test "should drop labels when collector emits fewer values than labels":
discard BadCollector.newCollector("badMetric", "Badly behaved collector")
let metrics = defaultRegistry.toJson(includeOnly = @["badMetric"])
check metrics ==
%*{
"metrics": [
{
"name": "bad_metric",
"type": "gauge",
"help": "Badly behaved collector",
"value": 1.0,
"labels": {"label1": "value1"},
},
{
"name": "bad_metric",
"type": "gauge",
"help": "Badly behaved collector",
"value": 1.0,
"labels": {"label1": "value1", "label2": "value2"},
},
]
}