diff --git a/cmd/promtool/main.go b/cmd/promtool/main.go index 5be2734e6b..1a620037c1 100644 --- a/cmd/promtool/main.go +++ b/cmd/promtool/main.go @@ -23,6 +23,7 @@ import ( "net/url" "os" "path/filepath" + "reflect" "strconv" "strings" "time" @@ -303,9 +304,49 @@ func checkRules(filename string) (int, []error) { numRules += len(rg.Rules) } + dRules := checkDuplicates(rgs.Groups) + if len(dRules) != 0 { + fmt.Printf("%d duplicate rules(s) found.\n", len(dRules)) + for _, n := range dRules { + fmt.Printf("Metric: %s\nLabel(s):\n", n.metric) + for i, l := range n.label { + fmt.Printf("\t%s: %s\n", i, l) + } + } + fmt.Println("Might cause inconsistency while recording expressions.") + } + return numRules, nil } +type compareRuleType struct { + metric string + label map[string]string +} + +func checkDuplicates(r []rulefmt.RuleGroup) []compareRuleType { + var duplicates []compareRuleType + + for rindex := range r { + for index, props := range r[rindex].Rules { + inst := compareRuleType{ + metric: props.Record, + label: props.Labels, + } + for i := 0; i < index; i++ { + t := compareRuleType{ + metric: r[rindex].Rules[i].Record, + label: r[rindex].Rules[i].Labels, + } + if reflect.DeepEqual(t, inst) { + duplicates = append(duplicates, t) + } + } + } + } + return duplicates +} + var checkMetricsUsage = strings.TrimSpace(` Pass Prometheus metrics over stdin to lint them for consistency and correctness.