160 lines
4.4 KiB
Go
160 lines
4.4 KiB
Go
package alerting
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana/pkg/log"
|
|
)
|
|
|
|
var (
|
|
descriptionFmt = "Actual value: %1.2f for %s. "
|
|
)
|
|
|
|
type HandlerImpl struct {
|
|
log log.Logger
|
|
alertJobTimeout time.Duration
|
|
}
|
|
|
|
func NewHandler() *HandlerImpl {
|
|
return &HandlerImpl{
|
|
log: log.New("alerting.executor"),
|
|
alertJobTimeout: time.Second * 5,
|
|
}
|
|
}
|
|
|
|
func (e *HandlerImpl) Execute(context *AlertResultContext) {
|
|
|
|
go e.eval(context)
|
|
|
|
select {
|
|
case <-time.After(e.alertJobTimeout):
|
|
context.Error = fmt.Errorf("Timeout")
|
|
context.EndTime = time.Now()
|
|
e.log.Debug("Job Execution timeout", "alertId", context.Rule.Id)
|
|
case <-context.DoneChan:
|
|
e.log.Debug("Job Execution done", "timing", context.GetDurationSeconds(), "alertId", context.Rule.Id, "firing", context.Firing)
|
|
}
|
|
|
|
}
|
|
|
|
func (e *HandlerImpl) eval(context *AlertResultContext) {
|
|
|
|
for _, condition := range context.Rule.Conditions {
|
|
condition.Eval(context)
|
|
|
|
// break if condition could not be evaluated
|
|
if context.Error != nil {
|
|
break
|
|
}
|
|
|
|
// break if result has not triggered yet
|
|
if context.Firing == false {
|
|
break
|
|
}
|
|
}
|
|
|
|
context.EndTime = time.Now()
|
|
context.DoneChan <- true
|
|
}
|
|
|
|
// func (e *HandlerImpl) executeQuery(job *AlertJob) (tsdb.TimeSeriesSlice, error) {
|
|
// getDsInfo := &m.GetDataSourceByIdQuery{
|
|
// Id: job.Rule.Query.DatasourceId,
|
|
// OrgId: job.Rule.OrgId,
|
|
// }
|
|
//
|
|
// if err := bus.Dispatch(getDsInfo); err != nil {
|
|
// return nil, fmt.Errorf("Could not find datasource")
|
|
// }
|
|
//
|
|
// req := e.GetRequestForAlertRule(job.Rule, getDsInfo.Result)
|
|
// result := make(tsdb.TimeSeriesSlice, 0)
|
|
//
|
|
// resp, err := tsdb.HandleRequest(req)
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("Alerting: GetSeries() tsdb.HandleRequest() error %v", err)
|
|
// }
|
|
//
|
|
// for _, v := range resp.Results {
|
|
// if v.Error != nil {
|
|
// return nil, fmt.Errorf("Alerting: GetSeries() tsdb.HandleRequest() response error %v", v)
|
|
// }
|
|
//
|
|
// result = append(result, v.Series...)
|
|
// }
|
|
//
|
|
// return result, nil
|
|
// }
|
|
//
|
|
// func (e *HandlerImpl) GetRequestForAlertRule(rule *AlertRule, datasource *m.DataSource) *tsdb.Request {
|
|
// e.log.Debug("GetRequest", "query", rule.Query.Query, "from", rule.Query.From, "datasourceId", datasource.Id)
|
|
// req := &tsdb.Request{
|
|
// TimeRange: tsdb.TimeRange{
|
|
// From: "-" + rule.Query.From,
|
|
// To: rule.Query.To,
|
|
// },
|
|
// Queries: []*tsdb.Query{
|
|
// {
|
|
// RefId: "A",
|
|
// Query: rule.Query.Query,
|
|
// DataSource: &tsdb.DataSourceInfo{
|
|
// Id: datasource.Id,
|
|
// Name: datasource.Name,
|
|
// PluginId: datasource.Type,
|
|
// Url: datasource.Url,
|
|
// },
|
|
// },
|
|
// },
|
|
// }
|
|
//
|
|
// return req
|
|
// }
|
|
//
|
|
// func (e *HandlerImpl) evaluateRule(rule *AlertRule, series tsdb.TimeSeriesSlice) *AlertResult {
|
|
// e.log.Debug("Evaluating Alerting Rule", "seriesCount", len(series), "ruleName", rule.Name)
|
|
//
|
|
// triggeredAlert := make([]*TriggeredAlert, 0)
|
|
//
|
|
// for _, serie := range series {
|
|
// e.log.Debug("Evaluating series", "series", serie.Name)
|
|
// transformedValue, _ := rule.Transformer.Transform(serie)
|
|
//
|
|
// critResult := evalCondition(rule.Critical, transformedValue)
|
|
// condition2 := fmt.Sprintf("%v %s %v ", transformedValue, rule.Critical.Operator, rule.Critical.Value)
|
|
// e.log.Debug("Alert execution Crit", "name", serie.Name, "condition", condition2, "result", critResult)
|
|
// if critResult {
|
|
// triggeredAlert = append(triggeredAlert, &TriggeredAlert{
|
|
// State: alertstates.Critical,
|
|
// Value: transformedValue,
|
|
// Metric: serie.Name,
|
|
// })
|
|
// continue
|
|
// }
|
|
//
|
|
// warnResult := evalCondition(rule.Warning, transformedValue)
|
|
// condition := fmt.Sprintf("%v %s %v ", transformedValue, rule.Warning.Operator, rule.Warning.Value)
|
|
// e.log.Debug("Alert execution Warn", "name", serie.Name, "condition", condition, "result", warnResult)
|
|
// if warnResult {
|
|
// triggeredAlert = append(triggeredAlert, &TriggeredAlert{
|
|
// State: alertstates.Warn,
|
|
// Value: transformedValue,
|
|
// Metric: serie.Name,
|
|
// })
|
|
// }
|
|
// }
|
|
//
|
|
// executionState := alertstates.Ok
|
|
// for _, raised := range triggeredAlert {
|
|
// if raised.State == alertstates.Critical {
|
|
// executionState = alertstates.Critical
|
|
// }
|
|
//
|
|
// if executionState != alertstates.Critical && raised.State == alertstates.Warn {
|
|
// executionState = alertstates.Warn
|
|
// }
|
|
// }
|
|
//
|
|
// return &AlertResult{State: executionState, TriggeredAlerts: triggeredAlert}
|
|
// }
|