From 0d4cf45c960a3c36b9eaecc8e0a373e5bdbaeab6 Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Fri, 2 Oct 2026 08:17:04 +0000 Subject: [PATCH] Serve the delivery duration histogram from boot (closes #267) webhooker_delivery_duration_seconds was absent from /metrics until the first delivery, while every other delivery series is materialised at zero when the collectors are registered. initSeries now materialises the histogram too, for the same four target types, so a scrape of an instance that has delivered nothing shows it with a zero count and sum. The registration test lists it with the other series, and a new route test scrapes /metrics on a freshly built instance and finds it for every target type. Model: opus-5-5 --- internal/metrics/metrics.go | 1 + internal/metrics/metrics_test.go | 1 + internal/server/routes_test.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 1d8f8f3..3658d9c 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -384,6 +384,7 @@ func (s *Set) initSeries() { s.deliveriesFailed.WithLabelValues(label) s.deliveryRetries.WithLabelValues(label) s.deliveryReplays.WithLabelValues(label) + s.deliveryDuration.WithLabelValues(label) s.deliveriesPending.WithLabelValues(label) s.deliveriesRetrying.WithLabelValues(label) s.circuitBreakersOpen.WithLabelValues(label) diff --git a/internal/metrics/metrics_test.go b/internal/metrics/metrics_test.go index a8b3a64..d89ea73 100644 --- a/internal/metrics/metrics_test.go +++ b/internal/metrics/metrics_test.go @@ -167,6 +167,7 @@ func TestKnownSeriesExistBeforeAnyDelivery(t *testing.T) { "webhooker_deliveries_succeeded_total", "webhooker_deliveries_failed_total", "webhooker_delivery_retries_total", + "webhooker_delivery_duration_seconds", "webhooker_circuit_breakers_open", } { assert.ElementsMatch(t, diff --git a/internal/server/routes_test.go b/internal/server/routes_test.go index 0c12126..52a20da 100644 --- a/internal/server/routes_test.go +++ b/internal/server/routes_test.go @@ -1576,3 +1576,31 @@ func TestTwoMetricsRoutersInOneProcess(t *testing.T) { } } } + +// TestMetricsScrapeBeforeAnyDelivery pins +// https://git.eeqj.de/sneak/webhooker/issues/267: an instance that +// has delivered nothing must still serve the delivery duration +// histogram, at zero, for every target type. +func TestMetricsScrapeBeforeAnyDelivery(t *testing.T) { + t.Parallel() + + env := newTestEnvWithConfig( + t, metricsConfig(t, metricsUser, metricsAuthValue), + ) + + scrape := env.metricsRequest(metricsUser, metricsAuthValue) + require.Equal(t, http.StatusOK, scrape.Code) + + for _, targetType := range []database.TargetType{ + database.TargetTypeHTTP, + database.TargetTypeDatabase, + database.TargetTypeLog, + database.TargetTypeSlack, + } { + assert.Contains( + t, scrape.Body.String(), + `webhooker_delivery_duration_seconds_count{target_type="`+ + string(targetType)+`"} 0`, + ) + } +} -- 2.54.0