Merge pull request #8920 from zhaoxiangchun/bugfix/zxc-commonalert

fix(monitor): modify notify alertInfo and alertOk detach resource
This commit is contained in:
Zexi Li
2020-11-24 09:33:41 +08:00
committed by GitHub
8 changed files with 81 additions and 46 deletions
@@ -2,7 +2,7 @@
策略名称: {{.name}}
触发时间: {{.start_time}}
报警级别: {{.level}}
触发条件: {{.description}}
触发条件: {{.description | unescaped}}
资源数量:{{len .matches}}
资源名称:{{.resource_name}}
@@ -2,7 +2,7 @@
AlertName: {{.name}}
Time: {{.start_time}}
Level: {{.level}}
TriggerCondition: {{html .description}}
TriggerCondition: {{.description | unescaped}}
ResourceCount: {{len .matches}}
ResourceName: {{.resource_name}}
+2
View File
@@ -34,7 +34,9 @@ type AlertRecordCreateInput struct {
type AlertRecordRule struct {
Metric string `json:"metric"`
Measurement string `json:"measurement"`
MeasurementDesc string `json:"measurement_desc"`
Field string `json:"field"`
FieldDesc string `json:"field_desc"`
// 比较运算符, 比如: >, <, >=, <=
Comparator string `json:"comparator"`
+7 -1
View File
@@ -91,7 +91,9 @@ func getTemplate(ctx context.Context, topic string, contType string, channel npk
if err != nil {
return nil, err
}
tmp, err := template.New(key).Parse(string(cont))
tmp := template.New(key)
tmp.Funcs(template.FuncMap{"unescaped": unescaped})
tmp, err = tmp.Parse(string(cont))
if err != nil {
return nil, err
}
@@ -100,6 +102,10 @@ func getTemplate(ctx context.Context, topic string, contType string, channel npk
return templatesTable[key], nil
}
func unescaped(str string) template.HTML {
return template.HTML(str)
}
func getContent(ctx context.Context, topic string, contType string, channel npk.TNotifyChannel, data jsonutils.JSONObject) (string, error) {
if channel == npk.NotifyByWebhook {
return "", nil
+16 -2
View File
@@ -223,11 +223,25 @@ func (c *QueryCondition) NewEvalMatch(context *alerting.EvalContext, series tsdb
if alertDetails.GetPointStr {
evalMatch.ValueStr = c.jointPointStr(series, evalMatch.ValueStr, valStrArr)
}
evalMatch.MeasurementDesc = alertDetails.MeasurementDisplayName
evalMatch.FieldDesc = alertDetails.FieldDescription.DisplayName
c.newRuleDescription(context, alertDetails)
return evalMatch, nil
}
func (c *QueryCondition) newRuleDescription(context *alerting.EvalContext, alertDetails *monitor.CommonAlertMetricDetails) {
ruleDes := alerting.RuleDescription{
AlertRecordRule: monitor.AlertRecordRule{
Metric: fmt.Sprintf("%s.%s", alertDetails.Measurement, alertDetails.Field),
Measurement: alertDetails.Measurement,
MeasurementDesc: alertDetails.MeasurementDisplayName,
Field: alertDetails.Field,
FieldDesc: alertDetails.FieldDescription.DisplayName,
Comparator: alertDetails.Comparator,
Threshold: c.RationalizeValueFromUnit(alertDetails.Threshold, alertDetails.FieldDescription.Unit, ""),
},
}
context.RuleDescription = &ruleDes
}
func (c *QueryCondition) jointPointStr(series tsdb.TimeSeries, value string, valStrArr []string) string {
str := ""
for i := 0; i < len(valStrArr); i++ {
+5
View File
@@ -42,6 +42,7 @@ type EvalContext struct {
StartTime time.Time
EndTime time.Time
Rule *Rule
RuleDescription *RuleDescription
NoDataFound bool
PrevAlertState monitor.AlertStateType
@@ -50,6 +51,10 @@ type EvalContext struct {
UserCred mcclient.TokenCredential
}
type RuleDescription struct {
monitor.AlertRecordRule
}
// NewEvalContext is the EvalContext constructor.
func NewEvalContext(alertCtx context.Context, userCred mcclient.TokenCredential, rule *Rule) *EvalContext {
return &EvalContext{
+41 -38
View File
@@ -17,7 +17,6 @@ package alerting
import (
"database/sql"
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
@@ -143,32 +142,47 @@ func (n *notificationService) getNeededNotifiers(nIds []string, evalCtx *EvalCon
}
}
if shouldNotify {
var matches []*monitor.EvalMatch
if evalCtx.Firing {
matches = evalCtx.EvalMatches
} else {
matches = evalCtx.AlertOkEvalMatches
}
recordCreateInput := monitor.AlertRecordCreateInput{
StandaloneResourceCreateInput: apis.StandaloneResourceCreateInput{
GenerateName: evalCtx.Rule.Name,
},
AlertId: evalCtx.Rule.Id,
Level: evalCtx.Rule.Level,
State: string(evalCtx.Rule.State),
EvalData: matches,
AlertRule: newAlertRecordRule(evalCtx),
}
createData := recordCreateInput.JSON(recordCreateInput)
record, err := db.DoCreate(models.AlertRecordManager, evalCtx.Ctx, evalCtx.UserCred, jsonutils.NewDict(), createData, evalCtx.UserCred)
if err != nil {
log.Errorf("create alert record err:%v", err)
}
record.PostCreate(evalCtx.Ctx, evalCtx.UserCred, evalCtx.UserCred, nil, createData)
n.createAlertRecordWhenNotify(evalCtx)
}
if !shouldNotify && evalCtx.shouldUpdateAlertState() && evalCtx.NoDataFound {
n.detachAlertResourceWhenNodata(evalCtx)
}
return result, nil
}
func (n *notificationService) createAlertRecordWhenNotify(evalCtx *EvalContext) {
var matches []*monitor.EvalMatch
if evalCtx.Firing {
matches = evalCtx.EvalMatches
} else {
matches = evalCtx.AlertOkEvalMatches
}
recordCreateInput := monitor.AlertRecordCreateInput{
StandaloneResourceCreateInput: apis.StandaloneResourceCreateInput{
GenerateName: evalCtx.Rule.Name,
},
AlertId: evalCtx.Rule.Id,
Level: evalCtx.Rule.Level,
State: string(evalCtx.Rule.State),
EvalData: matches,
AlertRule: newAlertRecordRule(evalCtx),
}
createData := recordCreateInput.JSON(recordCreateInput)
record, err := db.DoCreate(models.AlertRecordManager, evalCtx.Ctx, evalCtx.UserCred, jsonutils.NewDict(), createData, evalCtx.UserCred)
if err != nil {
log.Errorf("create alert record err:%v", err)
}
record.PostCreate(evalCtx.Ctx, evalCtx.UserCred, evalCtx.UserCred, nil, createData)
}
func (n *notificationService) detachAlertResourceWhenNodata(evalCtx *EvalContext) {
errs := models.CommonAlertManager.DetachAlertResourceByAlertId(evalCtx.Ctx, evalCtx.UserCred, evalCtx.Rule.Id)
if len(errs) != 0 {
log.Errorf("detachAlertResourceWhenNodata err:%#v", errors.NewAggregate(errs))
}
}
type NotifierPlugin struct {
Type string
Factory NotifierFactory
@@ -205,25 +219,14 @@ func InitNotifier(config NotificationConfig) (Notifier, error) {
func newAlertRecordRule(evalCtx *EvalContext) monitor.AlertRecordRule {
alertRule := monitor.AlertRecordRule{}
if evalCtx.RuleDescription != nil {
alertRule = evalCtx.RuleDescription.AlertRecordRule
}
if evalCtx.Rule.Frequency < 60 {
alertRule.Period = fmt.Sprintf("%ds", evalCtx.Rule.Frequency)
} else {
alertRule.Period = fmt.Sprintf("%dm", evalCtx.Rule.Frequency/60)
}
ruleStr := evalCtx.Rule.Message
ruleElementArr := strings.Split(ruleStr, " ")
if len(ruleElementArr) == 3 {
alertRule.Metric = ruleElementArr[0]
alertRule.Comparator = ruleElementArr[1]
alertRule.Threshold = ruleElementArr[2]
}
if len(evalCtx.EvalMatches) != 0 {
alertRule.MeasurementDesc = evalCtx.EvalMatches[0].MeasurementDesc
alertRule.FieldDesc = evalCtx.EvalMatches[0].FieldDesc
}
if len(evalCtx.AlertOkEvalMatches) != 0 {
alertRule.MeasurementDesc = evalCtx.AlertOkEvalMatches[0].MeasurementDesc
alertRule.FieldDesc = evalCtx.AlertOkEvalMatches[0].FieldDesc
}
return alertRule
}
+8 -3
View File
@@ -992,15 +992,20 @@ func (alert *SCommonAlert) StartDetachTask(ctx context.Context, userCred mcclien
func (alert *SCommonAlert) DetachAlertResourceOnDisable(ctx context.Context,
userCred mcclient.TokenCredential) (errs []error) {
resources, err := GetAlertResourceManager().getResourceFromAlertId(alert.Id)
return CommonAlertManager.DetachAlertResourceByAlertId(ctx, userCred, alert.Id)
}
func (manager *SCommonAlertManager) DetachAlertResourceByAlertId(ctx context.Context,
userCred mcclient.TokenCredential, alertId string) (errs []error) {
resources, err := GetAlertResourceManager().getResourceFromAlertId(alertId)
if err != nil {
errs = append(errs, errors.Wrap(err, "getResourceFromAlert error"))
return
}
for _, resource := range resources {
err := resource.DetachAlert(ctx, userCred, alert.Id)
err := resource.DetachAlert(ctx, userCred, alertId)
if err != nil {
errs = append(errs, errors.Wrapf(err, "resource:%s DetachAlert:%s err", resource.Id, alert.Id))
errs = append(errs, errors.Wrapf(err, "resource:%s DetachAlert:%s err", resource.Id, alertId))
}
}
return