result_handler.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package alerting
  15. import (
  16. "time"
  17. "yunion.io/x/jsonutils"
  18. "yunion.io/x/log"
  19. "yunion.io/x/pkg/errors"
  20. "yunion.io/x/onecloud/pkg/monitor/models"
  21. )
  22. type resultHandler interface {
  23. handle(ctx *EvalContext) error
  24. }
  25. type defaultResultHandler struct {
  26. notifier *notificationService
  27. }
  28. func newResultHandler() *defaultResultHandler {
  29. return &defaultResultHandler{
  30. notifier: newNotificationService(),
  31. }
  32. }
  33. func (handler *defaultResultHandler) handle(evalCtx *EvalContext) error {
  34. execErr := ""
  35. annotationData := jsonutils.NewDict()
  36. if len(evalCtx.EvalMatches) > 0 {
  37. annotationData.Add(jsonutils.Marshal(evalCtx.EvalMatches), "evalMatches")
  38. }
  39. if evalCtx.Error != nil {
  40. execErr = evalCtx.Error.Error()
  41. annotationData.Add(jsonutils.NewString(evalCtx.Error.Error()), "error")
  42. } else if evalCtx.NoDataFound {
  43. annotationData.Add(jsonutils.JSONTrue, "noData")
  44. }
  45. if evalCtx.shouldUpdateAlertState() {
  46. log.Infof("New state change, alertId %s, prevState %s, newState %s", evalCtx.Rule.Id, evalCtx.PrevAlertState, evalCtx.Rule.State)
  47. alert, err := models.AlertManager.GetAlert(evalCtx.Rule.Id)
  48. if err != nil {
  49. log.Errorf("get alert %s error: %v", evalCtx.Rule.Id, err)
  50. return errors.Wrapf(err, "result get alert %s", evalCtx.Rule.Id)
  51. }
  52. input := models.AlertSetStateInput{
  53. State: evalCtx.Rule.State,
  54. UpdateStateTime: evalCtx.StartTime,
  55. ExecutionError: execErr,
  56. EvalData: annotationData,
  57. }
  58. if err := alert.SetState(input); err != nil {
  59. log.Errorf("Failed to set alert %s state: %v", evalCtx.Rule.Name, err)
  60. } else {
  61. // StateChanges is used for de duping alert notifications
  62. // when two servers are raising. This makes sure that the server
  63. // with the last state change always sends a notification
  64. evalCtx.Rule.StateChanges = alert.StateChanges
  65. // Update the last state change of the alert rule in memory
  66. evalCtx.Rule.LastStateChange = time.Now()
  67. }
  68. // TODO: save opslog
  69. }
  70. if evalCtx.Error != nil {
  71. return evalCtx.Error
  72. }
  73. if err := handler.notifier.SendIfNeeded(evalCtx); err != nil {
  74. return err
  75. }
  76. return nil
  77. }