diff --git a/build/monitor/root/opt/yunion/share/notify_templates/alerter/content@cn/DEFAULT b/build/monitor/root/opt/yunion/share/notify_templates/alerter/content@cn/DEFAULT index df6fb30b61..f1f6409560 100644 --- a/build/monitor/root/opt/yunion/share/notify_templates/alerter/content@cn/DEFAULT +++ b/build/monitor/root/opt/yunion/share/notify_templates/alerter/content@cn/DEFAULT @@ -1,18 +1,9 @@ -## {{.title}} -- 时间: {{.start_time}} -- 级别: {{.level}} -- 详情地址: {{.web_url}}/commonalerts +{{.title}} +策略名称: {{.name}} +触发时间: {{.start_time}} +报警级别: {{.level}} +触发条件: {{.description}} +资源数量:{{len .matches}} +资源名称:{{.resource_name}} -{{ range .matches}} -- 指标: {{.metric}} -- 触发值: {{html .value_str}} - -### 触发条件: -- {{html $.description}} - -### 标签 - > 名称: {{ index .tags "name" }} - > ip: {{ index .tags "ip" }} - > 平台: {{ index .tags "brand" }} ------- -{{- end}} \ No newline at end of file +详情地址: {{.web_url}}/commonalerts \ No newline at end of file diff --git a/build/monitor/root/opt/yunion/share/notify_templates/alerter/content@en/DEFAULT b/build/monitor/root/opt/yunion/share/notify_templates/alerter/content@en/DEFAULT index 16e338b277..0ee07a2ae4 100644 --- a/build/monitor/root/opt/yunion/share/notify_templates/alerter/content@en/DEFAULT +++ b/build/monitor/root/opt/yunion/share/notify_templates/alerter/content@en/DEFAULT @@ -1,18 +1,9 @@ -## {{.title}} -- Time: {{.start_time}} -- Level: {{.level}} -- WebUrl: {{.web_url}}/commonalerts +{{.title}} +AlertName: {{.name}} +Time: {{.start_time}} +Level: {{.level}} +TriggerCondition: {{html .description}} +ResourceCount: {{len .matches}} +ResourceName: {{.resource_name}} -{{ range .matches}} -- Metric: {{.metric}} -- Trigger value: {{html .value_str}} - -### Trigger condition: -- {{html $.description }} - -### Label - > Name: {{ index .tags "name" }} - > IP: {{ index .tags "ip" }} - > Brand: {{ index .tags "brand" }} ------- -{{- end}} +WebUrl: {{.web_url}}/commonalerts diff --git a/pkg/apis/monitor/template.go b/pkg/apis/monitor/template.go index 15cc09b7f7..5900f33af2 100644 --- a/pkg/apis/monitor/template.go +++ b/pkg/apis/monitor/template.go @@ -19,9 +19,10 @@ type NotificationTemplateCreateInput struct { } type NotificationTemplateConfig struct { - Title string `json:"title"` - Name string `json:"name"` - Matches []EvalMatch `json:"matches"` + Title string `json:"title"` + Name string `json:"name"` + ResourceName string `json:"resource_name"` + Matches []EvalMatch `json:"matches"` // PrevAlertState AlertStateType `json:"prev_alert_state"` // State AlertStateType `json:"state"` NoDataFound bool `json:"no_data"` diff --git a/pkg/apis/monitor/unifiedmonitor_const.go b/pkg/apis/monitor/unifiedmonitor_const.go index f1aae7062a..01570039bd 100644 --- a/pkg/apis/monitor/unifiedmonitor_const.go +++ b/pkg/apis/monitor/unifiedmonitor_const.go @@ -51,4 +51,5 @@ type MetricInputQuery struct { ProjectId string `json:"project_id"` MetricQuery []*AlertQuery `json:"metric_query"` Signature string `json:"signature"` + ShowMeta bool `json:"show_meta"` } diff --git a/pkg/monitor/alerting/eval_context.go b/pkg/monitor/alerting/eval_context.go index a0385af2e6..83472ade9a 100644 --- a/pkg/monitor/alerting/eval_context.go +++ b/pkg/monitor/alerting/eval_context.go @@ -17,6 +17,7 @@ package alerting import ( "context" "fmt" + "strings" "time" "yunion.io/x/jsonutils" @@ -186,15 +187,16 @@ func (c *EvalContext) GetNotificationTemplateConfig() monitor.NotificationTempla desc += "Error: " + c.Error.Error() } return monitor.NotificationTemplateConfig{ - Title: c.GetNotificationTitle(), - Name: c.Rule.Name, - Matches: c.GetEvalMatches(), - StartTime: c.StartTime.Format("2006-01-02 15:04:05"), - EndTime: c.EndTime.Format("2006-01-02 15:04:05"), - Description: desc, - Level: c.Rule.Level, - NoDataFound: c.NoDataFound, - WebUrl: c.GetCallbackURLPrefix(), + Title: c.GetNotificationTitle(), + Name: c.Rule.Name, + ResourceName: c.GetResourceNameOfMathes(), + Matches: c.GetEvalMatches(), + StartTime: c.StartTime.Format("2006-01-02 15:04:05"), + EndTime: c.EndTime.Format("2006-01-02 15:04:05"), + Description: desc, + Level: c.Rule.Level, + NoDataFound: c.NoDataFound, + WebUrl: c.GetCallbackURLPrefix(), } } @@ -211,3 +213,17 @@ func (c *EvalContext) GetEvalMatches() []monitor.EvalMatch { } return ret } + +func (c *EvalContext) GetResourceNameOfMathes() string { + names := strings.Builder{} + matches := c.GetEvalMatches() + for i, match := range matches { + if name, ok := match.Tags["name"]; ok { + names.WriteString(name) + if i < len(matches)-1 { + names.WriteString("、") + } + } + } + return names.String() +} diff --git a/pkg/monitor/alerting/notifiers/onecloud.go b/pkg/monitor/alerting/notifiers/onecloud.go index 50bf2069be..7e84b83198 100644 --- a/pkg/monitor/alerting/notifiers/onecloud.go +++ b/pkg/monitor/alerting/notifiers/onecloud.go @@ -153,15 +153,15 @@ func GetNotifyTemplateConfigOfEN(ctx *alerting.EvalContext) monitor.Notification // Notify sends the alert notification. func (oc *OneCloudNotifier) Notify(ctx *alerting.EvalContext, _ jsonutils.JSONObject) error { log.Infof("Sending alert notification %s to onecloud", ctx.GetRuleTitle()) + oc.Ctx = i18n.WithLangTag(oc.Ctx, language.Chinese) var config monitor.NotificationTemplateConfig - lang := i18n.Lang(ctx.Ctx) + lang := i18n.Lang(oc.Ctx) switch lang { case language.English: config = GetNotifyTemplateConfigOfEN(ctx) default: config = GetNotifyTemplateConfig(ctx) } - oc.filterMatchTagsForConfig(&config) contentConfig := oc.buildContent(config) @@ -197,9 +197,7 @@ var ( ) func (oc *OneCloudNotifier) filterMatchTagsForConfig(config *monitor.NotificationTemplateConfig) { - ctx := context.Background() - ctx = i18n.WithLangTag(ctx, language.Chinese) - sCompanyInfo, err := models.GetCompanyInfo(ctx) + sCompanyInfo, err := models.GetCompanyInfo(oc.Ctx) if err != nil { log.Errorf("GetCompanyInfo error:%#v", err) return @@ -265,7 +263,7 @@ type sendUserImpl struct { } func (s *sendUserImpl) send() error { - return notifyclient.NotifyAllWithoutRobot(s.Setting.UserIds, false, notify.TNotifyPriority(s.msg.Priority), + return notifyclient.NotifyAllWithoutRobotWithCtx(s.Ctx, s.Setting.UserIds, false, notify.TNotifyPriority(s.msg.Priority), "DEFAULT", jsonutils.Marshal(&s.config)) } @@ -274,7 +272,7 @@ type sendSysImpl struct { } func (s *sendSysImpl) send() error { - notifyclient.SystemNotify(notify.TNotifyPriority(s.msg.Priority), "DEFAULT", + notifyclient.SystemNotifyWithCtx(s.Ctx, notify.TNotifyPriority(s.msg.Priority), "DEFAULT", jsonutils.Marshal(&s.config)) return nil } diff --git a/pkg/monitor/alertresourcedrivers/node.go b/pkg/monitor/alertresourcedrivers/node.go index 80f45df8d1..ef5caec869 100644 --- a/pkg/monitor/alertresourcedrivers/node.go +++ b/pkg/monitor/alertresourcedrivers/node.go @@ -47,7 +47,7 @@ func (drvF *nodeDriverF) IsEvalMatched(input monitor.EvalMatch) bool { if !hasHostType { return false } - if hostType != hostconsts.TELEGRAF_TAG_ONECLOUD_HOST_TYPE_HOST || + if hostType != hostconsts.TELEGRAF_TAG_ONECLOUD_HOST_TYPE_HOST && hostType != hostconsts.TELEGRAF_TAG_ONECLOUD_HOST_TYPE_CONTROLLER { return false } diff --git a/pkg/monitor/models/alertresource.go b/pkg/monitor/models/alertresource.go index 48e5ef110c..3073ccb543 100644 --- a/pkg/monitor/models/alertresource.go +++ b/pkg/monitor/models/alertresource.go @@ -109,15 +109,49 @@ func (m *SAlertResourceManager) ReconcileFromRecord(ctx context.Context, userCre if err != nil { return errors.Wrapf(err, "Get record %s eval data", record.GetId()) } + oldResources, err := m.getResourceFromAlertId(record.AlertId) + if err != nil { + return errors.Wrap(err, "ReconcileFromRecord getResourceFromAlertId error") + } errs := make([]error, 0) for _, match := range matches { if err := m.reconcileFromRecordMatch(ctx, userCred, ownerId, record, match); err != nil { errs = append(errs, err) } } + if len(errs) == 0 { + delErrs := m.deleteOldResource(ctx, userCred, record, oldResources) + if len(delErrs) != 0 { + errs = append(errs, delErrs...) + } + } return errors.NewAggregate(errs) } +func (m *SAlertResourceManager) deleteOldResource(ctx context.Context, userCred mcclient.TokenCredential, + record *SAlertRecord, oldResources []SAlertResource) (errs []error) { + matches, _ := record.GetEvalData() + needDelResources := make([]SAlertResource, 0) +LoopRes: + for _, oldResource := range oldResources { + for _, match := range matches { + resourceD, _ := GetAlertResourceDriver(match) + if oldResource.Name == resourceD.GetUniqCond().Name { + continue LoopRes + } + } + needDelResources = append(needDelResources, oldResource) + } + for i, _ := range needDelResources { + if err := needDelResources[i].DetachAlert(ctx, userCred, record.AlertId); err != nil { + errs = append(errs, errors.Wrapf(err, "deleteOldResource remove resource %s alert %s", + needDelResources[i].GetName(), + record.AlertId)) + } + } + return +} + type AlertResourceUniqCond struct { Type monitor.AlertResourceType Name string @@ -142,6 +176,17 @@ func (m *SAlertResourceManager) getResourceFromMatch(ctx context.Context, userCr return &objs[0], nil } +func (m *SAlertResourceManager) getResourceFromAlertId(alertId string) ([]SAlertResource, error) { + searchResourceIdQuery := GetAlertResourceAlertManager().Query(GetAlertResourceAlertManager().GetMasterFieldName()) + searchResourceIdQuery = searchResourceIdQuery.Equals(GetAlertResourceAlertManager().GetSlaveFieldName(), alertId) + query := m.Query().In("id", searchResourceIdQuery.SubQuery()) + objs := make([]SAlertResource, 0) + if err := db.FetchModelObjects(m, query, &objs); err != nil { + return nil, errors.Wrapf(err, "getResourceFromAlertId:%s error", alertId) + } + return objs, nil +} + func (m *SAlertResourceManager) reconcileFromRecordMatch(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, record *SAlertRecord, match monitor.EvalMatch) error { drv, err := GetAlertResourceDriver(match) if err != nil { diff --git a/pkg/monitor/models/unifiedmonitor.go b/pkg/monitor/models/unifiedmonitor.go index 747347f040..a78d31167f 100644 --- a/pkg/monitor/models/unifiedmonitor.go +++ b/pkg/monitor/models/unifiedmonitor.go @@ -252,7 +252,9 @@ func doQuery(query monitor.MetricInputQuery) (*mq.Metrics, error) { return nil, err } // drop metas contains raw_query - metrics.Metas = nil + if !query.ShowMeta { + metrics.Metas = nil + } return metrics, nil }