From 19b878ce66c4720ad55cbeb12e322a57f725cbed Mon Sep 17 00:00:00 2001 From: Matthew Jacobson Date: Fri, 7 Mar 2025 15:28:56 -0500 Subject: [PATCH] Alerting: Include time range in template dashboard and panel urls (#101095) Alerting: Include time range in templated dashboard and panel urls Time range: from=Alert.StartsAt-1hr Firing Alerts: to=Current Timestamp Resolved Alerts: to=Alert.EndsAt --- go.mod | 2 +- go.sum | 4 +- .../ngalert/notifier/templates_test.go | 77 ++++++++++++++++++- pkg/storage/unified/apistore/go.mod | 2 +- pkg/storage/unified/apistore/go.sum | 4 +- pkg/storage/unified/resource/go.mod | 2 +- pkg/storage/unified/resource/go.sum | 4 +- 7 files changed, 82 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index bcec4f1c620..66dfa33ebe0 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/googleapis/go-sql-spanner v1.11.1 // @grafana/grafana-search-and-storage github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group github.com/gorilla/websocket v1.5.3 // @grafana/grafana-app-platform-squad - github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061 // @grafana/alerting-backend + github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356 // @grafana/alerting-backend github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 // @grafana/identity-access-team github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 // @grafana/identity-access-team github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics diff --git a/go.sum b/go.sum index a2a07666502..7a25d79a5eb 100644 --- a/go.sum +++ b/go.sum @@ -1540,8 +1540,8 @@ github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7Fsg github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061 h1:2s0xCzcxw8MlzLbbrEkghmwQpXjwkcRJYSItBQ1ZD0U= -github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= +github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356 h1:71o8Bxw/wg+aBRUASiGux67gDEUC2bqq3I+x2hw8eIc= +github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 h1:FTuDRy/Shw8yOdG+v1DnkeuaCAl8fvwgcfaG9Wccuhg= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501/go.mod h1:XVpdLhaeYqz414FmGnW00/0vTe1x8c0GRH3KaeRtyg0= github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8= diff --git a/pkg/services/ngalert/notifier/templates_test.go b/pkg/services/ngalert/notifier/templates_test.go index fb266ac15f9..902c534a058 100644 --- a/pkg/services/ngalert/notifier/templates_test.go +++ b/pkg/services/ngalert/notifier/templates_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/go-openapi/strfmt" alertingModels "github.com/grafana/alerting/models" @@ -17,13 +18,42 @@ import ( ) var ( + timeNow = time.Now() simpleAlert = amv2.PostableAlert{ Alert: amv2.Alert{ - Labels: amv2.LabelSet{"__alert_rule_uid__": "rule uid", "alertname": "alert1", "lbl1": "val1"}, + Labels: amv2.LabelSet{ + alertingModels.RuleUIDLabel: "rule uid", + prometheusModel.AlertNameLabel: "alert1", + "lbl1": "val1", + }, }, - Annotations: amv2.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh", "__alertImageToken__": "test-image-1"}, - StartsAt: strfmt.DateTime{}, - EndsAt: strfmt.DateTime{}, + Annotations: amv2.LabelSet{ + "ann1": "annv1", + alertingModels.DashboardUIDAnnotation: "abcd", + alertingModels.PanelIDAnnotation: "42", + alertingModels.ImageTokenAnnotation: "test-image-1", + alertingModels.OrgIDAnnotation: "1", + }, + StartsAt: strfmt.DateTime(timeNow), + EndsAt: strfmt.DateTime(timeNow.Add(time.Hour)), // Firing. + } + resolvedAlert = amv2.PostableAlert{ + Alert: amv2.Alert{ + Labels: amv2.LabelSet{ + alertingModels.RuleUIDLabel: "rule uid", + prometheusModel.AlertNameLabel: "alert1", + "lbl1": "val1", + }, + }, + Annotations: amv2.LabelSet{ + "ann1": "annv1", + alertingModels.DashboardUIDAnnotation: "abcd", + alertingModels.PanelIDAnnotation: "42", + alertingModels.ImageTokenAnnotation: "test-image-1", + alertingModels.OrgIDAnnotation: "1", + }, + StartsAt: strfmt.DateTime(timeNow.Add(-30 * time.Minute)), + EndsAt: strfmt.DateTime(timeNow), // Resolved. } ) @@ -207,6 +237,45 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val }}, Errors: nil, }, + }, { + name: "DashboardURL generation contains from and to time", + input: apimodels.TestTemplatesConfigBodyParams{ + Alerts: []*amv2.PostableAlert{&resolvedAlert}, // We specifically use a resolved alert as otherwise the `to` time will be the current time and difficult to test. + Name: "slack.title", + Template: `{{ define "slack.title" }}{{ (index .Alerts 0 ).DashboardURL }}{{ end }}`, + }, + expected: TestTemplatesResults{ + Results: []alertingNotify.TestTemplatesResult{{ + Name: "slack.title", + Text: fmt.Sprintf("http://localhost:9093/d/%s?from=%d&orgId=%s&to=%d", + resolvedAlert.Annotations[alertingModels.DashboardUIDAnnotation], + timeNow.Add(-90*time.Minute).UnixMilli(), // StartsAt - 1hr. + resolvedAlert.Annotations[alertingModels.OrgIDAnnotation], + timeNow.UnixMilli()), + Scope: alertingNotify.TemplateScope(apimodels.RootScope), + }}, + Errors: nil, + }, + }, { + name: "PanelURL generation contains from and to time ", + input: apimodels.TestTemplatesConfigBodyParams{ + Alerts: []*amv2.PostableAlert{&resolvedAlert}, // We specifically use a resolved alert as otherwise the `to` time will be the current time and difficult to test. + Name: "slack.title", + Template: `{{ define "slack.title" }}{{ (index .Alerts 0 ).PanelURL }}{{ end }}`, + }, + expected: TestTemplatesResults{ + Results: []alertingNotify.TestTemplatesResult{{ + Name: "slack.title", + Text: fmt.Sprintf("http://localhost:9093/d/%s?from=%d&orgId=%s&to=%d&viewPanel=%s", + resolvedAlert.Annotations[alertingModels.DashboardUIDAnnotation], + timeNow.Add(-90*time.Minute).UnixMilli(), // StartsAt - 1hr. + resolvedAlert.Annotations[alertingModels.OrgIDAnnotation], + timeNow.UnixMilli(), + resolvedAlert.Annotations[alertingModels.PanelIDAnnotation]), + Scope: alertingNotify.TemplateScope(apimodels.RootScope), + }}, + Errors: nil, + }, }, } diff --git a/pkg/storage/unified/apistore/go.mod b/pkg/storage/unified/apistore/go.mod index 25c33692ef0..2414762e82e 100644 --- a/pkg/storage/unified/apistore/go.mod +++ b/pkg/storage/unified/apistore/go.mod @@ -203,7 +203,7 @@ require ( github.com/googleapis/go-sql-spanner v1.11.1 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061 // indirect + github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356 // indirect github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/dskit v0.0.0-20241105154643-a6b453a88040 // indirect diff --git a/pkg/storage/unified/apistore/go.sum b/pkg/storage/unified/apistore/go.sum index 2dc045ac2b6..99f93e65746 100644 --- a/pkg/storage/unified/apistore/go.sum +++ b/pkg/storage/unified/apistore/go.sum @@ -1253,8 +1253,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061 h1:2s0xCzcxw8MlzLbbrEkghmwQpXjwkcRJYSItBQ1ZD0U= -github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= +github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356 h1:71o8Bxw/wg+aBRUASiGux67gDEUC2bqq3I+x2hw8eIc= +github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 h1:FTuDRy/Shw8yOdG+v1DnkeuaCAl8fvwgcfaG9Wccuhg= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501/go.mod h1:XVpdLhaeYqz414FmGnW00/0vTe1x8c0GRH3KaeRtyg0= github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8= diff --git a/pkg/storage/unified/resource/go.mod b/pkg/storage/unified/resource/go.mod index 9d6bb4b900d..a4569aca346 100644 --- a/pkg/storage/unified/resource/go.mod +++ b/pkg/storage/unified/resource/go.mod @@ -131,7 +131,7 @@ require ( github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/googleapis/go-sql-spanner v1.11.1 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061 // indirect + github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/grafana-app-sdk/logging v0.30.0 // indirect github.com/grafana/grafana-aws-sdk v0.31.5 // indirect diff --git a/pkg/storage/unified/resource/go.sum b/pkg/storage/unified/resource/go.sum index a8ad1b779f1..32f61d7aae2 100644 --- a/pkg/storage/unified/resource/go.sum +++ b/pkg/storage/unified/resource/go.sum @@ -1150,8 +1150,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061 h1:2s0xCzcxw8MlzLbbrEkghmwQpXjwkcRJYSItBQ1ZD0U= -github.com/grafana/alerting v0.0.0-20250305143710-aae4827ec061/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= +github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356 h1:71o8Bxw/wg+aBRUASiGux67gDEUC2bqq3I+x2hw8eIc= +github.com/grafana/alerting v0.0.0-20250307175047-1d263576d356/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 h1:FTuDRy/Shw8yOdG+v1DnkeuaCAl8fvwgcfaG9Wccuhg= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501/go.mod h1:XVpdLhaeYqz414FmGnW00/0vTe1x8c0GRH3KaeRtyg0= github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8=