diff --git a/cmd/climc/shell/monitor/commonalert.go b/cmd/climc/shell/monitor/commonalert.go index 27ff72cebd..0845007a09 100644 --- a/cmd/climc/shell/monitor/commonalert.go +++ b/cmd/climc/shell/monitor/commonalert.go @@ -34,7 +34,7 @@ type CommonAlertTerm struct { Comparator string Threshold float64 Filters []monitorapi.MetricQueryTag - FieldOpt string + FieldOpt monitorapi.CommonAlertFieldOpt Name string ConditionType string From string @@ -94,7 +94,7 @@ func newCommonAlertQuery(tem *CommonAlertTerm) *monitorapi.CommonAlertQuery { Operator: tem.Operator, } if tem.FieldOpt != "" { - commonAlert.FieldOpt = monitorapi.CommonAlertFieldOpt_Division + commonAlert.FieldOpt = monitorapi.CommonAlertFieldOptDivision } if len(tem.ConditionType) != 0 { commonAlert.ConditionType = tem.ConditionType diff --git a/pkg/apis/monitor/alert.go b/pkg/apis/monitor/alert.go index f1364168eb..da288b227a 100644 --- a/pkg/apis/monitor/alert.go +++ b/pkg/apis/monitor/alert.go @@ -238,3 +238,13 @@ func init() { return &AlertSetting{} }) } + +type EvaluatorType string + +const ( + EvaluatorTypeGT EvaluatorType = "gt" + EvaluatorTypeLT EvaluatorType = "lt" + EvaluatorTypeEQ EvaluatorType = "eq" + EvaluatorTypeWithinRange EvaluatorType = "within_range" + EvaluatorTypeOutsideRange EvaluatorType = "outside_range" +) diff --git a/pkg/apis/monitor/alertrecord.go b/pkg/apis/monitor/alertrecord.go index c5a6b12344..353a482886 100644 --- a/pkg/apis/monitor/alertrecord.go +++ b/pkg/apis/monitor/alertrecord.go @@ -77,10 +77,12 @@ type AlertRecordRule struct { // 比较运算符, 比如: >, <, >=, <= Comparator string `json:"comparator"` // 报警阀值 - Threshold string `json:"threshold"` - Period string `json:"period"` - AlertDuration int64 `json:"alert_duration"` - ConditionType string `json:"condition_type"` + Threshold string `json:"threshold"` + ThresholdRange []float64 `json:"threshold_range"` + Unit string `json:"unit"` + Period string `json:"period"` + AlertDuration int64 `json:"alert_duration"` + ConditionType string `json:"condition_type"` // 静默期 SilentPeriod string `json:"silent_period"` Reducer string `json:"reducer"` diff --git a/pkg/apis/monitor/commalert.go b/pkg/apis/monitor/commalert.go index 592927c997..c84b3b084b 100644 --- a/pkg/apis/monitor/commalert.go +++ b/pkg/apis/monitor/commalert.go @@ -34,9 +34,6 @@ const ( CommonAlertDefaultRecipient = "commonalert-default" - //metirc fields 之间的运算 - CommonAlertFieldOpt_Division = "/" - DEFAULT_SEND_NOTIFY_CHANNEL = "users" METRIC_QUERY_TYPE_NO_DATA = "nodata_query" @@ -47,6 +44,13 @@ const ( CommonAlertLevelFatal = "fatal" ) +type CommonAlertFieldOpt string + +const ( + //metirc fields 之间的运算 + CommonAlertFieldOptDivision CommonAlertFieldOpt = "/" +) + var CommonAlertLevels = []string{CommonAlertLevelNormal, CommonAlertLevelImportant, CommonAlertLevelFatal} type CommonAlertCreateBaseInput struct { @@ -96,13 +100,15 @@ type CommonAlertQuery struct { *AlertQuery // metric points'value的运算方式 Reduce string `json:"reduce"` - // 比较运算符, 比如: >, <, >=, <= + // 比较运算符, 比如: >, <, >=, <=, within_range, outside_range Comparator string `json:"comparator"` - // 报警阀值 + // 报警阀值 (用于 gt, lt, eq) Threshold float64 `json:"threshold"` - //field yunsuan - FieldOpt string `json:"field_opt"` - ConditionType string `json:"condition_type"` + // 范围参数 (用于 within_range, outside_range) + ThresholdRange []float64 `json:"threshold_range"` + // field 运算 + FieldOpt CommonAlertFieldOpt `json:"field_opt"` + ConditionType string `json:"condition_type"` // Operator should be chosen from 'and | or' Operator string `json:"operator"` } @@ -161,12 +167,12 @@ type CommonAlertDetails struct { } type CommonAlertMetricDetails struct { - Operator string `json:"operator"` - Comparator string `json:"comparator"` - Threshold float64 `json:"threshold"` - WithinRange []float64 `json:"within_range"` - ConditionType string `json:"condition_type"` - ThresholdStr string `json:"threshold_str"` + Operator string `json:"operator"` + Comparator string `json:"comparator"` + Threshold float64 `json:"threshold"` + ThresholdRange []float64 `json:"threshold_range"` + ConditionType string `json:"condition_type"` + ThresholdStr string `json:"threshold_str"` // metric points'value的运算方式 Reduce string `json:"reduce"` DB string `json:"db"` diff --git a/pkg/apis/monitor/nodealert.go b/pkg/apis/monitor/nodealert.go index e51413a9e9..ae81b368ac 100644 --- a/pkg/apis/monitor/nodealert.go +++ b/pkg/apis/monitor/nodealert.go @@ -168,15 +168,15 @@ const ( ) func GetNodeAlertEvaluator(comparator string, threshold float64) Condition { - typ := ConditionGreaterThan + typ := EvaluatorType(ConditionGreaterThan) switch comparator { case ">=", ">": - typ = ConditionGreaterThan + typ = EvaluatorType(ConditionGreaterThan) case "<=", "<": - typ = ConditionLessThan + typ = EvaluatorType(ConditionLessThan) } return Condition{ - Type: typ, + Type: string(typ), Params: []float64{threshold}, } } diff --git a/pkg/mcclient/modules/monitor/helper.go b/pkg/mcclient/modules/monitor/helper.go index 26b29a15ae..e3e6f729cf 100644 --- a/pkg/mcclient/modules/monitor/helper.go +++ b/pkg/mcclient/modules/monitor/helper.go @@ -184,7 +184,7 @@ func (c *AlertCondition) ToCondition() monitor.AlertCondition { func (c *AlertCondition) ToCommonAlertQuery() monitor.CommonAlertQuery { aq := c.query.ToAlertQuery() - eval := c.evaluator.Type + eval := string(c.evaluator.Type) if !utils.IsInStringArray(eval, []string{"lt", "gt", "eq"}) { panic(fmt.Sprintf("Invalid evaluator %q", eval)) } diff --git a/pkg/monitor/alerting/conditions/evaluator.go b/pkg/monitor/alerting/conditions/evaluator.go index bc22c52709..398874aa12 100644 --- a/pkg/monitor/alerting/conditions/evaluator.go +++ b/pkg/monitor/alerting/conditions/evaluator.go @@ -134,10 +134,10 @@ func NewAlertEvaluator(cond *monitor.Condition) (AlertEvaluator, error) { return nil, validators.ErrMissingParameterType } - if utils.IsInStringArray(typ, validators.EvaluatorDefaultTypes) { + if utils.IsInStringArray(string(typ), validators.EvaluatorDefaultTypes) { return newThresholdEvaluator(cond) } - if utils.IsInStringArray(typ, validators.EvaluatorRangedTypes) { + if utils.IsInStringArray(string(typ), validators.EvaluatorRangedTypes) { return newRangedEvaluator(cond) } diff --git a/pkg/monitor/models/alertpannel.go b/pkg/monitor/models/alertpannel.go index 39f33e992e..3016fe95ec 100644 --- a/pkg/monitor/models/alertpannel.go +++ b/pkg/monitor/models/alertpannel.go @@ -115,7 +115,7 @@ func (man *SAlertPanelManager) ValidateCreateData( } else { for _, query := range data.CommonMetricInputQuery.MetricQuery { if len(query.Comparator) != 0 { - if !utils.IsInStringArray(getQueryEvalType(query.Comparator), validators.EvaluatorDefaultTypes) { + if !utils.IsInStringArray(string(getQueryEvalType(query.Comparator)), validators.EvaluatorDefaultTypes) { return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator) } } @@ -274,7 +274,7 @@ func (dash *SAlertPanel) ValidateUpdateData( return data, errors.Wrap(err, "metric_query Unmarshal error") } if len(query.Comparator) != 0 { - if !utils.IsInStringArray(getQueryEvalType(query.Comparator), validators.EvaluatorDefaultTypes) { + if !utils.IsInStringArray(string(getQueryEvalType(query.Comparator)), validators.EvaluatorDefaultTypes) { return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator) } } diff --git a/pkg/monitor/models/commonalert.go b/pkg/monitor/models/commonalert.go index 7c149d3098..032e0fbd69 100644 --- a/pkg/monitor/models/commonalert.go +++ b/pkg/monitor/models/commonalert.go @@ -218,11 +218,8 @@ func (man *SCommonAlertManager) ValidateCreateData( return data, merrors.NewArgIsEmptyErr("metric_query") } else { for _, query := range data.CommonMetricInputQuery.MetricQuery { - if query.ConditionType == monitor.METRIC_QUERY_TYPE_NO_DATA { - query.Comparator = "==" - } - if !utils.IsInStringArray(getQueryEvalType(query.Comparator), validators.EvaluatorDefaultTypes) { - return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator) + if err := validateCommonAlertQuery(query); err != nil { + return data, err } if _, ok := monitor.AlertReduceFunc[query.Reduce]; !ok { return data, httperrors.NewInputParameterError("the reduce is illegal: %s", query.Reduce) @@ -453,7 +450,7 @@ func (alert *SCommonAlert) PostCreate(ctx context.Context, for i, metricQ := range input.CommonMetricInputQuery.MetricQuery { if metricQ.FieldOpt != "" { if i == 0 { - fieldOpt = metricQ.FieldOpt + fieldOpt = string(metricQ.FieldOpt) continue } fieldOpt = fmt.Sprintf("%s+%s", fieldOpt, metricQ.FieldOpt) @@ -804,11 +801,23 @@ func getCommonAlertMetricDetailsFromCondition( cmp = "==" case "lt": cmp = "<=" + case "within_range": + cmp = "within_range" + case "outside_range": + cmp = "outside_range" } metricDetails.Comparator = cmp - if len(cond.Evaluator.Params) != 0 { - metricDetails.Threshold = cond.Evaluator.Params[0] + // 处理 ranged types + if utils.IsInStringArray(cond.Evaluator.Type, validators.EvaluatorRangedTypes) { + if len(cond.Evaluator.Params) >= 2 { + metricDetails.ThresholdRange = []float64{cond.Evaluator.Params[0], cond.Evaluator.Params[1]} + } + } else { + // 处理默认 types + if len(cond.Evaluator.Params) != 0 { + metricDetails.Threshold = cond.Evaluator.Params[0] + } } metricDetails.Reduce = cond.Reducer.Type @@ -910,25 +919,94 @@ func getMetricDescriptionDetails(metricDetails *monitor.CommonAlertMetricDetails } func getExtraFieldDetails(metricDetails *monitor.CommonAlertMetricDetails) { - if metricDetails.FieldOpt == monitor.CommonAlertFieldOpt_Division && metricDetails.Threshold < float64(1) { + if metricDetails.FieldOpt == string(monitor.CommonAlertFieldOptDivision) && metricDetails.Threshold < float64(1) { metricDetails.Threshold = metricDetails.Threshold * float64(100) metricDetails.FieldDescription.Unit = "%" } } -func getQueryEvalType(evalType string) string { - typ := "" +func getQueryEvalType(evalType string) monitor.EvaluatorType { + var typ monitor.EvaluatorType switch evalType { case ">=", ">": - typ = "gt" + typ = monitor.EvaluatorTypeGT case "<=", "<": - typ = "lt" + typ = monitor.EvaluatorTypeLT case "==": - typ = "eq" + typ = monitor.EvaluatorTypeEQ + case "within_range": + typ = monitor.EvaluatorTypeWithinRange + case "outside_range": + typ = monitor.EvaluatorTypeOutsideRange } return typ } +// validateCommonAlertQuery 校验 CommonAlertQuery 的 comparator 和 threshold_range +func validateCommonAlertQuery(query *monitor.CommonAlertQuery) error { + if query.ConditionType == monitor.METRIC_QUERY_TYPE_NO_DATA { + query.Comparator = "==" + } + evalType := getQueryEvalType(query.Comparator) + if !sets.NewString(append( + validators.EvaluatorDefaultTypes, + validators.EvaluatorRangedTypes...)...).Has(string(evalType)) { + return httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator) + } + // 验证 ranged types 的参数 + if utils.IsInStringArray(string(evalType), validators.EvaluatorRangedTypes) { + if len(query.ThresholdRange) < 2 { + return httperrors.NewInputParameterError("threshold_range or outside_range requires 2 parameters, got %d", len(query.ThresholdRange)) + } + // 确保第一项小于等于第二项 + if query.ThresholdRange[0] > query.ThresholdRange[1] { + return httperrors.NewInputParameterError("threshold_range first value (%v) must be less than or equal to second value (%v)", query.ThresholdRange[0], query.ThresholdRange[1]) + } + } + return nil +} + +// validateComparatorAndThreshold 校验字符串形式的 comparator, threshold 和 threshold_range +func validateComparatorAndThreshold(comparator string, threshold string, thresholdRange []jsonutils.JSONObject) error { + var evalType monitor.EvaluatorType + if len(comparator) != 0 { + evalType = getQueryEvalType(comparator) + if !utils.IsInStringArray(string(evalType), append(validators.EvaluatorDefaultTypes, validators.EvaluatorRangedTypes...)) { + return httperrors.NewInputParameterError("the Comparator is illegal: %s", comparator) + } + // 验证 ranged types 的参数 + if utils.IsInStringArray(string(evalType), validators.EvaluatorRangedTypes) { + if len(thresholdRange) < 2 { + return httperrors.NewInputParameterError("threshold_range or outside_range requires 2 parameters, got %d", len(thresholdRange)) + } + } + } + if len(threshold) != 0 { + _, err := strconv.ParseFloat(threshold, 64) + if err != nil { + return httperrors.NewInputParameterError("threshold:%s should be number type", threshold) + } + } + if len(thresholdRange) > 0 { + if len(thresholdRange) < 2 { + return httperrors.NewInputParameterError("threshold_range requires 2 parameters, got %d", len(thresholdRange)) + } + vals := make([]float64, len(thresholdRange)) + for i, val := range thresholdRange { + parsedVal, err := strconv.ParseFloat(val.String(), 64) + if err != nil { + return httperrors.NewInputParameterError("threshold_range[%d]: %s should be number type", i, val.String()) + } + vals[i] = parsedVal + } + // 确保第一项小于等于第二项 + if vals[0] > vals[1] { + return httperrors.NewInputParameterError("threshold_range first value (%v) must be less than or equal to second value (%v)", vals[0], vals[1]) + } + } + return nil +} + func (man *SCommonAlertManager) toAlertCreatInput(input monitor.CommonAlertCreateInput) (monitor.AlertCreateInput, error) { freq, _ := time.ParseDuration(input.Period) ret := new(monitor.AlertCreateInput) @@ -944,13 +1022,29 @@ func (man *SCommonAlertManager) toAlertCreatInput(input monitor.CommonAlertCreat if len(metricquery.ConditionType) != 0 { conditionType = metricquery.ConditionType } + evalType := getQueryEvalType(metricquery.Comparator) + var evaluatorParams []float64 + // 处理 ranged types (within_range, outside_range) + if utils.IsInStringArray(string(evalType), validators.EvaluatorRangedTypes) { + if len(metricquery.ThresholdRange) < 2 { + return *ret, httperrors.NewInputParameterError("threshold_range or outside_range requires 2 parameters, got %d", len(metricquery.ThresholdRange)) + } + fieldOpt := monitor.CommonAlertFieldOpt(metricquery.FieldOpt) + evaluatorParams = []float64{ + fieldOperatorThreshold(fieldOpt, metricquery.ThresholdRange[0]), + fieldOperatorThreshold(fieldOpt, metricquery.ThresholdRange[1]), + } + } else { + // 处理默认 types (gt, lt, eq) + fieldOpt := monitor.CommonAlertFieldOpt(metricquery.FieldOpt) + evaluatorParams = []float64{fieldOperatorThreshold(fieldOpt, metricquery.Threshold)} + } condition := monitor.AlertCondition{ - Type: conditionType, - Query: *metricquery.AlertQuery, - Reducer: monitor.Condition{Type: metricquery.Reduce}, - Evaluator: monitor.Condition{Type: getQueryEvalType(metricquery.Comparator), - Params: []float64{fieldOperatorThreshold(metricquery.FieldOpt, metricquery.Threshold)}}, - Operator: "and", + Type: conditionType, + Query: *metricquery.AlertQuery, + Reducer: monitor.Condition{Type: metricquery.Reduce}, + Evaluator: monitor.Condition{Type: string(evalType), Params: evaluatorParams}, + Operator: "and", } if metricquery.Operator != "" { if !sets.NewString("and", "or").Has(metricquery.Operator) { @@ -959,15 +1053,15 @@ func (man *SCommonAlertManager) toAlertCreatInput(input monitor.CommonAlertCreat condition.Operator = metricquery.Operator } if metricquery.FieldOpt != "" { - condition.Reducer.Operators = []string{metricquery.FieldOpt} + condition.Reducer.Operators = []string{string(metricquery.FieldOpt)} } ret.Settings.Conditions = append(ret.Settings.Conditions, condition) } return *ret, nil } -func fieldOperatorThreshold(opt string, threshold float64) float64 { - if opt == monitor.CommonAlertFieldOpt_Division && threshold > 1 { +func fieldOperatorThreshold(opt monitor.CommonAlertFieldOpt, threshold float64) float64 { + if opt == monitor.CommonAlertFieldOptDivision && threshold > 1 { return threshold / float64(100) } return threshold @@ -1023,11 +1117,8 @@ func (alert *SCommonAlert) ValidateUpdateData( if err != nil { return data, errors.Wrap(err, "metric_query Unmarshal error") } - if query.ConditionType == monitor.METRIC_QUERY_TYPE_NO_DATA { - query.Comparator = "==" - } - if !utils.IsInStringArray(getQueryEvalType(query.Comparator), validators.EvaluatorDefaultTypes) { - return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", query.Comparator) + if err := validateCommonAlertQuery(query); err != nil { + return data, err } if _, ok := monitor.AlertReduceFunc[query.Reduce]; !ok { return data, httperrors.NewInputParameterError("the reduce is illegal: %s", query.Reduce) @@ -1276,21 +1367,14 @@ func (alert *SCommonAlert) PerformConfig(ctx context.Context, userCred mcclient. period, _ := data.GetString("period") comparator, _ := data.GetString("comparator") threshold, _ := data.GetString("threshold") + thresholdRange, _ := data.GetArray("threshold_range") if len(period) != 0 { if _, err := time.ParseDuration(period); err != nil { return data, httperrors.NewInputParameterError("Invalid period format: %s", period) } } - if len(comparator) != 0 { - if !utils.IsInStringArray(getQueryEvalType(comparator), validators.EvaluatorDefaultTypes) { - return data, httperrors.NewInputParameterError("the Comparator is illegal: %s", comparator) - } - } - if len(threshold) != 0 { - _, err := strconv.ParseFloat(threshold, 64) - if err != nil { - return data, httperrors.NewInputParameterError("threshold:%s should be number type", threshold) - } + if err := validateComparatorAndThreshold(comparator, threshold, thresholdRange); err != nil { + return data, err } _, err := db.Update(alert, func() error { if len(period) != 0 { @@ -1299,12 +1383,19 @@ func (alert *SCommonAlert) PerformConfig(ctx context.Context, userCred mcclient. } setting, _ := alert.GetSettings() if len(comparator) != 0 { - setting.Conditions[0].Evaluator.Type = getQueryEvalType(comparator) - + evalType := getQueryEvalType(comparator) + setting.Conditions[0].Evaluator.Type = string(evalType) } - if len(threshold) != 0 { + // 处理 ranged types + if len(thresholdRange) >= 2 { + vals := make([]float64, 2) + for i := 0; i < 2 && i < len(thresholdRange); i++ { + val, _ := strconv.ParseFloat(thresholdRange[i].String(), 64) + vals[i] = fieldOperatorThreshold("", val) + } + setting.Conditions[0].Evaluator.Params = vals + } else if len(threshold) != 0 { val, _ := strconv.ParseFloat(threshold, 64) - fmt.Println(threshold) setting.Conditions[0].Evaluator.Params = []float64{fieldOperatorThreshold("", val)} } alert.Settings = jsonutils.Marshal(setting) @@ -1509,7 +1600,9 @@ func (alert *SCommonAlert) GetAlertRule(settings *monitor.AlertSetting, index in Field: alertDetails.Field, FieldDesc: alertDetails.FieldDescription.DisplayName, Comparator: alertDetails.Comparator, + Unit: alertDetails.FieldDescription.Unit, Threshold: RationalizeValueFromUnit(alertDetails.Threshold, alertDetails.FieldDescription.Unit, ""), + ThresholdRange: alertDetails.ThresholdRange, ConditionType: alertDetails.ConditionType, Reducer: alertDetails.Reduce, } @@ -1557,7 +1650,7 @@ func RationalizeValueFromUnit(value float64, unit string, opt string) string { } return FormatFileSize(value, unit, float64(1000)) } - if unit == "%" && monitor.CommonAlertFieldOpt_Division == opt { + if unit == "%" && monitor.CommonAlertFieldOptDivision == monitor.CommonAlertFieldOpt(opt) { return fmt.Sprintf("%0.2f%s", value*100, unit) } return fmt.Sprintf("%0.2f%s", value, unit) diff --git a/pkg/monitor/validators/validators.go b/pkg/monitor/validators/validators.go index 92e45afa90..efd301534a 100644 --- a/pkg/monitor/validators/validators.go +++ b/pkg/monitor/validators/validators.go @@ -36,8 +36,8 @@ const ( ) var ( - EvaluatorDefaultTypes = []string{"gt", "lt", "eq"} - EvaluatorRangedTypes = []string{"within_range", "outside_range"} + EvaluatorDefaultTypes = []string{string(monitor.EvaluatorTypeGT), string(monitor.EvaluatorTypeLT), string(monitor.EvaluatorTypeEQ)} + EvaluatorRangedTypes = []string{string(monitor.EvaluatorTypeWithinRange), string(monitor.EvaluatorTypeOutsideRange)} CommonAlertType = []string{ monitor.CommonAlertNomalAlertType, @@ -152,10 +152,10 @@ func ValidateAlertConditionEvaluator(input monitor.Condition) error { if typ == "" { return ErrMissingParameterType } - if utils.IsInStringArray(typ, EvaluatorDefaultTypes) { + if utils.IsInStringArray(string(typ), EvaluatorDefaultTypes) { return ValidateAlertConditionThresholdEvaluator(input) } - if utils.IsInStringArray(typ, EvaluatorRangedTypes) { + if utils.IsInStringArray(string(typ), EvaluatorRangedTypes) { return ValidateAlertConditionRangedEvaluator(input) } if typ != "no_value" { @@ -176,14 +176,14 @@ func ValidateAlertConditionType(typ string) error { func ValidateAlertConditionThresholdEvaluator(input monitor.Condition) error { if len(input.Params) == 0 { - return errors.Wrapf(ErrMissingParameterThreshold, "Evaluator %s", HumanThresholdType(input.Type)) + return errors.Wrapf(ErrMissingParameterThreshold, "Evaluator %s", HumanThresholdType(monitor.EvaluatorType(input.Type))) } return nil } func ValidateAlertConditionRangedEvaluator(input monitor.Condition) error { if len(input.Params) == 0 { - return errors.Wrapf(ErrMissingParameterThreshold, "Evaluator %s", HumanThresholdType(input.Type)) + return errors.Wrapf(ErrMissingParameterThreshold, "Evaluator %s", HumanThresholdType(monitor.EvaluatorType(input.Type))) } if len(input.Params) == 1 { return errors.Wrap(ErrMissingParameterThreshold, "RangedEvaluator parameter second parameter is missing") @@ -193,16 +193,18 @@ func ValidateAlertConditionRangedEvaluator(input monitor.Condition) error { // HumanThresholdType converts a threshold "type" string to a string that matches the UI // so errors are less confusing. -func HumanThresholdType(typ string) string { +func HumanThresholdType(typ monitor.EvaluatorType) string { switch typ { - case "gt": + case monitor.EvaluatorTypeGT: return "IS ABOVE" - case "lt": + case monitor.EvaluatorTypeLT: return "IS BELOW" - case "within_range": + case monitor.EvaluatorTypeWithinRange: return "IS WITHIN RANGE" - case "outside_range": + case monitor.EvaluatorTypeOutsideRange: return "IS OUTSIDE RANGE" + case monitor.EvaluatorTypeEQ: + return "IS EQUAL TO" } return "" }