VarFillingAfterQuery 填充变量,先查询再填充变量 公式: mem_used_percent{host="$host"} > $val 其中 $host 为参数变量,$val 为值变量 实现步骤: 依次遍历参数配置节点,保证同一参数变量的子筛选可以覆盖上一层筛选 每个节点先查询无参数的 query, 即 mem_used_percent{} > curVal, 得到满足值变量的所有结果 结果中有满足本节点参数变量的值,加入异常点列表 参数变量的值不满足的组合,需要覆盖上层筛选中产生的异常点
(query models.PromQuery, readerClient promsdk.API)
| 389 | // 结果中有满足本节点参数变量的值,加入异常点列表 |
| 390 | // 参数变量的值不满足的组合,需要覆盖上层筛选中产生的异常点 |
| 391 | func (arw *AlertRuleWorker) VarFillingAfterQuery(query models.PromQuery, readerClient promsdk.API) []models.AnomalyPoint { |
| 392 | varToLabel := ExtractVarMapping(query.PromQl) |
| 393 | fullQuery := removeVal(query.PromQl) |
| 394 | // 存储所有的异常点,key 为参数变量的组合,可以实现子筛选对上一层筛选的覆盖 |
| 395 | anomalyPointsMap := make(map[string]models.AnomalyPoint) |
| 396 | // 统一变量配置格式 |
| 397 | VarConfigForCalc := &models.ChildVarConfig{ |
| 398 | ParamVal: make([]map[string]models.ParamQuery, 1), |
| 399 | ChildVarConfigs: query.VarConfig.ChildVarConfigs, |
| 400 | } |
| 401 | VarConfigForCalc.ParamVal[0] = make(map[string]models.ParamQuery) |
| 402 | for _, p := range query.VarConfig.ParamVal { |
| 403 | VarConfigForCalc.ParamVal[0][p.Name] = models.ParamQuery{ |
| 404 | ParamType: p.ParamType, |
| 405 | Query: p.Query, |
| 406 | } |
| 407 | } |
| 408 | // 使用一个统一的参数变量顺序 |
| 409 | var ParamKeys []string |
| 410 | for val, valQuery := range VarConfigForCalc.ParamVal[0] { |
| 411 | if valQuery.ParamType == "threshold" { |
| 412 | continue |
| 413 | } |
| 414 | ParamKeys = append(ParamKeys, val) |
| 415 | } |
| 416 | sort.Slice(ParamKeys, func(i, j int) bool { |
| 417 | return ParamKeys[i] < ParamKeys[j] |
| 418 | }) |
| 419 | // 遍历变量配置链表 |
| 420 | curNode := VarConfigForCalc |
| 421 | for curNode != nil { |
| 422 | for _, param := range curNode.ParamVal { |
| 423 | // curQuery 当前节点的无参数 query,用于时序库查询 |
| 424 | curQuery := fullQuery |
| 425 | // realQuery 当前节点产生异常点的 query,用于告警展示 |
| 426 | realQuery := query.PromQl |
| 427 | // 取出阈值变量 |
| 428 | valMap := make(map[string]string) |
| 429 | for val, valQuery := range param { |
| 430 | if valQuery.ParamType == "threshold" { |
| 431 | valMap[val] = getString(valQuery.Query) |
| 432 | } |
| 433 | } |
| 434 | // 替换值变量 |
| 435 | for key, val := range valMap { |
| 436 | curQuery = strings.Replace(curQuery, fmt.Sprintf("$%s", key), val, -1) |
| 437 | realQuery = strings.Replace(realQuery, fmt.Sprintf("$%s", key), val, -1) |
| 438 | } |
| 439 | // 得到满足值变量的所有结果 |
| 440 | arw.Processor.Stats.CounterQueryDataTotal.WithLabelValues(fmt.Sprintf("%d", arw.DatasourceId), fmt.Sprintf("%d", arw.Rule.Id)).Inc() |
| 441 | value, _, err := readerClient.Query(context.Background(), curQuery, time.Now()) |
| 442 | if err != nil { |
| 443 | logger.Errorf("rule_eval:%s, promql:%s, error:%v", arw.Key(), curQuery, err) |
| 444 | continue |
| 445 | } |
| 446 | seqVals := getSamples(value) |
| 447 | // 得到参数变量的所有组合 |
| 448 | paramPermutation, err := arw.getParamPermutation(param, ParamKeys, varToLabel, query.PromQl, readerClient) |
no test coverage detected