diff --git a/coderd/x/nats/metrics_test.go b/coderd/x/nats/metrics_test.go index 36f2eae096..9e39d429cd 100644 --- a/coderd/x/nats/metrics_test.go +++ b/coderd/x/nats/metrics_test.go @@ -58,8 +58,13 @@ func TestPubsub_Metrics(t *testing.T) { testutil.PromCounterHasValue(t, metrics, gatherCount, "coder_nats_pubsub_messages_total", "normal") && testutil.PromCounterHasValue(t, metrics, float64(len(data))+latencyBytes, "coder_nats_pubsub_received_bytes_total") && testutil.PromCounterHasValue(t, metrics, float64(len(data))+latencyBytes, "coder_nats_pubsub_published_bytes_total") && - testutil.PromGaugeAssertion(t, metrics, func(in float64) bool { return in > 0 }, "coder_nats_pubsub_send_latency_seconds") && - testutil.PromGaugeAssertion(t, metrics, func(in float64) bool { return in > 0 }, "coder_nats_pubsub_receive_latency_seconds") && + // The latency gauges can be exactly 0 on Windows, whose monotonic + // clock advances in coarse (up to 15.6ms) ticks; a sub-tick publish + // measures a zero duration. An absent gauge reads as -1, so >= 0 + // still proves the gauge was gathered, and the measures_total/errs + // counters below prove measurement ran and succeeded. + testutil.PromGaugeAssertion(t, metrics, func(in float64) bool { return in >= 0 }, "coder_nats_pubsub_send_latency_seconds") && + testutil.PromGaugeAssertion(t, metrics, func(in float64) bool { return in >= 0 }, "coder_nats_pubsub_receive_latency_seconds") && testutil.PromCounterHasValue(t, metrics, gatherCount, "coder_nats_pubsub_latency_measures_total") && !testutil.PromCounterGathered(t, metrics, "coder_nats_pubsub_latency_measure_errs_total") }, testutil.WaitShort, testutil.IntervalFast) @@ -95,8 +100,10 @@ func TestPubsub_Metrics(t *testing.T) { testutil.PromCounterHasValue(t, metrics, 1, "coder_nats_pubsub_messages_total", "colossal") && testutil.PromCounterHasValue(t, metrics, float64(colossalSize+len(data))+latencyBytes, "coder_nats_pubsub_received_bytes_total") && testutil.PromCounterHasValue(t, metrics, float64(colossalSize+len(data))+latencyBytes, "coder_nats_pubsub_published_bytes_total") && - testutil.PromGaugeAssertion(t, metrics, func(in float64) bool { return in > 0 }, "coder_nats_pubsub_send_latency_seconds") && - testutil.PromGaugeAssertion(t, metrics, func(in float64) bool { return in > 0 }, "coder_nats_pubsub_receive_latency_seconds") && + // Zero latency is accepted for coarse clocks; see the comment on + // the first Eventually above. + testutil.PromGaugeAssertion(t, metrics, func(in float64) bool { return in >= 0 }, "coder_nats_pubsub_send_latency_seconds") && + testutil.PromGaugeAssertion(t, metrics, func(in float64) bool { return in >= 0 }, "coder_nats_pubsub_receive_latency_seconds") && testutil.PromCounterHasValue(t, metrics, gatherCount, "coder_nats_pubsub_latency_measures_total") && !testutil.PromCounterGathered(t, metrics, "coder_nats_pubsub_latency_measure_errs_total") }, testutil.WaitShort, testutil.IntervalFast) diff --git a/coderd/x/nats/natsbench/natsbench_internal_test.go b/coderd/x/nats/natsbench/natsbench_internal_test.go index 9c4322bdd1..8a96042540 100644 --- a/coderd/x/nats/natsbench/natsbench_internal_test.go +++ b/coderd/x/nats/natsbench/natsbench_internal_test.go @@ -2,7 +2,6 @@ package main import ( "testing" - "time" "github.com/stretchr/testify/require" @@ -66,9 +65,22 @@ func TestRunSingleNode(t *testing.T) { require.EqualValues(t, pl.totalExpected, res.Delivered) require.Greater(t, res.Delivered, res.Published, "fan-out must exceed publishes") require.Zero(t, res.Drops) - require.Greater(t, res.PubsPerSec, 0.0) - require.Greater(t, res.DeliveriesPerSec, 0.0) - require.Greater(t, res.DeliverDuration, time.Duration(0)) + // The exact count assertions above are the authoritative correctness + // checks; a run that published or delivered nothing fails there. The + // rates below are derived (count / duration), and Windows' monotonic + // clock advances in coarse (up to 15.6ms) ticks, so a sub-tick phase + // measures a 0 duration and must yield a 0 rate rather than a + // fabricated one. On fine-grained clocks the strict branch applies. + if res.PublishDuration > 0 { + require.Greater(t, res.PubsPerSec, 0.0) + } else { + require.Zero(t, res.PubsPerSec) + } + if res.DeliverDuration > 0 { + require.Greater(t, res.DeliveriesPerSec, 0.0) + } else { + require.Zero(t, res.DeliveriesPerSec) + } require.GreaterOrEqual(t, res.DeliverDuration, res.PublishDuration) } @@ -101,6 +113,16 @@ func TestRunCluster(t *testing.T) { require.EqualValues(t, pl.totalExpected, res.Expected) require.EqualValues(t, pl.totalExpected, res.Delivered) require.Zero(t, res.Drops) - require.Greater(t, res.PubsPerSec, 0.0) - require.Greater(t, res.DeliveriesPerSec, 0.0) + // See TestRunSingleNode: counts above are the correctness checks; + // coarse clocks can quantize a phase duration, and thus its rate, to 0. + if res.PublishDuration > 0 { + require.Greater(t, res.PubsPerSec, 0.0) + } else { + require.Zero(t, res.PubsPerSec) + } + if res.DeliverDuration > 0 { + require.Greater(t, res.DeliveriesPerSec, 0.0) + } else { + require.Zero(t, res.DeliveriesPerSec) + } }