Merge pull request #9138 from zhaoxiangchun/bugfix/zxc-suggest-timefromj-master

fix(monitor): modify influxdbSuggestDriver query err
This commit is contained in:
Zexi Li
2020-12-03 14:41:51 +08:00
committed by GitHub
9 changed files with 168 additions and 48 deletions
+8 -7
View File
@@ -50,13 +50,14 @@ type SuggestSysAlertCreateInput struct {
type SuggestSysAlertDetails struct {
apis.VirtualResourceDetails
compute.CloudregionResourceInfo
RuleName string `json:"rule_name"`
ShowName string `json:"show_name"`
ResType string `json:"res_type"`
Suggest string `json:"suggest"`
Brand string `json:"brand"`
Account string `json:"account"`
ResName string `json:"res_name"`
RuleName string `json:"rule_name"`
ShowName string `json:"show_name"`
ResType string `json:"res_type"`
Suggest string `json:"suggest"`
Brand string `json:"brand"`
Account string `json:"account"`
ResName string `json:"res_name"`
CommonAlertMetricDetails []*CommonAlertMetricDetails `json:"common_alert_metric_details"`
}
type SuggestSysAlertUpdateInput struct {
+5
View File
@@ -23,6 +23,11 @@ import (
const (
METRIC_TAG = "TAG"
METRIC_FIELD = "FIELD"
METRIC_VM_ID = "vm_id"
METRIC_OSS_ID = "oss_id"
METRIC_RDS_ID = "rds_id"
METRIC_REDIS_ID = "redis_id"
)
var PROPERTY_TYPE = []string{"databases", "measurements", "metric-measurement"}
+2
View File
@@ -274,4 +274,6 @@ const (
ACT_NETWORK_REMOVE_VPC_FAILED = "network_remove_vpc_failed"
ACT_NETWORK_MODIFY_ROUTE = "network_modify_route"
ACT_NETWORK_MODIFY_ROUTE_FAILED = "network_modify_route_failed"
ACT_UPDATE_RULE = "update_config"
)
@@ -0,0 +1,88 @@
package conditions
import (
"fmt"
"yunion.io/x/onecloud/pkg/apis/monitor"
"yunion.io/x/onecloud/pkg/monitor/alerting"
"yunion.io/x/onecloud/pkg/monitor/tsdb"
)
func init() {
alerting.RegisterCondition("suggest_query", func(model *monitor.AlertCondition, index int) (alerting.Condition,
error) {
return newSuggestQueryCondition(model, index)
})
}
type SuggestQueryCondition struct {
*QueryCondition
}
func newSuggestQueryCondition(model *monitor.AlertCondition, index int) (*SuggestQueryCondition, error) {
queryCondition, err := newQueryCondition(model, index)
if err != nil {
return nil, err
}
condition := new(SuggestQueryCondition)
condition.QueryCondition = queryCondition
return condition, nil
}
func (c *SuggestQueryCondition) Eval(context *alerting.EvalContext) (*alerting.ConditionResult, error) {
timeRange := tsdb.NewTimeRange(c.Query.From, c.Query.To)
ret, err := c.executeQuery(context, timeRange)
if err != nil {
return nil, err
}
seriesList := ret.series
emptySeriesCount := 0
evalMatchCount := 0
var matches []*monitor.EvalMatch
for _, series := range seriesList {
reducedValue, _ := c.Reducer.Reduce(series)
evalMatch := c.Evaluator.Eval(reducedValue)
if reducedValue == nil {
emptySeriesCount++
}
if context.IsTestRun {
context.Logs = append(context.Logs, &monitor.ResultLogEntry{
Message: fmt.Sprintf("Condition[%d]: Eval: %v, Metric: %s, Value: %v", c.Index, evalMatch, series.Name, reducedValue),
})
}
if evalMatch {
evalMatchCount++
}
if evalMatch {
matches = append(matches, &monitor.EvalMatch{
Metric: series.Name,
Value: reducedValue,
Tags: series.Tags,
})
}
}
// handle no series special case
if len(seriesList) == 0 {
// eval condition for null value
evalMatch := c.Evaluator.Eval(nil)
if context.IsTestRun {
context.Logs = append(context.Logs, &monitor.ResultLogEntry{
Message: fmt.Sprintf("Condition: Eval: %v, Query returned No Series (reduced to null/no value)", evalMatch),
})
}
if evalMatch {
evalMatchCount++
matches = append(matches, &monitor.EvalMatch{
Metric: "NoData",
Value: nil,
})
}
}
return &alerting.ConditionResult{
Firing: evalMatchCount > 0,
NoDataFound: emptySeriesCount == len(seriesList),
Operator: c.Operator,
EvalMatches: matches,
}, nil
}
+1 -1
View File
@@ -954,7 +954,6 @@ func (alert *SCommonAlert) PerformConfig(ctx context.Context, userCred mcclient.
period, _ := data.GetString("period")
comparator, _ := data.GetString("comparator")
threshold, _ := data.GetString("threshold")
fmt.Println(threshold)
if len(period) != 0 {
if _, err := time.ParseDuration(period); err != nil {
return data, httperrors.NewInputParameterError("Invalid period format: %s", period)
@@ -989,6 +988,7 @@ func (alert *SCommonAlert) PerformConfig(ctx context.Context, userCred mcclient.
alert.Settings = jsonutils.Marshal(setting)
return nil
})
PerformConfigLog(alert, userCred)
return jsonutils.Marshal(alert), err
}
+15 -16
View File
@@ -25,7 +25,6 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/tristate"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis/monitor"
@@ -37,6 +36,7 @@ import (
merrors "yunion.io/x/onecloud/pkg/monitor/errors"
"yunion.io/x/onecloud/pkg/monitor/registry"
"yunion.io/x/onecloud/pkg/util/influxdb"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
@@ -328,14 +328,11 @@ func (self *SSuggestSysRule) AllowPerformEnable(ctx context.Context, userCred mc
}
func (self *SSuggestSysRule) PerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !self.Enabled.Bool() {
db.Update(self, func() error {
self.Enabled = tristate.True
return nil
})
db.OpsLog.LogEvent(self, db.ACT_ENABLE, "", userCred)
self.updateCronjob()
err := db.EnabledPerformEnable(self, ctx, userCred, true)
if err != nil {
return nil, errors.Wrap(err, "EnabledPerformEnable")
}
self.updateCronjob()
return nil, nil
}
@@ -344,14 +341,11 @@ func (self *SSuggestSysRule) AllowPerformDisable(ctx context.Context, userCred m
}
func (self *SSuggestSysRule) PerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if self.Enabled.IsTrue() {
db.Update(self, func() error {
self.Enabled = tristate.False
return nil
})
db.OpsLog.LogEvent(self, db.ACT_DISABLE, "", userCred)
self.updateCronjob()
err := db.EnabledPerformEnable(self, ctx, userCred, false)
if err != nil {
return nil, errors.Wrap(err, "EnabledPerformEnable")
}
self.updateCronjob()
return nil, nil
}
@@ -386,11 +380,16 @@ func (self *SSuggestSysRule) PerformConfig(ctx context.Context, userCred mcclien
}
return nil
})
db.OpsLog.LogEvent(self, "modifyconfig", "", userCred)
PerformConfigLog(self, userCred)
self.updateCronjob()
return nil, nil
}
func PerformConfigLog(model db.IModel, userCred mcclient.TokenCredential) {
db.OpsLog.LogEvent(model, db.ACT_UPDATE_RULE, "", userCred)
logclient.AddSimpleActionLog(model, logclient.ACT_UPDATE_RULE, nil, userCred, true)
}
func (self *SSuggestSysRuleManager) AllowGetPropertyRuleType(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return true
}
@@ -91,6 +91,7 @@ func (drv *InfluxdbBaseDriver) GetLatestAlerts(rule *models.SSuggestSysRule, ins
return ret, errors.Wrap(err, "rule getScaleEvalResult happen error")
}
if firing {
log.Errorf("evalMatchMapLen:%d", len(evalMatchMap))
serverArr, err := drv.getResourcesByEvalMatchsMap(evalMatchMap, instance)
if err != nil {
return ret, errors.Wrap(err, "rule getResource error")
@@ -106,7 +107,7 @@ func (drv *InfluxdbBaseDriver) getScaleEvalResult(scales []monitor.Scale) (bool,
scaleEvalMatchs := make(map[string][]*monitor.EvalMatch, 0)
for index, scale := range scales {
condition := monitor.AlertCondition{
Type: "query",
Type: "suggest_query",
Query: drv.newAlertQuery(scale),
Evaluator: monitor.Condition{Type: getQueryEvalType(scale), Params: []float64{scale.Threshold}},
Reducer: monitor.Condition{Type: "avg"},
@@ -119,7 +120,7 @@ func (drv *InfluxdbBaseDriver) getScaleEvalResult(scales []monitor.Scale) (bool,
jsonutils.Marshal(condition))
}
duration, _ := time.ParseDuration(condition.Query.From)
queryCon := queryCondition.(*conditions.QueryCondition)
queryCon := queryCondition.(*conditions.SuggestQueryCondition)
queryCon.Reducer = conditions.NewSuggestRuleReducer(queryCon.Reducer.GetType(), duration)
//evalContext := alerting.NewEvalContext(context.Background(), auth.AdminCredential(), nil)
evalContext := alerting.EvalContext{
@@ -175,8 +176,9 @@ func (drv *InfluxdbBaseDriver) getResourcesByEvalMatchsMap(evalMatchsMap map[str
}
resArr := jsonutils.NewArray()
for _, evalMatch := range maxEvalMatch {
res, mappingId, mappingVal := drv.getResourceFromEvalMatch(evalMatch)
if mappingId == "" {
res, mappingId, err := drv.getResourceFromEvalMatch(evalMatch)
if err != nil {
log.Errorln(err)
continue
}
suggestSysAlert, err := getSuggestSysAlertFromJson(res, drv)
@@ -185,28 +187,44 @@ func (drv *InfluxdbBaseDriver) getResourcesByEvalMatchsMap(evalMatchsMap map[str
}
suggestSysAlert.Action = string(monitor.SCALE_DOWN_DRIVER_ACTION)
suggestSysAlert.MonitorConfig = jsonutils.Marshal(instance)
suggestSysAlert.Problem = describeEvalResultTojson(evalMatchsMap, mappingId, mappingVal)
suggestSysAlert.Problem = drv.describeEvalResultTojson(evalMatchsMap, mappingId)
resArr.Add(jsonutils.Marshal(suggestSysAlert))
}
return resArr.GetArray()
}
func (drv *InfluxdbBaseDriver) getResourceFromEvalMatch(evalMatch *monitor.EvalMatch) (jsonutils.JSONObject, string, string) {
idTag := getMetricIdTag(evalMatch.Tags)
func (drv *InfluxdbBaseDriver) getResourceFromEvalMatch(evalMatch *monitor.EvalMatch) (jsonutils.JSONObject, string, error) {
var server jsonutils.JSONObject
mappingId := ""
mappingVal := ""
for id, val := range idTag {
serverobj, err := drv.getResourceById(id)
if err != nil {
continue
}
server = serverobj
mappingId = id
mappingVal = val
break
id, err := drv.getMetricId(evalMatch)
if err != nil {
return server, mappingId, errors.Wrap(err, "InfluxdbBaseDriver getMetricId err")
}
return server, mappingId, mappingVal
serverobj, err := drv.getResourceById(id)
if err != nil {
return server, mappingId, errors.Wrapf(err, "InfluxdbBaseDriver getResourceById:%s err", id)
}
server = serverobj
mappingId = id
return server, mappingId, nil
}
func (drv *InfluxdbBaseDriver) getMetricId(evalMatch *monitor.EvalMatch) (string, error) {
var id string
switch drv.GetResourceType() {
case monitor.SCALE_MONTITOR_RES_TYPE:
id = evalMatch.Tags[monitor.METRIC_VM_ID]
case monitor.REDIS_UNREASONABLE_MONITOR_RES_TYPE:
id = evalMatch.Tags[monitor.METRIC_REDIS_ID]
case monitor.RDS_UNREASONABLE_MONITOR_RES_TYPE:
id = evalMatch.Tags[monitor.METRIC_RDS_ID]
case monitor.OSS_UNREASONABLE_MONITOR_RES_TYPE:
id = evalMatch.Tags[monitor.METRIC_OSS_ID]
}
if len(id) == 0 {
return id, fmt.Errorf("no find resourceId by the driver type:%s", string(drv.GetResourceType()))
}
return id, nil
}
func (drv *InfluxdbBaseDriver) getResourceById(id string) (jsonutils.JSONObject, error) {
@@ -223,15 +241,16 @@ func (drv *InfluxdbBaseDriver) getResourceById(id string) (jsonutils.JSONObject,
return nil, fmt.Errorf("unsupporttd to get resource by the driver type:%s", string(drv.GetResourceType()))
}
func describeEvalResultTojson(evalMatchsMap map[string][]*monitor.EvalMatch, mappingId, mappingVal string) jsonutils.JSONObject {
func (drv *InfluxdbBaseDriver) describeEvalResultTojson(evalMatchsMap map[string][]*monitor.EvalMatch,
mappingId string) jsonutils.JSONObject {
problem := jsonutils.NewDict()
loopEvalMap:
for _, evalMatchs := range evalMatchsMap {
for _, evalMatch := range evalMatchs {
idTag := getMetricIdTag(evalMatch.Tags)
if val, ok := idTag[mappingId]; ok {
if val == mappingVal {
problem.Add(jsonutils.NewFloat64(*evalMatch.Value), evalMatch.Metric)
}
metricId, _ := drv.getMetricId(evalMatch)
if metricId == mappingId {
problem.Add(jsonutils.NewFloat64(*evalMatch.Value), evalMatch.Metric)
break loopEvalMap
}
}
}
+2
View File
@@ -192,4 +192,6 @@ const (
ACT_NETWORK_ADD_VPC = "network_add_vpc"
ACT_NETWORK_REMOVE_VPC = "network_remove_vpc"
ACT_NETWORK_MODIFY_ROUTE = "network_modify_route"
ACT_UPDATE_RULE = "update_config"
)
+4
View File
@@ -653,4 +653,8 @@ func init() {
EN("Modify Network Route").
CN("修改网络路由策略"),
)
t.Set(ACT_UPDATE_RULE, i18n.NewTableEntry().
EN("Update RuleConfig").
CN("调整规则配置"),
)
}