mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Basic support for time_intervals (#83216)
This commit adds basic support for time_intervals, as mute_time_intervals is deprecated in Alertmanager and scheduled to be removed before 1.0. It does not add support for time_intervals in API or file provisioning, nor does it support exporting time intervals. This will be added in later commits to keep the changes as simple as possible.
This commit is contained in:
@@ -739,6 +739,8 @@ func (c *GettableApiAlertingConfig) GetReceivers() []*GettableApiReceiver {
|
||||
return c.Receivers
|
||||
}
|
||||
|
||||
func (c *GettableApiAlertingConfig) GetTimeIntervals() []config.TimeInterval { return c.TimeIntervals }
|
||||
|
||||
func (c *GettableApiAlertingConfig) GetMuteTimeIntervals() []config.MuteTimeInterval {
|
||||
return c.MuteTimeIntervals
|
||||
}
|
||||
@@ -803,6 +805,7 @@ type Config struct {
|
||||
Global *config.GlobalConfig `yaml:"global,omitempty" json:"global,omitempty"`
|
||||
Route *Route `yaml:"route,omitempty" json:"route,omitempty"`
|
||||
InhibitRules []config.InhibitRule `yaml:"inhibit_rules,omitempty" json:"inhibit_rules,omitempty"`
|
||||
TimeIntervals []config.TimeInterval `yaml:"time_intervals,omitempty" json:"time_intervals,omitempty"`
|
||||
MuteTimeIntervals []config.MuteTimeInterval `yaml:"mute_time_intervals,omitempty" json:"mute_time_intervals,omitempty"`
|
||||
Templates []string `yaml:"templates" json:"templates"`
|
||||
}
|
||||
@@ -936,6 +939,15 @@ func (c *Config) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
tiNames := make(map[string]struct{})
|
||||
for _, ti := range c.TimeIntervals {
|
||||
if ti.Name == "" {
|
||||
return fmt.Errorf("missing name in time interval")
|
||||
}
|
||||
if _, ok := tiNames[ti.Name]; ok {
|
||||
return fmt.Errorf("time interval %q is not unique", ti.Name)
|
||||
}
|
||||
tiNames[ti.Name] = struct{}{}
|
||||
}
|
||||
for _, mt := range c.MuteTimeIntervals {
|
||||
if mt.Name == "" {
|
||||
return fmt.Errorf("missing name in mute time interval")
|
||||
@@ -976,6 +988,8 @@ func (c *PostableApiAlertingConfig) GetReceivers() []*PostableApiReceiver {
|
||||
return c.Receivers
|
||||
}
|
||||
|
||||
func (c *PostableApiAlertingConfig) GetTimeIntervals() []config.TimeInterval { return c.TimeIntervals }
|
||||
|
||||
func (c *PostableApiAlertingConfig) GetMuteTimeIntervals() []config.MuteTimeInterval {
|
||||
return c.MuteTimeIntervals
|
||||
}
|
||||
|
||||
@@ -485,7 +485,50 @@ func Test_ConfigUnmashaling(t *testing.T) {
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "empty mute time name should error",
|
||||
desc: "missing time interval name should error",
|
||||
err: errors.New("missing name in time interval"),
|
||||
input: `
|
||||
{
|
||||
"route": {
|
||||
"receiver": "grafana-default-email"
|
||||
},
|
||||
"time_intervals": [
|
||||
{
|
||||
"name": "",
|
||||
"time_intervals": [
|
||||
{
|
||||
"times": [
|
||||
{
|
||||
"start_time": "00:00",
|
||||
"end_time": "12:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"templates": null,
|
||||
"receivers": [
|
||||
{
|
||||
"name": "grafana-default-email",
|
||||
"grafana_managed_receiver_configs": [
|
||||
{
|
||||
"uid": "uxwfZvtnz",
|
||||
"name": "email receiver",
|
||||
"type": "email",
|
||||
"disableResolveMessage": false,
|
||||
"settings": {
|
||||
"addresses": "<example@email.com>"
|
||||
},
|
||||
"secureFields": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
desc: "missing mute time interval name should error",
|
||||
err: errors.New("missing name in mute time interval"),
|
||||
input: `
|
||||
{
|
||||
@@ -529,7 +572,64 @@ func Test_ConfigUnmashaling(t *testing.T) {
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "not unique mute time names should error",
|
||||
desc: "duplicate time interval names should error",
|
||||
err: errors.New("time interval \"test1\" is not unique"),
|
||||
input: `
|
||||
{
|
||||
"route": {
|
||||
"receiver": "grafana-default-email"
|
||||
},
|
||||
"time_intervals": [
|
||||
{
|
||||
"name": "test1",
|
||||
"time_intervals": [
|
||||
{
|
||||
"times": [
|
||||
{
|
||||
"start_time": "00:00",
|
||||
"end_time": "12:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "test1",
|
||||
"time_intervals": [
|
||||
{
|
||||
"times": [
|
||||
{
|
||||
"start_time": "00:00",
|
||||
"end_time": "12:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"templates": null,
|
||||
"receivers": [
|
||||
{
|
||||
"name": "grafana-default-email",
|
||||
"grafana_managed_receiver_configs": [
|
||||
{
|
||||
"uid": "uxwfZvtnz",
|
||||
"name": "email receiver",
|
||||
"type": "email",
|
||||
"disableResolveMessage": false,
|
||||
"settings": {
|
||||
"addresses": "<example@email.com>"
|
||||
},
|
||||
"secureFields": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "duplicate mute time interval names should error",
|
||||
err: errors.New("mute time interval \"test1\" is not unique"),
|
||||
input: `
|
||||
{
|
||||
@@ -585,6 +685,65 @@ func Test_ConfigUnmashaling(t *testing.T) {
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "duplicate time and mute time interval names should error",
|
||||
err: errors.New("mute time interval \"test1\" is not unique"),
|
||||
input: `
|
||||
{
|
||||
"route": {
|
||||
"receiver": "grafana-default-email"
|
||||
},
|
||||
"mute_time_intervals": [
|
||||
{
|
||||
"name": "test1",
|
||||
"time_intervals": [
|
||||
{
|
||||
"times": [
|
||||
{
|
||||
"start_time": "00:00",
|
||||
"end_time": "12:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"time_intervals": [
|
||||
{
|
||||
"name": "test1",
|
||||
"time_intervals": [
|
||||
{
|
||||
"times": [
|
||||
{
|
||||
"start_time": "00:00",
|
||||
"end_time": "12:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"templates": null,
|
||||
"receivers": [
|
||||
{
|
||||
"name": "grafana-default-email",
|
||||
"grafana_managed_receiver_configs": [
|
||||
{
|
||||
"uid": "uxwfZvtnz",
|
||||
"name": "email receiver",
|
||||
"type": "email",
|
||||
"disableResolveMessage": false,
|
||||
"settings": {
|
||||
"addresses": "<example@email.com>"
|
||||
},
|
||||
"secureFields": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "mute time intervals on root route should error",
|
||||
err: errors.New("root route must not have any mute time intervals"),
|
||||
|
||||
@@ -111,6 +111,10 @@ func (a AlertingConfiguration) InhibitRules() []alertingNotify.InhibitRule {
|
||||
return a.alertmanagerConfig.InhibitRules
|
||||
}
|
||||
|
||||
func (a AlertingConfiguration) TimeIntervals() []alertingNotify.TimeInterval {
|
||||
return a.alertmanagerConfig.TimeIntervals
|
||||
}
|
||||
|
||||
func (a AlertingConfiguration) MuteTimeIntervals() []alertingNotify.MuteTimeInterval {
|
||||
return a.alertmanagerConfig.MuteTimeIntervals
|
||||
}
|
||||
|
||||
@@ -20,13 +20,14 @@ type NotificationSettingsValidator interface {
|
||||
|
||||
// staticValidator is a NotificationSettingsValidator that uses static pre-fetched values for available receivers and mute timings.
|
||||
type staticValidator struct {
|
||||
availableReceivers map[string]struct{}
|
||||
availableMuteTimings map[string]struct{}
|
||||
availableReceivers map[string]struct{}
|
||||
availableTimeIntervals map[string]struct{}
|
||||
}
|
||||
|
||||
// apiAlertingConfig contains the methods required to validate NotificationSettings and create autogen routes.
|
||||
type apiAlertingConfig[R receiver] interface {
|
||||
GetReceivers() []R
|
||||
GetTimeIntervals() []config.TimeInterval
|
||||
GetMuteTimeIntervals() []config.MuteTimeInterval
|
||||
GetRoute() *definitions.Route
|
||||
}
|
||||
@@ -42,14 +43,17 @@ func NewNotificationSettingsValidator[R receiver](am apiAlertingConfig[R]) Notif
|
||||
availableReceivers[receiver.GetName()] = struct{}{}
|
||||
}
|
||||
|
||||
availableMuteTimings := make(map[string]struct{})
|
||||
availableTimeIntervals := make(map[string]struct{})
|
||||
for _, interval := range am.GetTimeIntervals() {
|
||||
availableTimeIntervals[interval.Name] = struct{}{}
|
||||
}
|
||||
for _, interval := range am.GetMuteTimeIntervals() {
|
||||
availableMuteTimings[interval.Name] = struct{}{}
|
||||
availableTimeIntervals[interval.Name] = struct{}{}
|
||||
}
|
||||
|
||||
return staticValidator{
|
||||
availableReceivers: availableReceivers,
|
||||
availableMuteTimings: availableMuteTimings,
|
||||
availableReceivers: availableReceivers,
|
||||
availableTimeIntervals: availableTimeIntervals,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +67,7 @@ func (n staticValidator) Validate(settings models.NotificationSettings) error {
|
||||
errs = append(errs, fmt.Errorf("receiver '%s' does not exist", settings.Receiver))
|
||||
}
|
||||
for _, interval := range settings.MuteTimeIntervals {
|
||||
if _, ok := n.availableMuteTimings[interval]; !ok {
|
||||
if _, ok := n.availableTimeIntervals[interval]; !ok {
|
||||
errs = append(errs, fmt.Errorf("mute time interval '%s' does not exist", interval))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user