notifier.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. "DashboardImage": grafanaUrl + "/render/dashboard-solo/db/alerting?from=1466169458375&to=1466171258375&panelId=1&width=1000&height=500",
  56. },
  57. To: []string{this.To},
  58. Template: "alert_notification.html",
  59. }
  60. err := bus.Dispatch(cmd)
  61. if err != nil {
  62. this.log.Error("Could not send alert notification as email", "error", err)
  63. }
  64. }
  65. type WebhookNotifier struct {
  66. Url string
  67. User string
  68. Password string
  69. log log.Logger
  70. }
  71. func (this *WebhookNotifier) Dispatch(alertResult *AlertResult) {
  72. this.log.Info("Sending webhook")
  73. bodyJSON := simplejson.New()
  74. bodyJSON.Set("name", alertResult.AlertJob.Rule.Name)
  75. bodyJSON.Set("state", alertResult.State)
  76. bodyJSON.Set("trigged", alertResult.TriggeredAlerts)
  77. body, _ := bodyJSON.MarshalJSON()
  78. cmd := &m.SendWebhook{
  79. Url: this.Url,
  80. User: this.User,
  81. Password: this.Password,
  82. Body: string(body),
  83. }
  84. bus.Dispatch(cmd)
  85. }
  86. type NotificationDispatcher interface {
  87. Dispatch(alertResult *AlertResult)
  88. }
  89. func (n *NotifierImpl) getNotifiers(orgId int64, notificationGroups []int64) []*Notification {
  90. query := &m.GetAlertNotificationQuery{
  91. OrgID: orgId,
  92. Ids: notificationGroups,
  93. }
  94. err := bus.Dispatch(query)
  95. if err != nil {
  96. n.log.Error("Failed to read notifications", "error", err)
  97. }
  98. var result []*Notification
  99. for _, notification := range query.Result {
  100. not, err := NewNotificationFromDBModel(notification)
  101. if err == nil {
  102. result = append(result, not)
  103. }
  104. }
  105. return result
  106. }
  107. func NewNotificationFromDBModel(model *m.AlertNotification) (*Notification, error) {
  108. notifier, err := createNotifier(model.Type, model.Settings)
  109. if err != nil {
  110. return nil, err
  111. }
  112. return &Notification{
  113. Name: model.Name,
  114. Type: model.Type,
  115. Notifierr: notifier,
  116. SendCritical: !model.Settings.Get("ignoreCrit").MustBool(),
  117. SendWarning: !model.Settings.Get("ignoreWarn").MustBool(),
  118. }, nil
  119. }
  120. var createNotifier = func(notificationType string, settings *simplejson.Json) (NotificationDispatcher, error) {
  121. if notificationType == "email" {
  122. to := settings.Get("to").MustString()
  123. if to == "" {
  124. return nil, fmt.Errorf("Could not find to propertie in settings")
  125. }
  126. return &EmailNotifier{
  127. To: to,
  128. log: log.New("alerting.notification.email"),
  129. }, nil
  130. }
  131. url := settings.Get("url").MustString()
  132. if url == "" {
  133. return nil, fmt.Errorf("Could not find url propertie in settings")
  134. }
  135. return &WebhookNotifier{
  136. Url: url,
  137. User: settings.Get("user").MustString(),
  138. Password: settings.Get("password").MustString(),
  139. log: log.New("alerting.notification.webhook"),
  140. }, nil
  141. }