opsgenie.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package notifiers
  2. import (
  3. "fmt"
  4. "strconv"
  5. "github.com/grafana/grafana/pkg/bus"
  6. "github.com/grafana/grafana/pkg/components/simplejson"
  7. "github.com/grafana/grafana/pkg/log"
  8. "github.com/grafana/grafana/pkg/metrics"
  9. m "github.com/grafana/grafana/pkg/models"
  10. "github.com/grafana/grafana/pkg/services/alerting"
  11. )
  12. func init() {
  13. alerting.RegisterNotifier("opsgenie", NewOpsGenieNotifier)
  14. }
  15. var (
  16. opsgenieCreateAlertURL string = "https://api.opsgenie.com/v1/json/alert"
  17. opsgenieCloseAlertURL string = "https://api.opsgenie.com/v1/json/alert/close"
  18. )
  19. func NewOpsGenieNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
  20. autoClose := model.Settings.Get("autoClose").MustBool(true)
  21. apiKey := model.Settings.Get("apiKey").MustString()
  22. if apiKey == "" {
  23. return nil, alerting.ValidationError{Reason: "Could not find api key property in settings"}
  24. }
  25. return &OpsGenieNotifier{
  26. NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
  27. ApiKey: apiKey,
  28. AutoClose: autoClose,
  29. log: log.New("alerting.notifier.opsgenie"),
  30. }, nil
  31. }
  32. type OpsGenieNotifier struct {
  33. NotifierBase
  34. ApiKey string
  35. AutoClose bool
  36. log log.Logger
  37. }
  38. func (this *OpsGenieNotifier) Notify(evalContext *alerting.EvalContext) error {
  39. metrics.M_Alerting_Notification_Sent_OpsGenie.Inc(1)
  40. var err error
  41. switch evalContext.Rule.State {
  42. case m.AlertStateOK:
  43. if this.AutoClose {
  44. err = this.closeAlert(evalContext)
  45. }
  46. case m.AlertStateAlerting:
  47. err = this.createAlert(evalContext)
  48. }
  49. return err
  50. }
  51. func (this *OpsGenieNotifier) createAlert(evalContext *alerting.EvalContext) error {
  52. this.log.Info("Creating OpsGenie alert", "ruleId", evalContext.Rule.Id, "notification", this.Name)
  53. ruleUrl, err := evalContext.GetRuleUrl()
  54. if err != nil {
  55. this.log.Error("Failed get rule link", "error", err)
  56. return err
  57. }
  58. bodyJSON := simplejson.New()
  59. bodyJSON.Set("apiKey", this.ApiKey)
  60. bodyJSON.Set("message", evalContext.Rule.Name)
  61. bodyJSON.Set("source", "Grafana")
  62. bodyJSON.Set("alias", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10))
  63. bodyJSON.Set("description", fmt.Sprintf("%s - %s\n%s", evalContext.Rule.Name, ruleUrl, evalContext.Rule.Message))
  64. details := simplejson.New()
  65. details.Set("url", ruleUrl)
  66. if evalContext.ImagePublicUrl != "" {
  67. details.Set("image", evalContext.ImagePublicUrl)
  68. }
  69. bodyJSON.Set("details", details)
  70. body, _ := bodyJSON.MarshalJSON()
  71. cmd := &m.SendWebhookSync{
  72. Url: opsgenieCreateAlertURL,
  73. Body: string(body),
  74. HttpMethod: "POST",
  75. }
  76. if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
  77. this.log.Error("Failed to send notification to OpsGenie", "error", err, "body", string(body))
  78. }
  79. return nil
  80. }
  81. func (this *OpsGenieNotifier) closeAlert(evalContext *alerting.EvalContext) error {
  82. this.log.Info("Closing OpsGenie alert", "ruleId", evalContext.Rule.Id, "notification", this.Name)
  83. bodyJSON := simplejson.New()
  84. bodyJSON.Set("apiKey", this.ApiKey)
  85. bodyJSON.Set("alias", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10))
  86. body, _ := bodyJSON.MarshalJSON()
  87. cmd := &m.SendWebhookSync{
  88. Url: opsgenieCloseAlertURL,
  89. Body: string(body),
  90. HttpMethod: "POST",
  91. }
  92. if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
  93. this.log.Error("Failed to send notification to OpsGenie", "error", err, "body", string(body))
  94. return err
  95. }
  96. return nil
  97. }