mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Revert changes post code review and move them to notification page
This commit is contained in:
@@ -21,18 +21,17 @@ type AlertRule struct {
|
|||||||
ExecutionError string `json:"executionError"`
|
ExecutionError string `json:"executionError"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
CanEdit bool `json:"canEdit"`
|
CanEdit bool `json:"canEdit"`
|
||||||
NotifyOnce bool `json:"notifyOnce"`
|
|
||||||
NotifyEval uint64 `json:"notifyEval"`
|
|
||||||
NotifyFreq uint64 `json:"notifyFrequency"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlertNotification struct {
|
type AlertNotification struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
IsDefault bool `json:"isDefault"`
|
IsDefault bool `json:"isDefault"`
|
||||||
Created time.Time `json:"created"`
|
NotifyOnce bool `json:"notifyOnce"`
|
||||||
Updated time.Time `json:"updated"`
|
Frequency bool `json:"frequency"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlertTestCommand struct {
|
type AlertTestCommand struct {
|
||||||
@@ -62,9 +61,11 @@ type EvalMatch struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NotificationTestCommand struct {
|
type NotificationTestCommand struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Settings *simplejson.Json `json:"settings"`
|
NotifyOnce bool `json:"notifyOnce"`
|
||||||
|
Frequency time.Duration `json:"frequency"`
|
||||||
|
Settings *simplejson.Json `json:"settings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PauseAlertCommand struct {
|
type PauseAlertCommand struct {
|
||||||
|
|||||||
@@ -72,9 +72,6 @@ type Alert struct {
|
|||||||
Silenced bool
|
Silenced bool
|
||||||
ExecutionError string
|
ExecutionError string
|
||||||
Frequency int64
|
Frequency int64
|
||||||
NotifyOnce bool
|
|
||||||
NotifyFreq uint64
|
|
||||||
NotifyEval uint64
|
|
||||||
|
|
||||||
EvalData *simplejson.Json
|
EvalData *simplejson.Json
|
||||||
NewStateDate time.Time
|
NewStateDate time.Time
|
||||||
@@ -98,8 +95,6 @@ func (this *Alert) ContainsUpdates(other *Alert) bool {
|
|||||||
result := false
|
result := false
|
||||||
result = result || this.Name != other.Name
|
result = result || this.Name != other.Name
|
||||||
result = result || this.Message != other.Message
|
result = result || this.Message != other.Message
|
||||||
result = result || this.NotifyOnce != other.NotifyOnce
|
|
||||||
result = result || (!other.NotifyOnce && this.NotifyFreq != other.NotifyFreq)
|
|
||||||
|
|
||||||
if this.Settings != nil && other.Settings != nil {
|
if this.Settings != nil && other.Settings != nil {
|
||||||
json1, err1 := this.Settings.Encode()
|
json1, err1 := this.Settings.Encode()
|
||||||
@@ -164,10 +159,6 @@ type SetAlertStateCommand struct {
|
|||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type IncAlertEvalCommand struct {
|
|
||||||
AlertId int64
|
|
||||||
}
|
|
||||||
|
|
||||||
//Queries
|
//Queries
|
||||||
type GetAlertsQuery struct {
|
type GetAlertsQuery struct {
|
||||||
OrgId int64
|
OrgId int64
|
||||||
|
|||||||
@@ -7,32 +7,38 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type AlertNotification struct {
|
type AlertNotification struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
OrgId int64 `json:"-"`
|
OrgId int64 `json:"-"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
IsDefault bool `json:"isDefault"`
|
NotifyOnce bool `json:"notifyOnce"`
|
||||||
Settings *simplejson.Json `json:"settings"`
|
Frequency time.Duration `json:"frequency"`
|
||||||
Created time.Time `json:"created"`
|
IsDefault bool `json:"isDefault"`
|
||||||
Updated time.Time `json:"updated"`
|
Settings *simplejson.Json `json:"settings"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateAlertNotificationCommand struct {
|
type CreateAlertNotificationCommand struct {
|
||||||
Name string `json:"name" binding:"Required"`
|
Name string `json:"name" binding:"Required"`
|
||||||
Type string `json:"type" binding:"Required"`
|
Type string `json:"type" binding:"Required"`
|
||||||
IsDefault bool `json:"isDefault"`
|
NotifyOnce bool `json:"notifyOnce" binding:"Required"`
|
||||||
Settings *simplejson.Json `json:"settings"`
|
Frequency time.Duration `json:"frequency"`
|
||||||
|
IsDefault bool `json:"isDefault"`
|
||||||
|
Settings *simplejson.Json `json:"settings"`
|
||||||
|
|
||||||
OrgId int64 `json:"-"`
|
OrgId int64 `json:"-"`
|
||||||
Result *AlertNotification
|
Result *AlertNotification
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateAlertNotificationCommand struct {
|
type UpdateAlertNotificationCommand struct {
|
||||||
Id int64 `json:"id" binding:"Required"`
|
Id int64 `json:"id" binding:"Required"`
|
||||||
Name string `json:"name" binding:"Required"`
|
Name string `json:"name" binding:"Required"`
|
||||||
Type string `json:"type" binding:"Required"`
|
Type string `json:"type" binding:"Required"`
|
||||||
IsDefault bool `json:"isDefault"`
|
NotifyOnce string `json:"notifyOnce" binding:"Required"`
|
||||||
Settings *simplejson.Json `json:"settings" binding:"Required"`
|
Frequency string `json:"frequency"`
|
||||||
|
IsDefault bool `json:"isDefault"`
|
||||||
|
Settings *simplejson.Json `json:"settings" binding:"Required"`
|
||||||
|
|
||||||
OrgId int64 `json:"-"`
|
OrgId int64 `json:"-"`
|
||||||
Result *AlertNotification
|
Result *AlertNotification
|
||||||
@@ -63,3 +69,34 @@ type GetAllAlertNotificationsQuery struct {
|
|||||||
|
|
||||||
Result []*AlertNotification
|
Result []*AlertNotification
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NotificationJournal struct {
|
||||||
|
Id int64
|
||||||
|
OrgId int64
|
||||||
|
AlertId int64
|
||||||
|
NotifierId int64
|
||||||
|
SentAt time.Time
|
||||||
|
Success bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type RecordNotificationJournalCommand struct {
|
||||||
|
OrgId int64
|
||||||
|
AlertId int64
|
||||||
|
NotifierId int64
|
||||||
|
SentAt time.Time
|
||||||
|
Success bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetLatestNotificationQuery struct {
|
||||||
|
OrgId int64
|
||||||
|
AlertId int64
|
||||||
|
NotifierId int64
|
||||||
|
|
||||||
|
Result *NotificationJournal
|
||||||
|
}
|
||||||
|
|
||||||
|
type CleanNotificationJournalCommand struct {
|
||||||
|
OrgId int64
|
||||||
|
AlertId int64
|
||||||
|
NotifierId int64
|
||||||
|
}
|
||||||
|
|||||||
@@ -143,3 +143,18 @@ func (c *EvalContext) GetNewState() m.AlertStateType {
|
|||||||
|
|
||||||
return m.AlertStateOK
|
return m.AlertStateOK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *EvalContext) LastNotify(notifierId int64) *time.Time {
|
||||||
|
cmd := &m.GetLatestNotificationQuery{
|
||||||
|
OrgId: c.Rule.OrgId,
|
||||||
|
AlertId: c.Rule.Id,
|
||||||
|
NotifierId: notifierId,
|
||||||
|
}
|
||||||
|
if err := bus.Dispatch(cmd); err != nil {
|
||||||
|
c.log.Warn("Could not determine last time alert",
|
||||||
|
c.Rule.Name, "notified")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cmd.Result.SentAt
|
||||||
|
}
|
||||||
|
|||||||
@@ -122,8 +122,6 @@ func (e *DashAlertExtractor) getAlertFromPanels(jsonWithPanels *simplejson.Json,
|
|||||||
Handler: jsonAlert.Get("handler").MustInt64(),
|
Handler: jsonAlert.Get("handler").MustInt64(),
|
||||||
Message: jsonAlert.Get("message").MustString(),
|
Message: jsonAlert.Get("message").MustString(),
|
||||||
Frequency: frequency,
|
Frequency: frequency,
|
||||||
NotifyOnce: jsonAlert.Get("notifyOnce").MustBool(),
|
|
||||||
NotifyFreq: jsonAlert.Get("notifyFrequency").MustUint64(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, condition := range jsonAlert.Get("conditions").MustArray() {
|
for _, condition := range jsonAlert.Get("conditions").MustArray() {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ type Notifier interface {
|
|||||||
|
|
||||||
GetNotifierId() int64
|
GetNotifierId() int64
|
||||||
GetIsDefault() bool
|
GetIsDefault() bool
|
||||||
|
GetNotifyOnce() bool
|
||||||
|
GetFrequency() time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type NotifierSlice []Notifier
|
type NotifierSlice []Notifier
|
||||||
|
|||||||
@@ -66,7 +66,17 @@ func (n *notificationService) sendNotifications(context *EvalContext, notifiers
|
|||||||
not := notifier //avoid updating scope variable in go routine
|
not := notifier //avoid updating scope variable in go routine
|
||||||
n.log.Debug("Sending notification", "type", not.GetType(), "id", not.GetNotifierId(), "isDefault", not.GetIsDefault())
|
n.log.Debug("Sending notification", "type", not.GetType(), "id", not.GetNotifierId(), "isDefault", not.GetIsDefault())
|
||||||
metrics.M_Alerting_Notification_Sent.WithLabelValues(not.GetType()).Inc()
|
metrics.M_Alerting_Notification_Sent.WithLabelValues(not.GetType()).Inc()
|
||||||
g.Go(func() error { return not.Notify(context) })
|
g.Go(func() error {
|
||||||
|
success := not.Notify(context) == nil
|
||||||
|
cmd := &m.RecordNotificationJournalCommand{
|
||||||
|
OrgId: context.Rule.OrgId,
|
||||||
|
AlertId: context.Rule.Id,
|
||||||
|
NotifierId: not.GetNotifierId(),
|
||||||
|
SentAt: time.Now(),
|
||||||
|
Success: success,
|
||||||
|
}
|
||||||
|
return bus.Dispatch(cmd)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return g.Wait()
|
return g.Wait()
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func NewAlertmanagerNotifier(model *m.AlertNotification) (alerting.Notifier, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &AlertmanagerNotifier{
|
return &AlertmanagerNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Url: url,
|
Url: url,
|
||||||
log: log.New("alerting.notifier.prometheus-alertmanager"),
|
log: log.New("alerting.notifier.prometheus-alertmanager"),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package notifiers
|
package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/services/alerting"
|
"github.com/grafana/grafana/pkg/services/alerting"
|
||||||
@@ -12,9 +14,11 @@ type NotifierBase struct {
|
|||||||
Id int64
|
Id int64
|
||||||
IsDeault bool
|
IsDeault bool
|
||||||
UploadImage bool
|
UploadImage bool
|
||||||
|
NotifyOnce bool
|
||||||
|
Frequency time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNotifierBase(id int64, isDefault bool, name, notifierType string, model *simplejson.Json) NotifierBase {
|
func NewNotifierBase(id int64, isDefault bool, name, notifierType string, notifyOnce bool, frequency time.Duration, model *simplejson.Json) NotifierBase {
|
||||||
uploadImage := true
|
uploadImage := true
|
||||||
value, exist := model.CheckGet("uploadImage")
|
value, exist := model.CheckGet("uploadImage")
|
||||||
if exist {
|
if exist {
|
||||||
@@ -27,15 +31,17 @@ func NewNotifierBase(id int64, isDefault bool, name, notifierType string, model
|
|||||||
IsDeault: isDefault,
|
IsDeault: isDefault,
|
||||||
Type: notifierType,
|
Type: notifierType,
|
||||||
UploadImage: uploadImage,
|
UploadImage: uploadImage,
|
||||||
|
NotifyOnce: notifyOnce,
|
||||||
|
Frequency: frequency,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultShouldNotify(context *alerting.EvalContext) bool {
|
func defaultShouldNotify(context *alerting.EvalContext, notifyOnce bool, frequency time.Duration, lastNotify *time.Time) bool {
|
||||||
// Only notify on state change.
|
// Only notify on state change.
|
||||||
if context.PrevAlertState == context.Rule.State && context.Rule.NotifyOnce {
|
if context.PrevAlertState == context.Rule.State && notifyOnce {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !context.Rule.NotifyOnce && context.Rule.NotifyEval != 0 {
|
if !notifyOnce && lastNotify != nil && lastNotify.Add(frequency).After(time.Now()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Do not notify when we become OK for the first time.
|
// Do not notify when we become OK for the first time.
|
||||||
@@ -46,7 +52,8 @@ func defaultShouldNotify(context *alerting.EvalContext) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *NotifierBase) ShouldNotify(context *alerting.EvalContext) bool {
|
func (n *NotifierBase) ShouldNotify(context *alerting.EvalContext) bool {
|
||||||
return defaultShouldNotify(context)
|
lastNotify := context.LastNotify(n.Id)
|
||||||
|
return defaultShouldNotify(context, n.NotifyOnce, n.Frequency, lastNotify)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NotifierBase) GetType() string {
|
func (n *NotifierBase) GetType() string {
|
||||||
@@ -64,3 +71,11 @@ func (n *NotifierBase) GetNotifierId() int64 {
|
|||||||
func (n *NotifierBase) GetIsDefault() bool {
|
func (n *NotifierBase) GetIsDefault() bool {
|
||||||
return n.IsDeault
|
return n.IsDeault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NotifierBase) GetNotifyOnce() bool {
|
||||||
|
return n.NotifyOnce
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NotifierBase) GetFrequency() time.Duration {
|
||||||
|
return n.Frequency
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func NewDingDingNotifier(model *m.AlertNotification) (alerting.Notifier, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &DingDingNotifier{
|
return &DingDingNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Url: url,
|
Url: url,
|
||||||
log: log.New("alerting.notifier.dingding"),
|
log: log.New("alerting.notifier.dingding"),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func NewDiscordNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &DiscordNotifier{
|
return &DiscordNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
WebhookURL: url,
|
WebhookURL: url,
|
||||||
log: log.New("alerting.notifier.discord"),
|
log: log.New("alerting.notifier.discord"),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func NewEmailNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return &EmailNotifier{
|
return &EmailNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Addresses: addresses,
|
Addresses: addresses,
|
||||||
log: log.New("alerting.notifier.email"),
|
log: log.New("alerting.notifier.email"),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ func NewHipChatNotifier(model *models.AlertNotification) (alerting.Notifier, err
|
|||||||
roomId := model.Settings.Get("roomid").MustString()
|
roomId := model.Settings.Get("roomid").MustString()
|
||||||
|
|
||||||
return &HipChatNotifier{
|
return &HipChatNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Url: url,
|
Url: url,
|
||||||
ApiKey: apikey,
|
ApiKey: apikey,
|
||||||
RoomId: roomId,
|
RoomId: roomId,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func NewKafkaNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &KafkaNotifier{
|
return &KafkaNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
Topic: topic,
|
Topic: topic,
|
||||||
log: log.New("alerting.notifier.kafka"),
|
log: log.New("alerting.notifier.kafka"),
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func NewLINENotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &LineNotifier{
|
return &LineNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Token: token,
|
Token: token,
|
||||||
log: log.New("alerting.notifier.line"),
|
log: log.New("alerting.notifier.line"),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func NewOpsGenieNotifier(model *m.AlertNotification) (alerting.Notifier, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &OpsGenieNotifier{
|
return &OpsGenieNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
ApiKey: apiKey,
|
ApiKey: apiKey,
|
||||||
ApiUrl: apiUrl,
|
ApiUrl: apiUrl,
|
||||||
AutoClose: autoClose,
|
AutoClose: autoClose,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &PagerdutyNotifier{
|
return &PagerdutyNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Key: key,
|
Key: key,
|
||||||
AutoResolve: autoResolve,
|
AutoResolve: autoResolve,
|
||||||
log: log.New("alerting.notifier.pagerduty"),
|
log: log.New("alerting.notifier.pagerduty"),
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ func NewPushoverNotifier(model *m.AlertNotification) (alerting.Notifier, error)
|
|||||||
return nil, alerting.ValidationError{Reason: "API token not given"}
|
return nil, alerting.ValidationError{Reason: "API token not given"}
|
||||||
}
|
}
|
||||||
return &PushoverNotifier{
|
return &PushoverNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
UserKey: userKey,
|
UserKey: userKey,
|
||||||
ApiToken: apiToken,
|
ApiToken: apiToken,
|
||||||
Priority: priority,
|
Priority: priority,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func NewSensuNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &SensuNotifier{
|
return &SensuNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Url: url,
|
Url: url,
|
||||||
User: model.Settings.Get("username").MustString(),
|
User: model.Settings.Get("username").MustString(),
|
||||||
Source: model.Settings.Get("source").MustString(),
|
Source: model.Settings.Get("source").MustString(),
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func NewSlackNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
uploadImage := model.Settings.Get("uploadImage").MustBool(true)
|
uploadImage := model.Settings.Get("uploadImage").MustBool(true)
|
||||||
|
|
||||||
return &SlackNotifier{
|
return &SlackNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Url: url,
|
Url: url,
|
||||||
Recipient: recipient,
|
Recipient: recipient,
|
||||||
Mention: mention,
|
Mention: mention,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func NewTeamsNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &TeamsNotifier{
|
return &TeamsNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Url: url,
|
Url: url,
|
||||||
log: log.New("alerting.notifier.teams"),
|
log: log.New("alerting.notifier.teams"),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func NewTelegramNotifier(model *m.AlertNotification) (alerting.Notifier, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &TelegramNotifier{
|
return &TelegramNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
BotToken: botToken,
|
BotToken: botToken,
|
||||||
ChatID: chatId,
|
ChatID: chatId,
|
||||||
UploadImage: uploadImage,
|
UploadImage: uploadImage,
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ func NewThreemaNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &ThreemaNotifier{
|
return &ThreemaNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
GatewayID: gatewayID,
|
GatewayID: gatewayID,
|
||||||
RecipientID: recipientID,
|
RecipientID: recipientID,
|
||||||
APISecret: apiSecret,
|
APISecret: apiSecret,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func NewVictoropsNotifier(model *models.AlertNotification) (alerting.Notifier, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &VictoropsNotifier{
|
return &VictoropsNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
URL: url,
|
URL: url,
|
||||||
AutoResolve: autoResolve,
|
AutoResolve: autoResolve,
|
||||||
log: log.New("alerting.notifier.victorops"),
|
log: log.New("alerting.notifier.victorops"),
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func NewWebHookNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &WebhookNotifier{
|
return &WebhookNotifier{
|
||||||
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
|
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.NotifyOnce, model.Frequency, model.Settings),
|
||||||
Url: url,
|
Url: url,
|
||||||
User: model.Settings.Get("username").MustString(),
|
User: model.Settings.Get("username").MustString(),
|
||||||
Password: model.Settings.Get("password").MustString(),
|
Password: model.Settings.Get("password").MustString(),
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bus.Dispatch(&m.IncAlertEvalCommand{AlertId: evalContext.Rule.Id})
|
|
||||||
handler.notifier.SendIfNeeded(evalContext)
|
handler.notifier.SendIfNeeded(evalContext)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ type Rule struct {
|
|||||||
State m.AlertStateType
|
State m.AlertStateType
|
||||||
Conditions []Condition
|
Conditions []Condition
|
||||||
Notifications []int64
|
Notifications []int64
|
||||||
NotifyOnce bool
|
|
||||||
NotifyFreq uint64
|
|
||||||
NotifyEval uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValidationError struct {
|
type ValidationError struct {
|
||||||
@@ -100,9 +97,6 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) {
|
|||||||
model.Name = ruleDef.Name
|
model.Name = ruleDef.Name
|
||||||
model.Message = ruleDef.Message
|
model.Message = ruleDef.Message
|
||||||
model.Frequency = ruleDef.Frequency
|
model.Frequency = ruleDef.Frequency
|
||||||
model.NotifyOnce = ruleDef.NotifyOnce
|
|
||||||
model.NotifyFreq = ruleDef.NotifyFreq
|
|
||||||
model.NotifyEval = ruleDef.NotifyEval
|
|
||||||
model.State = ruleDef.State
|
model.State = ruleDef.State
|
||||||
model.NoDataState = m.NoDataOption(ruleDef.Settings.Get("noDataState").MustString("no_data"))
|
model.NoDataState = m.NoDataOption(ruleDef.Settings.Get("noDataState").MustString("no_data"))
|
||||||
model.ExecutionErrorState = m.ExecutionErrorOption(ruleDef.Settings.Get("executionErrorState").MustString("alerting"))
|
model.ExecutionErrorState = m.ExecutionErrorOption(ruleDef.Settings.Get("executionErrorState").MustString("alerting"))
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ func init() {
|
|||||||
bus.AddHandler("sql", GetAlertStatesForDashboard)
|
bus.AddHandler("sql", GetAlertStatesForDashboard)
|
||||||
bus.AddHandler("sql", PauseAlert)
|
bus.AddHandler("sql", PauseAlert)
|
||||||
bus.AddHandler("sql", PauseAllAlerts)
|
bus.AddHandler("sql", PauseAllAlerts)
|
||||||
bus.AddHandler("sql", IncAlertEval)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAlertById(query *m.GetAlertByIdQuery) error {
|
func GetAlertById(query *m.GetAlertByIdQuery) error {
|
||||||
@@ -189,7 +188,7 @@ func updateAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *DBS
|
|||||||
if alertToUpdate.ContainsUpdates(alert) {
|
if alertToUpdate.ContainsUpdates(alert) {
|
||||||
alert.Updated = timeNow()
|
alert.Updated = timeNow()
|
||||||
alert.State = alertToUpdate.State
|
alert.State = alertToUpdate.State
|
||||||
sess.MustCols("message", "notify_freq", "notify_once")
|
sess.MustCols("message")
|
||||||
_, err := sess.Id(alert.Id).Update(alert)
|
_, err := sess.Id(alert.Id).Update(alert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -344,22 +343,3 @@ func GetAlertStatesForDashboard(query *m.GetAlertStatesForDashboardQuery) error
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func IncAlertEval(cmd *m.IncAlertEvalCommand) error {
|
|
||||||
return inTransaction(func(sess *DBSession) error {
|
|
||||||
alert := m.Alert{}
|
|
||||||
|
|
||||||
if _, err := sess.Id(cmd.AlertId).Get(&alert); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
alert.NotifyEval = (alert.NotifyEval + 1) % alert.NotifyFreq
|
|
||||||
|
|
||||||
sess.MustCols("notify_eval")
|
|
||||||
if _, err := sess.Id(cmd.AlertId).Update(alert); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ func init() {
|
|||||||
bus.AddHandler("sql", DeleteAlertNotification)
|
bus.AddHandler("sql", DeleteAlertNotification)
|
||||||
bus.AddHandler("sql", GetAlertNotificationsToSend)
|
bus.AddHandler("sql", GetAlertNotificationsToSend)
|
||||||
bus.AddHandler("sql", GetAllAlertNotifications)
|
bus.AddHandler("sql", GetAllAlertNotifications)
|
||||||
|
bus.AddHandler("sql", RecordNotificationJournal)
|
||||||
|
bus.AddHandler("sql", GetLatestNotification)
|
||||||
|
bus.AddHandler("sql", CleanNotificationJournal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteAlertNotification(cmd *m.DeleteAlertNotificationCommand) error {
|
func DeleteAlertNotification(cmd *m.DeleteAlertNotificationCommand) error {
|
||||||
@@ -138,13 +141,15 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
alertNotification := &m.AlertNotification{
|
alertNotification := &m.AlertNotification{
|
||||||
OrgId: cmd.OrgId,
|
OrgId: cmd.OrgId,
|
||||||
Name: cmd.Name,
|
Name: cmd.Name,
|
||||||
Type: cmd.Type,
|
Type: cmd.Type,
|
||||||
Settings: cmd.Settings,
|
Settings: cmd.Settings,
|
||||||
Created: time.Now(),
|
NotifyOnce: cmd.NotifyOnce,
|
||||||
Updated: time.Now(),
|
Frequency: cmd.Frequency,
|
||||||
IsDefault: cmd.IsDefault,
|
Created: time.Now(),
|
||||||
|
Updated: time.Now(),
|
||||||
|
IsDefault: cmd.IsDefault,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = sess.Insert(alertNotification); err != nil {
|
if _, err = sess.Insert(alertNotification); err != nil {
|
||||||
@@ -192,3 +197,42 @@ func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RecordNotificationJournal(cmd *m.RecordNotificationJournalCommand) error {
|
||||||
|
return inTransaction(func(sess *DBSession) error {
|
||||||
|
journalEntry := &m.NotificationJournal{
|
||||||
|
OrgId: cmd.OrgId,
|
||||||
|
AlertId: cmd.AlertId,
|
||||||
|
NotifierId: cmd.NotifierId,
|
||||||
|
SentAt: cmd.SentAt,
|
||||||
|
Success: cmd.Success,
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := sess.Insert(journalEntry); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLatestNotification(cmd *m.GetLatestNotificationQuery) error {
|
||||||
|
return inTransaction(func(sess *DBSession) error {
|
||||||
|
notificationJournal := &m.NotificationJournal{}
|
||||||
|
_, err := sess.OrderBy("notification_journal.sent_at").Desc().Where("notification_journal.org_id = ? AND notification_journal.alert_id = ? AND notification_journal.notifier_id = ?", cmd.OrgId, cmd.AlertId, cmd.NotifierId).Get(notificationJournal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Result = notificationJournal
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func CleanNotificationJournal(cmd *m.CleanNotificationJournalCommand) error {
|
||||||
|
return inTransaction(func(sess *DBSession) error {
|
||||||
|
sql := "DELETE FROM notification_journal WHERE notification_journal.org_id = ? AND notification_journal.alert_id = ? AND notification_journal.notifier_id = ?"
|
||||||
|
_, err := sess.Exec(sql, cmd.OrgId, cmd.AlertId, cmd.NotifierId)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,9 +29,6 @@ func addAlertMigrations(mg *Migrator) {
|
|||||||
{Name: "state_changes", Type: DB_Int, Nullable: false},
|
{Name: "state_changes", Type: DB_Int, Nullable: false},
|
||||||
{Name: "created", Type: DB_DateTime, Nullable: false},
|
{Name: "created", Type: DB_DateTime, Nullable: false},
|
||||||
{Name: "updated", Type: DB_DateTime, Nullable: false},
|
{Name: "updated", Type: DB_DateTime, Nullable: false},
|
||||||
{Name: "notify_once", Type: DB_Bool, Nullable: false},
|
|
||||||
{Name: "notify_freq", Type: DB_Int, Nullable: false},
|
|
||||||
{Name: "notify_eval", Type: DB_Int, Nullable: false},
|
|
||||||
},
|
},
|
||||||
Indices: []*Index{
|
Indices: []*Index{
|
||||||
{Cols: []string{"org_id", "id"}, Type: IndexType},
|
{Cols: []string{"org_id", "id"}, Type: IndexType},
|
||||||
@@ -68,8 +65,32 @@ func addAlertMigrations(mg *Migrator) {
|
|||||||
mg.AddMigration("Add column is_default", NewAddColumnMigration(alert_notification, &Column{
|
mg.AddMigration("Add column is_default", NewAddColumnMigration(alert_notification, &Column{
|
||||||
Name: "is_default", Type: DB_Bool, Nullable: false, Default: "0",
|
Name: "is_default", Type: DB_Bool, Nullable: false, Default: "0",
|
||||||
}))
|
}))
|
||||||
|
mg.AddMigration("Add column frequency", NewAddColumnMigration(alert_notification, &Column{
|
||||||
|
Name: "frequency", Type: DB_BigInt, Nullable: true,
|
||||||
|
}))
|
||||||
|
mg.AddMigration("Add column notify_once", NewAddColumnMigration(alert_notification, &Column{
|
||||||
|
Name: "notify_once", Type: DB_Bool, Nullable: false, Default: "1",
|
||||||
|
}))
|
||||||
mg.AddMigration("add index alert_notification org_id & name", NewAddIndexMigration(alert_notification, alert_notification.Indices[0]))
|
mg.AddMigration("add index alert_notification org_id & name", NewAddIndexMigration(alert_notification, alert_notification.Indices[0]))
|
||||||
|
|
||||||
|
notification_journal := Table{
|
||||||
|
Name: "notification_journal",
|
||||||
|
Columns: []*Column{
|
||||||
|
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||||
|
{Name: "org_id", Type: DB_BigInt, Nullable: false},
|
||||||
|
{Name: "alert_id", Type: DB_BigInt, Nullable: false},
|
||||||
|
{Name: "notifier_id", Type: DB_BigInt, Nullable: false},
|
||||||
|
{Name: "sent_at", Type: DB_DateTime, Nullable: false},
|
||||||
|
{Name: "success", Type: DB_Bool, Nullable: false},
|
||||||
|
},
|
||||||
|
Indices: []*Index{
|
||||||
|
{Cols: []string{"org_id", "alert_id", "notifier_id"}, Type: IndexType},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mg.AddMigration("create notification_journal table v1", NewAddTableMigration(notification_journal))
|
||||||
|
mg.AddMigration("add index notification_journal org_id & alert_id & notifier_id", NewAddIndexMigration(notification_journal, notification_journal.Indices[0]))
|
||||||
|
|
||||||
mg.AddMigration("Update alert table charset", NewTableCharsetMigration("alert", []*Column{
|
mg.AddMigration("Update alert table charset", NewTableCharsetMigration("alert", []*Column{
|
||||||
{Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false},
|
{Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false},
|
||||||
{Name: "message", Type: DB_Text, Nullable: false},
|
{Name: "message", Type: DB_Text, Nullable: false},
|
||||||
|
|||||||
@@ -167,9 +167,6 @@ export class AlertTabCtrl {
|
|||||||
alert.noDataState = alert.noDataState || 'no_data';
|
alert.noDataState = alert.noDataState || 'no_data';
|
||||||
alert.executionErrorState = alert.executionErrorState || 'alerting';
|
alert.executionErrorState = alert.executionErrorState || 'alerting';
|
||||||
alert.frequency = alert.frequency || '60s';
|
alert.frequency = alert.frequency || '60s';
|
||||||
alert.notifyFrequency = alert.notifyFrequency || 10;
|
|
||||||
alert.notifyOnce = alert.notifyOnce == null ? true : alert.notifyOnce;
|
|
||||||
alert.frequency = alert.frequency || '60s';
|
|
||||||
alert.handler = alert.handler || 1;
|
alert.handler = alert.handler || 1;
|
||||||
alert.notifications = alert.notifications || [];
|
alert.notifications = alert.notifications || [];
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export class AlertNotificationEditCtrl {
|
|||||||
model: any;
|
model: any;
|
||||||
defaults: any = {
|
defaults: any = {
|
||||||
type: 'email',
|
type: 'email',
|
||||||
|
notifyOnce: true,
|
||||||
settings: {
|
settings: {
|
||||||
httpMethod: 'POST',
|
httpMethod: 'POST',
|
||||||
autoResolve: true,
|
autoResolve: true,
|
||||||
@@ -102,6 +103,7 @@ export class AlertNotificationEditCtrl {
|
|||||||
var payload = {
|
var payload = {
|
||||||
name: this.model.name,
|
name: this.model.name,
|
||||||
type: this.model.type,
|
type: this.model.type,
|
||||||
|
frequency: this.model.frequency,
|
||||||
settings: this.model.settings,
|
settings: this.model.settings,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,6 @@
|
|||||||
<input type="text" class="gf-form-input width-20" ng-model="ctrl.alert.name">
|
<input type="text" class="gf-form-input width-20" ng-model="ctrl.alert.name">
|
||||||
<span class="gf-form-label">Evaluate every</span>
|
<span class="gf-form-label">Evaluate every</span>
|
||||||
<input class="gf-form-input max-width-5" type="text" ng-model="ctrl.alert.frequency"></input>
|
<input class="gf-form-input max-width-5" type="text" ng-model="ctrl.alert.frequency"></input>
|
||||||
<a class="gf-form-label" ng-click="ctrl.alert.notifyOnce = !ctrl.alert.notifyOnce;">{{ ctrl.alert.notifyOnce ? 'Notify on state change' : 'Notify every' }}</a>
|
|
||||||
<input class="gf-form-input max-width-5" type="number" ng-model="ctrl.alert.notifyFrequency" ng-hide="ctrl.alert.notifyOnce"></input>
|
|
||||||
<span class="gf-form-label" ng-hide="ctrl.alert.notifyOnce">evaluations</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,11 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<a class="gf-form-label width-12" ng-click="ctrl.model.notifyOnce = !ctrl.model.notifyOnce;">{{ ctrl.model.notifyOnce ? 'Notify on state change' : 'Notify at most every' }}</a>
|
||||||
|
<input class="gf-form-input max-width-10" type="number" required ng-model="ctrl.model.frequency" required ng-hide="ctrl.model.notifyOnce"></input>
|
||||||
|
<span class="gf-form-label max-width-5" ng-hide="ctrl.model.notifyOnce">seconds</span>
|
||||||
|
</div>
|
||||||
<gf-form-switch
|
<gf-form-switch
|
||||||
class="gf-form"
|
class="gf-form"
|
||||||
label="Send on all alerts"
|
label="Send on all alerts"
|
||||||
|
|||||||
Reference in New Issue
Block a user