notifier.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package alerting
  2. import (
  3. "fmt"
  4. "github.com/grafana/grafana/pkg/bus"
  5. "github.com/grafana/grafana/pkg/components/simplejson"
  6. "github.com/grafana/grafana/pkg/log"
  7. m "github.com/grafana/grafana/pkg/models"
  8. "github.com/grafana/grafana/pkg/services/alerting/alertstates"
  9. "github.com/grafana/grafana/pkg/setting"
  10. )
  11. type NotifierImpl struct {
  12. log log.Logger
  13. }
  14. func NewNotifier() *NotifierImpl {
  15. return &NotifierImpl{
  16. log: log.New("alerting.notifier"),
  17. }
  18. }
  19. func (n *NotifierImpl) Notify(alertResult *AlertResult) {
  20. notifiers := n.getNotifiers(alertResult.AlertJob.Rule.OrgId, []int64{1, 2})
  21. for _, notifier := range notifiers {
  22. warn := alertResult.State == alertstates.Warn && notifier.SendWarning
  23. crit := alertResult.State == alertstates.Critical && notifier.SendCritical
  24. if warn || crit {
  25. n.log.Info("Sending notification", "state", alertResult.State, "type", notifier.Type)
  26. go notifier.Notifierr.Dispatch(alertResult)
  27. }
  28. }
  29. }
  30. type Notification struct {
  31. Name string
  32. Type string
  33. SendWarning bool
  34. SendCritical bool
  35. Notifierr NotificationDispatcher
  36. }
  37. type EmailNotifier struct {
  38. To string
  39. log log.Logger
  40. }
  41. func (this *EmailNotifier) Dispatch(alertResult *AlertResult) {
  42. this.log.Info("Sending email")
  43. grafanaUrl := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort)
  44. if setting.AppSubUrl != "" {
  45. grafanaUrl += "/" + setting.AppSubUrl
  46. }
  47. cmd := &m.SendEmailCommand{
  48. Data: map[string]interface{}{
  49. "Name": "Name",
  50. "State": alertResult.State,
  51. "Description": alertResult.Description,
  52. "TriggeredAlerts": alertResult.TriggeredAlerts,
  53. "DashboardLink": grafanaUrl + "/dashboard/db/alerting",
  54. "AlertPageUrl": grafanaUrl + "/alerting",
  55. },
  56. To: []string{this.To},
  57. Template: "alert_notification.html",
  58. }
  59. err := bus.Dispatch(cmd)
  60. if err != nil {
  61. this.log.Error("Could not send alert notification as email", "error", err)
  62. }
  63. }
  64. type WebhookNotifier struct {
  65. Url string
  66. User string
  67. Password string
  68. log log.Logger
  69. }
  70. func (this *WebhookNotifier) Dispatch(alertResult *AlertResult) {
  71. this.log.Info("Sending webhook")
  72. bodyJSON := simplejson.New()
  73. bodyJSON.Set("name", alertResult.AlertJob.Rule.Name)
  74. bodyJSON.Set("state", alertResult.State)
  75. bodyJSON.Set("trigged", alertResult.TriggeredAlerts)
  76. body, _ := bodyJSON.MarshalJSON()
  77. cmd := &m.SendWebhook{
  78. Url: this.Url,
  79. User: this.User,
  80. Password: this.Password,
  81. Body: string(body),
  82. }
  83. bus.Dispatch(cmd)
  84. }
  85. type NotificationDispatcher interface {
  86. Dispatch(alertResult *AlertResult)
  87. }
  88. func (n *NotifierImpl) getNotifiers(orgId int64, notificationGroups []int64) []*Notification {
  89. query := &m.GetAlertNotificationQuery{
  90. OrgID: orgId,
  91. Ids: notificationGroups,
  92. }
  93. err := bus.Dispatch(query)
  94. if err != nil {
  95. n.log.Error("Failed to read notifications", "error", err)
  96. }
  97. var result []*Notification
  98. for _, notification := range query.Result {
  99. not, err := NewNotificationFromDBModel(notification)
  100. if err == nil {
  101. result = append(result, not)
  102. }
  103. }
  104. return result
  105. }
  106. func NewNotificationFromDBModel(model *m.AlertNotification) (*Notification, error) {
  107. notifier, err := createNotifier(model.Type, model.Settings)
  108. if err != nil {
  109. return nil, err
  110. }
  111. return &Notification{
  112. Name: model.Name,
  113. Type: model.Type,
  114. Notifierr: notifier,
  115. SendCritical: !model.Settings.Get("ignoreCrit").MustBool(),
  116. SendWarning: !model.Settings.Get("ignoreWarn").MustBool(),
  117. }, nil
  118. }
  119. var createNotifier = func(notificationType string, settings *simplejson.Json) (NotificationDispatcher, error) {
  120. if notificationType == "email" {
  121. to := settings.Get("to").MustString()
  122. if to == "" {
  123. return nil, fmt.Errorf("Could not find to propertie in settings")
  124. }
  125. return &EmailNotifier{
  126. To: to,
  127. log: log.New("alerting.notification.email"),
  128. }, nil
  129. }
  130. url := settings.Get("url").MustString()
  131. if url == "" {
  132. return nil, fmt.Errorf("Could not find url propertie in settings")
  133. }
  134. return &WebhookNotifier{
  135. Url: url,
  136. User: settings.Get("user").MustString(),
  137. Password: settings.Get("password").MustString(),
  138. log: log.New("alerting.notification.webhook"),
  139. }, nil
  140. }