diff --git a/pkg/apis/monitor/alert.go b/pkg/apis/monitor/alert.go index 655122848b..7122fa2e1e 100644 --- a/pkg/apis/monitor/alert.go +++ b/pkg/apis/monitor/alert.go @@ -165,12 +165,14 @@ type ResultLogEntry struct { // EvalMatch represents the series violating the threshold. type EvalMatch struct { - Condition string `json:"condition"` - Value *float64 `json:"value"` - ValueStr string `json:"value_str"` - Metric string `json:"metric"` - Tags map[string]string `json:"tags"` - Unit string `json:"unit"` + Condition string `json:"condition"` + Value *float64 `json:"value"` + ValueStr string `json:"value_str"` + Metric string `json:"metric"` + MeasurementDesc string `json:"measurement_desc"` + FieldDesc string `json:"field_desc"` + Tags map[string]string `json:"tags"` + Unit string `json:"unit"` } type AlertTestRunOutput struct { diff --git a/pkg/apis/monitor/commalert.go b/pkg/apis/monitor/commalert.go index d9fba02cbc..95bde1512e 100644 --- a/pkg/apis/monitor/commalert.go +++ b/pkg/apis/monitor/commalert.go @@ -21,6 +21,8 @@ const ( //metirc fields 之间的运算 CommonAlertFieldOpt_Division = "/" + + DEFAULT_SEND_NOTIFY_CHANNEL = "users" ) var CommonAlertLevels = []string{"normal", "important", "fatal"} diff --git a/pkg/monitor/alerting/conditions/query.go b/pkg/monitor/alerting/conditions/query.go index 0497898d7d..0a22a26226 100644 --- a/pkg/monitor/alerting/conditions/query.go +++ b/pkg/monitor/alerting/conditions/query.go @@ -143,13 +143,12 @@ func (c *QueryCondition) Eval(context *alerting.EvalContext) (*alerting.Conditio //the relation metas with series is 1 to more meta = &metas[0] } - if evalMatch { - evalMatch, err := c.NewEvalMatch(context, *series, meta, reducedValue) - if err != nil { - return nil, errors.Wrap(err, "NewEvalMatch error") - } - matches = append(matches, evalMatch) + + match, err := c.NewEvalMatch(context, *series, meta, reducedValue) + if err != nil { + return nil, errors.Wrap(err, "NewEvalMatch error") } + matches = append(matches, match) } // handle no series special case @@ -181,8 +180,7 @@ func (c *QueryCondition) Eval(context *alerting.EvalContext) (*alerting.Conditio } func (c *QueryCondition) NewEvalMatch(context *alerting.EvalContext, series tsdb.TimeSeries, - meta *tsdb.QueryResultMeta, value *float64) (*monitor.EvalMatch, - error) { + meta *tsdb.QueryResultMeta, value *float64) (*monitor.EvalMatch, error) { evalMatch := new(monitor.EvalMatch) alert, err := models.CommonAlertManager.GetAlert(context.Rule.Id) if err != nil { @@ -208,6 +206,8 @@ func (c *QueryCondition) NewEvalMatch(context *alerting.EvalContext, series tsdb evalMatch.Unit = alertDetails.FieldDescription.Unit evalMatch.Value = value evalMatch.ValueStr = c.RationalizeValueFromUnit(*value, alertDetails.FieldDescription.Unit) + evalMatch.MeasurementDesc = alertDetails.MeasurementDisplayName + evalMatch.FieldDesc = alertDetails.FieldDescription.DisplayName return evalMatch, nil } diff --git a/pkg/monitor/alerting/notifiers/onecloud.go b/pkg/monitor/alerting/notifiers/onecloud.go index d645bb1abb..7afe80d57b 100644 --- a/pkg/monitor/alerting/notifiers/onecloud.go +++ b/pkg/monitor/alerting/notifiers/onecloud.go @@ -115,10 +115,6 @@ func GetNotifyTemplateConfig(ctx *alerting.EvalContext) monitor.NotificationTemp // Notify sends the alert notification. func (oc *OneCloudNotifier) Notify(ctx *alerting.EvalContext, _ jsonutils.JSONObject) error { - //onecloud 默认向webconsole发送消息 - //if err := WebConsoleNotify(ctx, oc.Setting.UserIds); err != nil { - // log.Errorf("failed to send webconsole %s: %v", oc.GetNotifierId(), err) - //} log.Infof("Sending alert notification %s to onecloud", ctx.GetRuleTitle()) config := GetNotifyTemplateConfig(ctx) contentConfig := oc.buildContent(config) @@ -142,35 +138,67 @@ func (oc *OneCloudNotifier) Notify(ctx *alerting.EvalContext, _ jsonutils.JSONOb Priority: notify.TNotifyPriority(config.Priority), Msg: content, } - //系统报警UserIds 为空 - if len(oc.Setting.UserIds) == 0 { - notifyclient.SystemNotify(notify.TNotifyPriority(msg.Priority), msg.Topic, jsonutils.NewString(content)) - return nil - } - return notify.Notifications.Send(oc.session, msg) + + factory := new(sendBodyFactory) + sendImp := factory.newSendnotify(oc, msg) + + return sendImp.send() } func (oc *OneCloudNotifier) buildContent(config monitor.NotificationTemplateConfig) *templates.TemplateConfig { return templates.NewTemplateConfig(config) } -func WebConsoleNotify(ctx *alerting.EvalContext, ids []string) error { - log.Infof("Sending alert notification %s to webconsole", ctx.GetRuleTitle()) - config := GetNotifyTemplateConfig(ctx) - contentConfig := templates.NewTemplateConfig(config) - content, err := contentConfig.GenerateMarkdown() - if err != nil { - return errors.Wrap(err, "build content") - } - - msg := notify.SNotifyMessage{ - Uid: ids, - ContactType: notify.NotifyByWebConsole, - Topic: config.Title, - Priority: notify.TNotifyPriority(config.Priority), - Msg: content, - Broadcast: true, - } - session := auth.GetAdminSession(ctx.Ctx, "", "") - return notify.Notifications.Send(session, msg) +type sendBodyFactory struct { +} + +func (f *sendBodyFactory) newSendnotify(notifier *OneCloudNotifier, message notify.SNotifyMessage) Isendnotify { + def := new(sendnotifyBase) + def.OneCloudNotifier = notifier + def.msg = message + if len(notifier.Setting.UserIds) == 0 { + sys := new(sendSysImpl) + sys.sendnotifyBase = def + return sys + } + switch notifier.Setting.Channel { + case monitor.DEFAULT_SEND_NOTIFY_CHANNEL: + user := new(sendUserImpl) + user.sendnotifyBase = def + return user + default: + return def + } +} + +type Isendnotify interface { + send() error +} + +type sendnotifyBase struct { + *OneCloudNotifier + msg notify.SNotifyMessage +} + +func (s *sendnotifyBase) send() error { + return notify.Notifications.Send(s.session, s.msg) +} + +type sendUserImpl struct { + *sendnotifyBase +} + +func (s *sendUserImpl) send() error { + return notifyclient.NotifyAllWithoutRobot(s.Setting.UserIds, false, notify.TNotifyPriority(s.msg.Priority), s.msg.Topic, + jsonutils.NewString(s.msg.Msg)) +} + +type sendSysImpl struct { + *sendnotifyBase +} + +func (s *sendSysImpl) send() error { + notifyclient.SystemNotify(notify.TNotifyPriority(s.msg.Priority), s.msg.Topic, + jsonutils.NewString(s.msg.Msg)) + return nil } diff --git a/pkg/monitor/models/commonalert.go b/pkg/monitor/models/commonalert.go index 22de46a156..73c84723ef 100644 --- a/pkg/monitor/models/commonalert.go +++ b/pkg/monitor/models/commonalert.go @@ -80,6 +80,11 @@ func (man *SCommonAlertManager) ValidateCreateData( if data.Level == "" { return data, httperrors.NewInputParameterError("level is empty") } + if len(data.Channel) == 0 { + data.Channel = []string{monitor.DEFAULT_SEND_NOTIFY_CHANNEL} + } else { + data.Channel = append(data.Channel, monitor.DEFAULT_SEND_NOTIFY_CHANNEL) + } if !utils.IsInStringArray(data.Level, monitor.CommonAlertLevels) { return data, httperrors.NewInputParameterError("Invalid level format: %s", data.Level) } @@ -594,6 +599,12 @@ func (alert *SCommonAlert) ValidateUpdateData( data.Set("frequency", jsonutils.NewInt(freqSpec)) } } + if channel, _ := data.GetArray("channel"); len(channel) > 0 { + channels := jsonutils.NewArray() + channels.Add(channel...) + channels.Add(jsonutils.NewString(monitor.DEFAULT_SEND_NOTIFY_CHANNEL)) + data.Set("channel", channels) + } if metric_query, _ := data.GetArray("metric_query"); len(metric_query) > 0 { for i, _ := range metric_query { query := new(monitor.CommonAlertQuery) diff --git a/pkg/monitor/models/datasource.go b/pkg/monitor/models/datasource.go index 2f530927c1..8c5f4f05fd 100644 --- a/pkg/monitor/models/datasource.go +++ b/pkg/monitor/models/datasource.go @@ -433,7 +433,6 @@ func (self *SDataSourceManager) getFromAndToFromParam(query jsonutils.JSONObject func (self *SDataSourceManager) getFilterMeasurementsAsyn(from, to string, measurements []monitor.InfluxMeasurement, db influxdb.SInfluxdb, tagFilter string) ([]monitor.InfluxMeasurement, error) { - log.Errorln("start asynchronous task") filterMeasurements := make([]monitor.InfluxMeasurement, 0) queryChan := new(influxdbQueryChan) queryChan.queryRtnChan = make(chan monitor.InfluxMeasurement, len(measurements)) @@ -647,11 +646,7 @@ func (self *SDataSourceManager) filterTagValue(measurement monitor.InfluxMeasure close(tagValChan2.rtnChan) return nil }) - err := tagValGroup2.Wait() - if err == nil { - log.Errorln("filterTagValue end ") - } - return err + return tagValGroup2.Wait() } func tagValUnion(measurement *monitor.InfluxMeasurement, rtn map[string][]string) { @@ -751,7 +746,6 @@ func getAttributesOnMeasurement(database, tp string, output *monitor.InfluxMeasu if err != nil { return errors.Wrap(err, "SHOW MEASUREMENTS") } - log.Errorf("SHOW %s KEYS ON %s FROM %s", tp, database, output.Measurement) if len(dbRtn) == 0 || len(dbRtn[0]) == 0 { return nil } @@ -827,7 +821,6 @@ func (self *SDataSourceManager) getFilterMeasurementTagValue(tagValueChan *influ } buffer.WriteString(fmt.Sprintf(` GROUP BY %q`, tagKey)) rtn, err := db.Query(buffer.String()) - log.Errorf("sql:", buffer.String()) if err != nil { return errors.Wrap(err, "getFilterMeasurementTagValue query error") } diff --git a/pkg/monitor/models/metric.go b/pkg/monitor/models/metric.go index f6e54e5cf1..fb05a83e8a 100644 --- a/pkg/monitor/models/metric.go +++ b/pkg/monitor/models/metric.go @@ -462,9 +462,7 @@ func (manager *SMetricMeasurementManager) initMetrics(ctx context.Context, metri func (manager *SMetricMeasurementManager) initMeasurementAndFieldInfo(createInput monitor.MetricCreateInput) error { userCred := auth.AdminCredential() - listInput := new(monitor.MetricListInput) - listInput.Measurement.Names = []string{createInput.Measurement.Name} - measurements, err := manager.getMeasurementByName(userCred, *listInput) + measurements, err := manager.getMeasurementByName(createInput.Measurement.Name) if err != nil { return errors.Wrap(err, "join query get measurement error") } @@ -486,10 +484,12 @@ func (manager *SMetricMeasurementManager) initMeasurementAndFieldInfo(createInpu return measurements[0].insertOrUpdateMetric(userCred, createInput, updateFields) } -func (manager *SMetricMeasurementManager) getMeasurementByName(userCred mcclient.TokenCredential, - listInput monitor.MetricListInput) ([]SMetricMeasurement, error) { +func (manager *SMetricMeasurementManager) getMeasurementByName(names ...string) ([]SMetricMeasurement, error) { + userCred := auth.AdminCredential() + listInput := new(monitor.MetricListInput) + listInput.Measurement.Names = names query, err := MetricMeasurementManager.ListItemFilter(context.Background(), MetricMeasurementManager.Query(), userCred, - listInput) + *listInput) if err != nil { return nil, err } diff --git a/pkg/monitor/models/unifiedmonitor.go b/pkg/monitor/models/unifiedmonitor.go index 102dcd082d..30b75fc25a 100644 --- a/pkg/monitor/models/unifiedmonitor.go +++ b/pkg/monitor/models/unifiedmonitor.go @@ -13,7 +13,6 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" - "yunion.io/x/onecloud/pkg/mcclient/auth" mq "yunion.io/x/onecloud/pkg/monitor/metricquery" "yunion.io/x/onecloud/pkg/monitor/tsdb" "yunion.io/x/onecloud/pkg/monitor/validators" @@ -338,10 +337,7 @@ func setSerieRowName(series *tsdb.TimeSeriesSlice, groupTag []string) { } measurement := strings.Split(serie.Name, ".")[0] //sep measurement set RowName by spe param - userCred := auth.AdminCredential() - listInput := new(monitor.MetricListInput) - listInput.Measurement.Names = []string{measurement} - measurements, _ := MetricMeasurementManager.getMeasurementByName(userCred, *listInput) + measurements, _ := MetricMeasurementManager.getMeasurementByName(measurement) if len(measurements) != 0 { if key, ok := monitor.MEASUREMENT_TAG_KEYWORD[measurements[0].ResType]; ok { serie.RawName = fmt.Sprintf("%d: %s", index, serie.Tags[key])