github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/alerts/alertsHandler/cronJobHandler.go (about)

     1  package alertsHandler
     2  
     3  /*
     4  Copyright 2023.
     5  
     6  Licensed under the Apache License, Version 2.0 (the "License");
     7  you may not use this file except in compliance with the License.
     8  You may obtain a copy of the License at
     9  
    10      http://www.apache.org/licenses/LICENSE-2.0
    11  
    12  Unless required by applicable law or agreed to in writing, software
    13  distributed under the License is distributed on an "AS IS" BASIS,
    14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15  See the License for the specific language governing permissions and
    16  limitations under the License.
    17  */
    18  
    19  import (
    20  	"time"
    21  
    22  	"github.com/go-co-op/gocron"
    23  	"github.com/siglens/siglens/pkg/alerts/alertutils"
    24  	"github.com/siglens/siglens/pkg/ast/pipesearch"
    25  	log "github.com/sirupsen/logrus"
    26  )
    27  
    28  var s = gocron.NewScheduler(time.UTC)
    29  
    30  func VerifyAlertCronJobExists(alertDataObj *alertutils.AlertDetails) bool {
    31  	job_ids := s.GetAllTags()
    32  	for _, id := range job_ids {
    33  		if alertDataObj.AlertId == id {
    34  			return true
    35  		}
    36  	}
    37  	return false
    38  }
    39  
    40  func AddCronJob(alertDataObj *alertutils.AlertDetails) (*gocron.Job, error) {
    41  	evaluationIntervalInSec := int(alertDataObj.EvalInterval * 60)
    42  
    43  	cron_job, err := s.Every(evaluationIntervalInSec).Second().Tag(alertDataObj.AlertId).DoWithJobDetails(evaluate, alertDataObj)
    44  	if err != nil {
    45  		log.Errorf("AddCronJob: Error adding a new cronJob to the CRON Scheduler: %s", err)
    46  		return &gocron.Job{}, err
    47  	}
    48  	s.StartAsync()
    49  	//TODO: for multinode set up, set create and set node_id to which this alert will be assigned
    50  	//TODO: node_id should be created using hash function
    51  	return cron_job, nil
    52  }
    53  
    54  func AddMinionSearchCronJob(alertDataObj *alertutils.MinionSearch) (*gocron.Job, error) {
    55  	evaluationIntervalInSec := int(alertDataObj.EvalInterval * 60)
    56  
    57  	cron_job, err := s.Every(evaluationIntervalInSec).Second().Tag(alertDataObj.AlertId).DoWithJobDetails(evaluateMinionSearch, alertDataObj)
    58  	if err != nil {
    59  		log.Errorf("AddMinionSearchCronJob: Error adding a new cronJob to the CRON Scheduler: %s", err)
    60  		return &gocron.Job{}, err
    61  	}
    62  	s.StartAsync()
    63  	//TODO: for multinode set up, set create and set node_id to which this alert will be assigned
    64  	//TODO: node_id should be created using hash function
    65  	return cron_job, nil
    66  }
    67  
    68  func RemoveCronJob(alertId string) error {
    69  	err := s.RemoveByTag(alertId)
    70  	if err != nil {
    71  		log.Errorf("ALERTSERVICE: RemoveCronJob error %v.", err)
    72  		return err
    73  	}
    74  	return nil
    75  }
    76  
    77  func evaluate(alertToEvaluate *alertutils.AlertDetails, job gocron.Job) {
    78  	serResVal := pipesearch.ProcessAlertsPipeSearchRequest(alertToEvaluate.QueryParams)
    79  	if serResVal == -1 {
    80  		log.Errorf("ALERTSERVICE: evaluate: Empty response returned by server.")
    81  		return
    82  	}
    83  	isFiring := evaluateConditions(serResVal, &alertToEvaluate.Condition, alertToEvaluate.Value)
    84  	if isFiring {
    85  		err := updateAlertState(alertToEvaluate.AlertId, alertutils.Firing)
    86  
    87  		if err != nil {
    88  			log.Errorf("ALERTSERVICE: evaluate: could not update the state to FIRING. Alert=%+v & err=%+v.", alertToEvaluate.AlertName, err)
    89  
    90  		}
    91  
    92  		alertEvent := alertutils.AlertHistoryDetails{
    93  			AlertId:          alertToEvaluate.AlertId,
    94  			EventDescription: alertutils.AlertFiring,
    95  			UserName:         alertutils.SystemGeneratedAlert,
    96  			EventTriggeredAt: time.Now().UTC(),
    97  		}
    98  		_, err = databaseObj.CreateAlertHistory(&alertEvent)
    99  		if err != nil {
   100  			log.Errorf("ALERTSERVICE: evaluate: could not create alert event in alert history. found error = %v", err)
   101  		}
   102  		err = NotifyAlertHandlerRequest(alertToEvaluate.AlertId)
   103  		if err != nil {
   104  			log.Errorf("ALERTSERVICE: evaluate: could not setup the notification handler. found error = %v", err)
   105  			return
   106  		}
   107  	} else {
   108  		err := updateAlertState(alertToEvaluate.AlertId, alertutils.Inactive)
   109  		if err != nil {
   110  			log.Errorf("ALERTSERVICE: evaluate: could not update the state to INACTIVE. Alert=%+v & err=%+v.", alertToEvaluate.AlertName, err)
   111  
   112  		}
   113  
   114  		alertEvent := alertutils.AlertHistoryDetails{
   115  			AlertId:          alertToEvaluate.AlertId,
   116  			EventDescription: alertutils.AlertNormal,
   117  			UserName:         alertutils.SystemGeneratedAlert,
   118  			EventTriggeredAt: time.Now().UTC(),
   119  		}
   120  		_, err = databaseObj.CreateAlertHistory(&alertEvent)
   121  		if err != nil {
   122  			log.Errorf("ALERTSERVICE: evaluate: could not create alert event in alert history. found error = %v", err)
   123  		}
   124  
   125  	}
   126  }
   127  
   128  func updateAlertState(alertId string, alertState alertutils.AlertState) error {
   129  	err := databaseObj.UpdateAlertStateByAlertID(alertId, alertState)
   130  	return err
   131  }
   132  
   133  func evaluateConditions(serResVal int, queryCond *alertutils.AlertQueryCondition, val float32) bool {
   134  	switch *queryCond {
   135  	case alertutils.IsAbove:
   136  		return serResVal > int(val)
   137  	case alertutils.IsBelow:
   138  		return serResVal < int(val)
   139  	case alertutils.IsEqualTo:
   140  		return serResVal == int(val)
   141  	case alertutils.IsNotEqualTo:
   142  		return serResVal != int(val)
   143  	case alertutils.HasNoValue:
   144  		return serResVal == 0
   145  	default:
   146  		return false
   147  	}
   148  }
   149  
   150  func evaluateMinionSearch(msToEvaluate *alertutils.MinionSearch, job gocron.Job) {
   151  	serResVal := pipesearch.ProcessAlertsPipeSearchRequest(msToEvaluate.QueryParams)
   152  	if serResVal == -1 {
   153  		log.Errorf("MinionSearch: evaluate: Empty response returned by server.")
   154  		return
   155  	}
   156  	isFiring := evaluateConditions(serResVal, &msToEvaluate.Condition, msToEvaluate.Value)
   157  	if isFiring {
   158  		err := updateMinionSearchState(msToEvaluate.AlertId, alertutils.Firing)
   159  		if err != nil {
   160  			log.Errorf("MinionSearch: evaluate: could not update the state to FIRING. Alert=%+v & err=%+v.", msToEvaluate.AlertName, err)
   161  		}
   162  
   163  		alertEvent := alertutils.AlertHistoryDetails{
   164  			AlertId:          msToEvaluate.AlertId,
   165  			EventDescription: alertutils.AlertFiring,
   166  			UserName:         alertutils.SystemGeneratedAlert,
   167  			EventTriggeredAt: time.Now().UTC(),
   168  		}
   169  		_, err = databaseObj.CreateAlertHistory(&alertEvent)
   170  		if err != nil {
   171  			log.Errorf("MinionSearch: evaluate: could not create alert event in alert history. found error = %v", err)
   172  
   173  		}
   174  		err = NotifyAlertHandlerRequest(msToEvaluate.AlertId)
   175  		if err != nil {
   176  			log.Errorf("MinionSearch: evaluate: could not setup the notification handler. found error = %v", err)
   177  			return
   178  		}
   179  	} else {
   180  		err := updateMinionSearchState(msToEvaluate.AlertId, alertutils.Inactive)
   181  		if err != nil {
   182  			log.Errorf("MinionSearch: evaluate: could not update the state to INACTIVE. Alert=%+v & err=%+v.", msToEvaluate.AlertName, err)
   183  
   184  		}
   185  
   186  		alertEvent := alertutils.AlertHistoryDetails{
   187  			AlertId:          msToEvaluate.AlertId,
   188  			EventDescription: alertutils.AlertNormal,
   189  			UserName:         alertutils.SystemGeneratedAlert,
   190  			EventTriggeredAt: time.Now().UTC(),
   191  		}
   192  		_, err = databaseObj.CreateAlertHistory(&alertEvent)
   193  		if err != nil {
   194  			log.Errorf("MinionSearch: evaluate: could not create alert event in alert history. found error = %v", err)
   195  
   196  		}
   197  	}
   198  }
   199  
   200  func updateMinionSearchState(alertId string, alertState alertutils.AlertState) error {
   201  	err := databaseObj.UpdateMinionSearchStateByAlertID(alertId, alertState)
   202  	return err
   203  }