alerting: only check frequency when not send once

This commit is contained in:
bergquist
2018-06-04 22:19:27 +02:00
parent 0e647db485
commit 93124f38fa
5 changed files with 135 additions and 81 deletions

View File

@@ -192,17 +192,7 @@ func GetAlertNotifications(c *m.ReqContext) Response {
result := make([]*dtos.AlertNotification, 0) result := make([]*dtos.AlertNotification, 0)
for _, notification := range query.Result { for _, notification := range query.Result {
result = append(result, &dtos.AlertNotification{ result = append(result, dtos.NewAlertNotification(notification))
Id: notification.Id,
Name: notification.Name,
Type: notification.Type,
IsDefault: notification.IsDefault,
Created: notification.Created,
Updated: notification.Updated,
Frequency: notification.Frequency.String(),
NotifyOnce: notification.NotifyOnce,
Settings: notification.Settings,
})
} }
return JSON(200, result) return JSON(200, result)
@@ -218,19 +208,7 @@ func GetAlertNotificationByID(c *m.ReqContext) Response {
return Error(500, "Failed to get alert notifications", err) return Error(500, "Failed to get alert notifications", err)
} }
result := &dtos.AlertNotification{ return JSON(200, dtos.NewAlertNotification(query.Result))
Id: query.Result.Id,
Name: query.Result.Name,
Type: query.Result.Type,
IsDefault: query.Result.IsDefault,
Created: query.Result.Created,
Updated: query.Result.Updated,
Frequency: query.Result.Frequency.String(),
NotifyOnce: query.Result.NotifyOnce,
Settings: query.Result.Settings,
}
return JSON(200, result)
} }
func CreateAlertNotification(c *m.ReqContext, cmd m.CreateAlertNotificationCommand) Response { func CreateAlertNotification(c *m.ReqContext, cmd m.CreateAlertNotificationCommand) Response {
@@ -240,19 +218,7 @@ func CreateAlertNotification(c *m.ReqContext, cmd m.CreateAlertNotificationComma
return Error(500, "Failed to create alert notification", err) return Error(500, "Failed to create alert notification", err)
} }
result := &dtos.AlertNotification{ return JSON(200, dtos.NewAlertNotification(cmd.Result))
Id: cmd.Result.Id,
Name: cmd.Result.Name,
Type: cmd.Result.Type,
IsDefault: cmd.Result.IsDefault,
Created: cmd.Result.Created,
Updated: cmd.Result.Updated,
Frequency: cmd.Result.Frequency.String(),
NotifyOnce: cmd.Result.NotifyOnce,
Settings: cmd.Result.Settings,
}
return JSON(200, result)
} }
func UpdateAlertNotification(c *m.ReqContext, cmd m.UpdateAlertNotificationCommand) Response { func UpdateAlertNotification(c *m.ReqContext, cmd m.UpdateAlertNotificationCommand) Response {
@@ -262,19 +228,7 @@ func UpdateAlertNotification(c *m.ReqContext, cmd m.UpdateAlertNotificationComma
return Error(500, "Failed to update alert notification", err) return Error(500, "Failed to update alert notification", err)
} }
result := &dtos.AlertNotification{ return JSON(200, dtos.NewAlertNotification(cmd.Result))
Id: cmd.Result.Id,
Name: cmd.Result.Name,
Type: cmd.Result.Type,
IsDefault: cmd.Result.IsDefault,
Created: cmd.Result.Created,
Updated: cmd.Result.Updated,
Frequency: cmd.Result.Frequency.String(),
NotifyOnce: cmd.Result.NotifyOnce,
Settings: cmd.Result.Settings,
}
return JSON(200, result)
} }
func DeleteAlertNotification(c *m.ReqContext) Response { func DeleteAlertNotification(c *m.ReqContext) Response {

View File

@@ -2,6 +2,7 @@ package api
import ( import (
"testing" "testing"
"time"
"github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
@@ -11,6 +12,24 @@ import (
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestRemoveZeroUnitsFromInterval(t *testing.T) {
tcs := []struct {
interval time.Duration
expected string
}{
{interval: time.Duration(time.Hour), expected: "1h"},
{interval: time.Duration(time.Hour + time.Minute), expected: "1h1m"},
{interval: time.Duration((time.Hour * 10) + time.Minute), expected: "10h1m"},
}
for _, tc := range tcs {
got := removeZeroesFromDuration(tc.interval)
if got != tc.expected {
t.Errorf("expected %s got %s internval: %v", tc.expected, got, tc.interval)
}
}
}
func TestAlertingApiEndpoint(t *testing.T) { func TestAlertingApiEndpoint(t *testing.T) {
Convey("Given an alert in a dashboard with an acl", t, func() { Convey("Given an alert in a dashboard with an acl", t, func() {

View File

@@ -1,11 +1,12 @@
package dtos package dtos
import ( import (
"strings"
"time" "time"
"github.com/grafana/grafana/pkg/components/null" "github.com/grafana/grafana/pkg/components/null"
"github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/components/simplejson"
m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
) )
type AlertRule struct { type AlertRule struct {
@@ -14,7 +15,7 @@ type AlertRule struct {
PanelId int64 `json:"panelId"` PanelId int64 `json:"panelId"`
Name string `json:"name"` Name string `json:"name"`
Message string `json:"message"` Message string `json:"message"`
State m.AlertStateType `json:"state"` State models.AlertStateType `json:"state"`
NewStateDate time.Time `json:"newStateDate"` NewStateDate time.Time `json:"newStateDate"`
EvalDate time.Time `json:"evalDate"` EvalDate time.Time `json:"evalDate"`
EvalData *simplejson.Json `json:"evalData"` EvalData *simplejson.Json `json:"evalData"`
@@ -23,6 +24,30 @@ type AlertRule struct {
CanEdit bool `json:"canEdit"` CanEdit bool `json:"canEdit"`
} }
func removeZeroesFromDuration(interval time.Duration) string {
frequency := interval.String()
frequency = strings.Replace(frequency, "0h", "", 1)
frequency = strings.Replace(frequency, "0m", "", 1)
frequency = strings.Replace(frequency, "0s", "", 1)
return frequency
}
func NewAlertNotification(notification *models.AlertNotification) *AlertNotification {
return &AlertNotification{
Id: notification.Id,
Name: notification.Name,
Type: notification.Type,
IsDefault: notification.IsDefault,
Created: notification.Created,
Updated: notification.Updated,
Frequency: removeZeroesFromDuration(notification.Frequency),
NotifyOnce: notification.NotifyOnce,
Settings: notification.Settings,
}
}
type AlertNotification struct { type AlertNotification struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
@@ -42,7 +67,7 @@ type AlertTestCommand struct {
type AlertTestResult struct { type AlertTestResult struct {
Firing bool `json:"firing"` Firing bool `json:"firing"`
State m.AlertStateType `json:"state"` State models.AlertStateType `json:"state"`
ConditionEvals string `json:"conditionEvals"` ConditionEvals string `json:"conditionEvals"`
TimeMs string `json:"timeMs"` TimeMs string `json:"timeMs"`
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`

View File

@@ -144,15 +144,17 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
return fmt.Errorf("Alert notification name %s already exists", cmd.Name) return fmt.Errorf("Alert notification name %s already exists", cmd.Name)
} }
var frequency time.Duration
if !cmd.NotifyOnce {
if cmd.Frequency == "" { if cmd.Frequency == "" {
return fmt.Errorf("Alert notification frequency required") return m.ErrNotificationFrequencyNotFound
} }
var frequency time.Duration
frequency, err = time.ParseDuration(cmd.Frequency) frequency, err = time.ParseDuration(cmd.Frequency)
if err != nil { if err != nil {
return err return err
} }
}
alertNotification := &m.AlertNotification{ alertNotification := &m.AlertNotification{
OrgId: cmd.OrgId, OrgId: cmd.OrgId,
@@ -200,6 +202,7 @@ func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
current.IsDefault = cmd.IsDefault current.IsDefault = cmd.IsDefault
current.NotifyOnce = cmd.NotifyOnce current.NotifyOnce = cmd.NotifyOnce
if !current.NotifyOnce {
if cmd.Frequency == "" { if cmd.Frequency == "" {
return m.ErrNotificationFrequencyNotFound return m.ErrNotificationFrequencyNotFound
} }
@@ -208,14 +211,16 @@ func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
if err != nil { if err != nil {
return err return err
} }
current.Frequency = frequency current.Frequency = frequency
}
sess.UseBool("is_default", "notify_once") sess.UseBool("is_default", "notify_once")
if affected, err := sess.ID(cmd.Id).Update(current); err != nil { if affected, err := sess.ID(cmd.Id).Update(current); err != nil {
return err return err
} else if affected == 0 { } else if affected == 0 {
return fmt.Errorf("Could not find alert notification") return fmt.Errorf("Could not update alert notification")
} }
cmd.Result = &current cmd.Result = &current

View File

@@ -11,7 +11,6 @@ import (
func TestAlertNotificationSQLAccess(t *testing.T) { func TestAlertNotificationSQLAccess(t *testing.T) {
Convey("Testing Alert notification sql access", t, func() { Convey("Testing Alert notification sql access", t, func() {
InitTestDB(t) InitTestDB(t)
var err error
Convey("Alert notifications should be empty", func() { Convey("Alert notifications should be empty", func() {
cmd := &m.GetAlertNotificationsQuery{ cmd := &m.GetAlertNotificationsQuery{
@@ -24,6 +23,58 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
So(cmd.Result, ShouldBeNil) So(cmd.Result, ShouldBeNil)
}) })
Convey("Cannot save alert notifier with notitfyonce = false", func() {
cmd := &m.CreateAlertNotificationCommand{
Name: "ops",
Type: "email",
OrgId: 1,
NotifyOnce: false,
Settings: simplejson.New(),
}
Convey("and missing frequency", func() {
err := CreateAlertNotificationCommand(cmd)
So(err, ShouldEqual, m.ErrNotificationFrequencyNotFound)
})
Convey("invalid frequency", func() {
cmd.Frequency = "invalid duration"
err := CreateAlertNotificationCommand(cmd)
So(err.Error(), ShouldEqual, "time: invalid duration invalid duration")
})
})
Convey("Cannot update alert notifier with notitfyonce = false", func() {
cmd := &m.CreateAlertNotificationCommand{
Name: "ops update",
Type: "email",
OrgId: 1,
NotifyOnce: true,
Settings: simplejson.New(),
}
err := CreateAlertNotificationCommand(cmd)
So(err, ShouldBeNil)
updateCmd := &m.UpdateAlertNotificationCommand{
Id: cmd.Result.Id,
NotifyOnce: false,
}
Convey("and missing frequency", func() {
err := UpdateAlertNotification(updateCmd)
So(err, ShouldEqual, m.ErrNotificationFrequencyNotFound)
})
Convey("invalid frequency", func() {
updateCmd.Frequency = "invalid duration"
err := UpdateAlertNotification(updateCmd)
So(err.Error(), ShouldEqual, "time: invalid duration invalid duration")
})
})
Convey("Can save Alert Notification", func() { Convey("Can save Alert Notification", func() {
cmd := &m.CreateAlertNotificationCommand{ cmd := &m.CreateAlertNotificationCommand{
Name: "ops", Name: "ops",
@@ -34,7 +85,7 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
Settings: simplejson.New(), Settings: simplejson.New(),
} }
err = CreateAlertNotificationCommand(cmd) err := CreateAlertNotificationCommand(cmd)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(cmd.Result.Id, ShouldNotEqual, 0) So(cmd.Result.Id, ShouldNotEqual, 0)
So(cmd.Result.OrgId, ShouldNotEqual, 0) So(cmd.Result.OrgId, ShouldNotEqual, 0)