mirror of https://github.com/grafana/grafana.git
				
				
				
			Alerting: Update default route groupBy to [grafana_folder, alertname] (#50052)
* Alerting: Update default route groupBy to [grafana_folder, alertname] Default group by for new routes and migrations is now [grafana_folder, alertname]
This commit is contained in:
		
							parent
							
								
									32c2b62dc7
								
							
						
					
					
						commit
						434e94ef2b
					
				|  | @ -223,7 +223,7 @@ func TestNotificationPolicyService(t *testing.T) { | |||
| 		require.NoError(t, err) | ||||
| 		require.Equal(t, "grafana-default-email", tree.Receiver) | ||||
| 		require.Nil(t, tree.Routes) | ||||
| 		require.Nil(t, tree.GroupBy) | ||||
| 		require.Equal(t, []model.LabelName{models.FolderTitleLabel, model.AlertNameLabel}, tree.GroupBy) | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,8 +7,10 @@ import ( | |||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/prometheus/alertmanager/pkg/labels" | ||||
| 	"github.com/prometheus/common/model" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/components/simplejson" | ||||
| 	ngModels "github.com/grafana/grafana/pkg/services/ngalert/models" | ||||
| 	"github.com/grafana/grafana/pkg/util" | ||||
| ) | ||||
| 
 | ||||
|  | @ -231,6 +233,7 @@ func (m *migration) createDefaultRouteAndReceiver(defaultChannels []*notificatio | |||
| 	defaultRoute := &Route{ | ||||
| 		Receiver:   defaultReceiverName, | ||||
| 		Routes:     make([]*Route, 0), | ||||
| 		GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, // To keep parity with pre-migration notifications.
 | ||||
| 	} | ||||
| 
 | ||||
| 	return defaultReceiver, defaultRoute, nil | ||||
|  | @ -442,6 +445,7 @@ type Route struct { | |||
| 	Matchers   Matchers `yaml:"matchers,omitempty" json:"matchers,omitempty"` | ||||
| 	Routes     []*Route `yaml:"routes,omitempty" json:"routes,omitempty"` | ||||
| 	Continue   bool     `yaml:"continue,omitempty" json:"continue,omitempty"` | ||||
| 	GroupByStr []string `yaml:"group_by,omitempty" json:"group_by,omitempty"` | ||||
| } | ||||
| 
 | ||||
| type Matchers labels.Matchers | ||||
|  |  | |||
|  | @ -3,9 +3,11 @@ package ualert | |||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/prometheus/common/model" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/components/simplejson" | ||||
| 	ngModels "github.com/grafana/grafana/pkg/services/ngalert/models" | ||||
| ) | ||||
| 
 | ||||
| func TestFilterReceiversForAlert(t *testing.T) { | ||||
|  | @ -148,6 +150,7 @@ func TestCreateRoute(t *testing.T) { | |||
| 				Matchers:   Matchers{{Type: 0, Name: "rule_uid", Value: "r_uid1"}}, | ||||
| 				Routes:     nil, | ||||
| 				Continue:   false, | ||||
| 				GroupByStr: nil, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
|  | @ -166,15 +169,18 @@ func TestCreateRoute(t *testing.T) { | |||
| 						Matchers:   Matchers{{Type: 0, Name: "rule_uid", Value: "r_uid1"}}, | ||||
| 						Routes:     nil, | ||||
| 						Continue:   true, | ||||
| 						GroupByStr: nil, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Receiver:   "recv2", | ||||
| 						Matchers:   Matchers{{Type: 0, Name: "rule_uid", Value: "r_uid1"}}, | ||||
| 						Routes:     nil, | ||||
| 						Continue:   true, | ||||
| 						GroupByStr: nil, | ||||
| 					}, | ||||
| 				}, | ||||
| 				Continue:   false, | ||||
| 				GroupByStr: nil, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | @ -296,6 +302,7 @@ func TestCreateDefaultRouteAndReceiver(t *testing.T) { | |||
| 			expRoute: &Route{ | ||||
| 				Receiver:   "autogen-contact-point-default", | ||||
| 				Routes:     make([]*Route, 0), | ||||
| 				GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
|  | @ -308,6 +315,7 @@ func TestCreateDefaultRouteAndReceiver(t *testing.T) { | |||
| 			expRoute: &Route{ | ||||
| 				Receiver:   "autogen-contact-point-default", | ||||
| 				Routes:     make([]*Route, 0), | ||||
| 				GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
|  | @ -317,6 +325,7 @@ func TestCreateDefaultRouteAndReceiver(t *testing.T) { | |||
| 			expRoute: &Route{ | ||||
| 				Receiver:   "name1", | ||||
| 				Routes:     make([]*Route, 0), | ||||
| 				GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  |  | |||
|  | @ -9,12 +9,14 @@ import ( | |||
| 	"github.com/google/go-cmp/cmp" | ||||
| 	"github.com/google/go-cmp/cmp/cmpopts" | ||||
| 	"github.com/prometheus/alertmanager/pkg/labels" | ||||
| 	"github.com/prometheus/common/model" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"xorm.io/xorm" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/components/simplejson" | ||||
| 	"github.com/grafana/grafana/pkg/models" | ||||
| 	"github.com/grafana/grafana/pkg/services/datasources" | ||||
| 	ngModels "github.com/grafana/grafana/pkg/services/ngalert/models" | ||||
| 	"github.com/grafana/grafana/pkg/services/sqlstore/migrations" | ||||
| 	"github.com/grafana/grafana/pkg/services/sqlstore/migrations/ualert" | ||||
| 	"github.com/grafana/grafana/pkg/services/sqlstore/migrator" | ||||
|  | @ -157,6 +159,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 							Routes: []*ualert.Route{ | ||||
| 								{Receiver: "notifier1", Matchers: createAlertNameMatchers("alert1")}, // These Matchers are temporary and will be replaced below with generated rule_uid.
 | ||||
| 								{Matchers: createAlertNameMatchers("alert2"), Routes: []*ualert.Route{ | ||||
|  | @ -178,6 +181,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "notifier6", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 							Routes: []*ualert.Route{ | ||||
| 								{Matchers: createAlertNameMatchers("alert4"), Routes: []*ualert.Route{ | ||||
| 									{Receiver: "notifier4", Matchers: createAlertNameMatchers("alert4"), Continue: true}, | ||||
|  | @ -210,6 +214,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 						}, | ||||
| 						Receivers: []*ualert.PostableApiReceiver{ | ||||
| 							{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}}, | ||||
|  | @ -230,6 +235,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "notifier1", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 						}, | ||||
| 						Receivers: []*ualert.PostableApiReceiver{ | ||||
| 							{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}}, | ||||
|  | @ -250,6 +256,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 						}, | ||||
| 						Receivers: []*ualert.PostableApiReceiver{ | ||||
| 							{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}}, | ||||
|  | @ -273,6 +280,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 						}, | ||||
| 						Receivers: []*ualert.PostableApiReceiver{ | ||||
| 							{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}}, | ||||
|  | @ -298,6 +306,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 						}, | ||||
| 						Receivers: []*ualert.PostableApiReceiver{ | ||||
| 							{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}}, | ||||
|  | @ -323,6 +332,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 							Routes: []*ualert.Route{ | ||||
| 								{Receiver: "notifier1", Matchers: createAlertNameMatchers("alert1")}, | ||||
| 								{Matchers: createAlertNameMatchers("alert2"), Routes: []*ualert.Route{ | ||||
|  | @ -351,6 +361,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 						}, | ||||
| 						Receivers: []*ualert.PostableApiReceiver{ | ||||
| 							{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}}, | ||||
|  | @ -373,6 +384,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 						}, | ||||
| 						Receivers: []*ualert.PostableApiReceiver{ | ||||
| 							{Name: "notifier1", GrafanaManagedReceivers: []*ualert.PostableGrafanaReceiver{{Name: "notifier1", Type: "email"}}}, | ||||
|  | @ -396,6 +408,7 @@ func TestDashAlertMigration(t *testing.T) { | |||
| 					AlertmanagerConfig: ualert.PostableApiAlertingConfig{ | ||||
| 						Route: &ualert.Route{ | ||||
| 							Receiver:   "autogen-contact-point-default", | ||||
| 							GroupByStr: []string{ngModels.FolderTitleLabel, model.AlertNameLabel}, | ||||
| 							Routes: []*ualert.Route{ | ||||
| 								{Receiver: "notifier1", Matchers: createAlertNameMatchers("alert1")}, | ||||
| 							}, | ||||
|  |  | |||
|  | @ -26,7 +26,8 @@ const ( | |||
| 	alertmanagerDefaultConfiguration = `{ | ||||
| 	"alertmanager_config": { | ||||
| 		"route": { | ||||
| 			"receiver": "grafana-default-email" | ||||
| 			"receiver": "grafana-default-email", | ||||
| 			"group_by": ["grafana_folder", "alertname"] | ||||
| 		}, | ||||
| 		"receivers": [{ | ||||
| 			"name": "grafana-default-email", | ||||
|  |  | |||
|  | @ -1832,7 +1832,8 @@ func TestAlertmanagerStatus(t *testing.T) { | |||
| 	}, | ||||
| 	"config": { | ||||
| 		"route": { | ||||
| 			"receiver": "grafana-default-email" | ||||
| 			"receiver": "grafana-default-email", | ||||
| 			"group_by": ["grafana_folder", "alertname"] | ||||
| 		}, | ||||
| 		"templates": null, | ||||
| 		"receivers": [{ | ||||
|  |  | |||
|  | @ -25,7 +25,8 @@ const defaultAlertmanagerConfigJSON = ` | |||
| 	"template_files": null, | ||||
| 	"alertmanager_config": { | ||||
| 		"route": { | ||||
| 			"receiver": "grafana-default-email" | ||||
| 			"receiver": "grafana-default-email", | ||||
| 			"group_by": ["grafana_folder", "alertname"] | ||||
| 		}, | ||||
| 		"templates": null, | ||||
| 		"receivers": [{ | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ import { AccessControlAction } from 'app/types'; | |||
| import AmRoutes from './AmRoutes'; | ||||
| import { fetchAlertManagerConfig, fetchStatus, updateAlertManagerConfig } from './api/alertmanager'; | ||||
| import { mockDataSource, MockDataSourceSrv, someCloudAlertManagerConfig, someCloudAlertManagerStatus } from './mocks'; | ||||
| import { defaultGroupBy } from './utils/amroutes'; | ||||
| import { getAllDataSources } from './utils/config'; | ||||
| import { ALERTMANAGER_NAME_QUERY_KEY } from './utils/constants'; | ||||
| import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from './utils/datasource'; | ||||
|  | @ -363,7 +364,7 @@ describe('AmRoutes', () => { | |||
|         receivers: [{ name: 'default' }], | ||||
|         route: { | ||||
|           continue: false, | ||||
|           group_by: ['severity', 'namespace'], | ||||
|           group_by: defaultGroupBy.concat(['severity', 'namespace']), | ||||
|           receiver: 'default', | ||||
|           routes: [], | ||||
|           mute_time_intervals: [], | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ import { | |||
|   optionalPositiveInteger, | ||||
|   stringToSelectableValue, | ||||
|   stringsToSelectableValues, | ||||
|   commonGroupByOptions, | ||||
| } from '../../utils/amroutes'; | ||||
| import { makeAMLink } from '../../utils/misc'; | ||||
| import { timeOptions } from '../../utils/time'; | ||||
|  | @ -86,7 +87,7 @@ export const AmRootRouteForm: FC<AmRootRouteFormProps> = ({ | |||
|                     setValue('groupBy', [...field.value, opt]); | ||||
|                   }} | ||||
|                   onChange={(value) => onChange(mapMultiSelectValueToStrings(value))} | ||||
|                   options={groupByOptions} | ||||
|                   options={[...commonGroupByOptions, groupByOptions]} | ||||
|                 /> | ||||
|               )} | ||||
|               control={control} | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ import { | |||
|   optionalPositiveInteger, | ||||
|   stringToSelectableValue, | ||||
|   stringsToSelectableValues, | ||||
|   commonGroupByOptions, | ||||
| } from '../../utils/amroutes'; | ||||
| import { timeOptions } from '../../utils/time'; | ||||
| 
 | ||||
|  | @ -179,7 +180,7 @@ export const AmRoutesExpandedForm: FC<AmRoutesExpandedFormProps> = ({ onCancel, | |||
|                       setValue('groupBy', [...field.value, opt]); | ||||
|                     }} | ||||
|                     onChange={(value) => onChange(mapMultiSelectValueToStrings(value))} | ||||
|                     options={groupByOptions} | ||||
|                     options={[...commonGroupByOptions, groupByOptions]} | ||||
|                   /> | ||||
|                 )} | ||||
|                 control={control} | ||||
|  |  | |||
|  | @ -59,10 +59,20 @@ export const emptyArrayFieldMatcher: MatcherFieldValue = { | |||
|   operator: MatcherOperator.equal, | ||||
| }; | ||||
| 
 | ||||
| // Default route group_by labels for newly created routes.
 | ||||
| export const defaultGroupBy = ['grafana_folder', 'alertname']; | ||||
| 
 | ||||
| // Common route group_by options for multiselect drop-down
 | ||||
| export const commonGroupByOptions = [ | ||||
|   { label: 'grafana_folder', value: 'grafana_folder' }, | ||||
|   { label: 'alertname', value: 'alertname' }, | ||||
|   { label: 'Disable (...)', value: '...' }, | ||||
| ]; | ||||
| 
 | ||||
| export const emptyRoute: FormAmRoute = { | ||||
|   id: '', | ||||
|   overrideGrouping: false, | ||||
|   groupBy: [], | ||||
|   groupBy: defaultGroupBy, | ||||
|   object_matchers: [], | ||||
|   routes: [], | ||||
|   continue: false, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue