I'm measuring server's requests count (Counter) and latencies (Summary), and test both with unit tests. I observe the metrics via InstrumentHandlerCounter and InstrumentHandlerDuration respectively.
For testing requests count, I hardcode the expectation in a string constant, and use CollectAndCompare to perform an exact match validation:
// Validate them
type codeLabelPair string
type scenarioExpectedSampleCountMap map[codeLabelPair]uint64
expectedSampleCountMap := scenarioExpectedSampleCountMap{
`name:"code" value:"200" `: 3,
`name:"code" value:"304" `: 1,
`name:"code" value:"502" `: 2,
}
reg := prometheus.NewPedanticRegistry()
if err := reg.Register(promRequestsLatency); err != nil {
this.T().Errorf(hintPrefix+" - registering collector failed: %s", err)
}
actualMetricFamilyArr, err := reg.Gather()
if err != nil {
this.T().Errorf(hintPrefix+" - gathering metrics failed: %s", err)
}
assert.Equal(this.T(), 1, len(actualMetricFamilyArr),
hintPrefix+" expects exactly one metric family.")
assert.Equal(this.T(), "request_latencies_in_seconds", *actualMetricFamilyArr[0].Name,
hintPrefix+" expects the right metric name.")
assert.Equal(this.T(), len(expectedSampleCountMap), len(actualMetricFamilyArr[0].Metric),
hintPrefix+" expects the right amount of metrics collected and gathered.")
for _, actualMetric := range actualMetricFamilyArr[0].Metric {
// Expect the right sample count.
code := actualMetric.Label[0].String()
expectedSampleCount := expectedSampleCountMap[codeLabelPair(code)]
actualSampleCount := actualMetric.Summary.GetSampleCount()
assert.Equal(this.T(), expectedSampleCount, actualSampleCount, hintPrefix+" expects the right sample count for "+code)
// Test quantiles.
expectedQuantileKeys := []float64{0.5, 0.9, 0.99}
// Expect the right number of quantiles.
assert.Equal(this.T(), len(expectedQuantileKeys), len(actualMetric.Summary.Quantile), hintPrefix+" expects the right number of quantiles.")
// Expect the right quantiles.
// Expect positive quantile values, because latencies are non-zero.
// Don't check the exact values, because latencies are non-deterministic.
for i, quantile := range actualMetric.Summary.Quantile {
assert.Equal(this.T(), expectedQuantileKeys[i], quantile.GetQuantile(), hintPrefix+" expects the right quantile.")
assert.True(this.T(), quantile.GetValue() > .0, hintPrefix+" expects non-zero quantile value (latency).")
}
}
Alternatively, is there a way to fake clock in Prometheus, so e.g. InstrumentHandlerDuration would propagate the pre-defined fake duration? Or, is there a good way to fake clock in Go? There is an option that doesn't look safe enough:
Thanks.