mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
Merge pull request #7838 from zhaoxiangchun/bugfix/zxc-monitor-alert
commonalert bugfix:
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -21,6 +21,8 @@ const (
|
||||
|
||||
//metirc fields 之间的运算
|
||||
CommonAlertFieldOpt_Division = "/"
|
||||
|
||||
DEFAULT_SEND_NOTIFY_CHANNEL = "users"
|
||||
)
|
||||
|
||||
var CommonAlertLevels = []string{"normal", "important", "fatal"}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user