From b0e24d9831fc52f6dbadeadba06656f533f52470 Mon Sep 17 00:00:00 2001 From: cawthorne Date: Tue, 7 Jul 2026 17:44:22 +0100 Subject: [PATCH 1/2] Default Grafana alert RuleQuery interval to 30s. Sets interval on Prometheus datasource query models (refId A) so deployed alert rules no longer default to 1s evaluation in Grafana UI. --- observability-lib/grafana/alerts.go | 15 ++++++++++++++- observability-lib/grafana/builder_test.go | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/observability-lib/grafana/alerts.go b/observability-lib/grafana/alerts.go index 775a51902f..8f9136b1af 100644 --- a/observability-lib/grafana/alerts.go +++ b/observability-lib/grafana/alerts.go @@ -13,6 +13,10 @@ type RuleQueryType string const ( RuleQueryTypeInstant RuleQueryType = "instant" + + // DefaultRuleQueryInterval is the default Prometheus query interval for alert rule models. + DefaultRuleQueryInterval = "30s" + defaultRuleQueryIntervalMs = 30 * 1000 ) type RuleQuery struct { @@ -23,6 +27,9 @@ type RuleQuery struct { TimeRange int64 Instant bool QueryType RuleQueryType + // Interval sets the Prometheus query interval in the alert rule model (e.g. "30s"). + // When empty, DefaultRuleQueryInterval is used. + Interval string } func newRuleQuery(query RuleQuery) *alerting.QueryBuilder { @@ -51,6 +58,12 @@ func newRuleQuery(query RuleQuery) *alerting.QueryBuilder { model.QueryType(string(query.QueryType)) } + interval := query.Interval + if interval == "" { + interval = DefaultRuleQueryInterval + } + model.Interval(interval) + return res.Model(model) } @@ -125,7 +138,7 @@ func newReduceSettingsOptions(options expr.ExprTypeReduceSettings) cog.Builder[e func newConditionQuery(options ConditionQuery) *alerting.QueryBuilder { if options.IntervalMs == nil { // Recommended value for intervalMs is 30s - options.IntervalMs = Pointer[float64](30 * 1000) + options.IntervalMs = Pointer[float64](defaultRuleQueryIntervalMs) } if options.MaxDataPoints == nil { diff --git a/observability-lib/grafana/builder_test.go b/observability-lib/grafana/builder_test.go index 210cc2cdc0..aa6f077713 100644 --- a/observability-lib/grafana/builder_test.go +++ b/observability-lib/grafana/builder_test.go @@ -5,6 +5,7 @@ import ( "github.com/grafana/grafana-foundation-sdk/go/alerting" "github.com/grafana/grafana-foundation-sdk/go/expr" + "github.com/grafana/grafana-foundation-sdk/go/prometheus" "github.com/stretchr/testify/require" "github.com/grafana/grafana-foundation-sdk/go/dashboard" @@ -546,3 +547,20 @@ func TestBuilder_AddTimeSeriesPanelWithAlert(t *testing.T) { require.Equal(t, "Panel Title", o.Alerts[0].RuleGroup) }) } + +func TestNewAlertRule_DefaultRuleQueryInterval(t *testing.T) { + rule, err := grafana.NewAlertRule(&grafana.AlertOptions{ + Title: "CPU High", + Query: []grafana.RuleQuery{{ + Expr: "up", + RefID: "A", + Datasource: "prometheus-uid", + }}, + }).Build() + require.NoError(t, err) + require.Len(t, rule.Data, 1) + model, ok := rule.Data[0].Model.(prometheus.Dataquery) + require.True(t, ok) + require.NotNil(t, model.Interval) + require.Equal(t, grafana.DefaultRuleQueryInterval, *model.Interval) +} From 7d62a11dbf1eb2ee888ce6a5158398d99a027d84 Mon Sep 17 00:00:00 2001 From: cawthorne Date: Tue, 7 Jul 2026 17:52:37 +0100 Subject: [PATCH 2/2] Derive alert query interval constants from shared seconds base. Addresses review feedback to avoid drift between the Prometheus query interval string and condition step intervalMs defaults. --- observability-lib/grafana/alerts.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/observability-lib/grafana/alerts.go b/observability-lib/grafana/alerts.go index 8f9136b1af..7a229f71be 100644 --- a/observability-lib/grafana/alerts.go +++ b/observability-lib/grafana/alerts.go @@ -1,6 +1,7 @@ package grafana import ( + "fmt" "maps" "github.com/grafana/grafana-foundation-sdk/go/alerting" @@ -14,11 +15,12 @@ type RuleQueryType string const ( RuleQueryTypeInstant RuleQueryType = "instant" - // DefaultRuleQueryInterval is the default Prometheus query interval for alert rule models. - DefaultRuleQueryInterval = "30s" - defaultRuleQueryIntervalMs = 30 * 1000 + defaultRuleQueryIntervalSeconds = 30 ) +// DefaultRuleQueryInterval is the default Prometheus query interval for alert rule models. +var DefaultRuleQueryInterval = fmt.Sprintf("%ds", defaultRuleQueryIntervalSeconds) + type RuleQuery struct { Expr string RefID string @@ -138,7 +140,7 @@ func newReduceSettingsOptions(options expr.ExprTypeReduceSettings) cog.Builder[e func newConditionQuery(options ConditionQuery) *alerting.QueryBuilder { if options.IntervalMs == nil { // Recommended value for intervalMs is 30s - options.IntervalMs = Pointer[float64](defaultRuleQueryIntervalMs) + options.IntervalMs = Pointer[float64](float64(defaultRuleQueryIntervalSeconds * 1000)) } if options.MaxDataPoints == nil {