mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
promtool: Speed up checking for duplicate rules
Trade space for speed. Convert all rules into our temporary struct, sort and then iterate. This is a significant when having many rules. Signed-off-by: Holger Hans Peter Freyther <holger@moiji-mobile.com>
This commit is contained in:
parent
3a309c1ae5
commit
5edec40d60
|
@ -24,7 +24,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -48,6 +48,7 @@ import (
|
||||||
_ "github.com/prometheus/prometheus/discovery/install" // Register service discovery implementations.
|
_ "github.com/prometheus/prometheus/discovery/install" // Register service discovery implementations.
|
||||||
"github.com/prometheus/prometheus/discovery/kubernetes"
|
"github.com/prometheus/prometheus/discovery/kubernetes"
|
||||||
"github.com/prometheus/prometheus/discovery/targetgroup"
|
"github.com/prometheus/prometheus/discovery/targetgroup"
|
||||||
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/prometheus/pkg/rulefmt"
|
"github.com/prometheus/prometheus/pkg/rulefmt"
|
||||||
"github.com/prometheus/prometheus/promql"
|
"github.com/prometheus/prometheus/promql"
|
||||||
)
|
)
|
||||||
|
@ -471,8 +472,8 @@ func checkRules(filename string) (int, []error) {
|
||||||
fmt.Printf("%d duplicate rule(s) found.\n", len(dRules))
|
fmt.Printf("%d duplicate rule(s) found.\n", len(dRules))
|
||||||
for _, n := range dRules {
|
for _, n := range dRules {
|
||||||
fmt.Printf("Metric: %s\nLabel(s):\n", n.metric)
|
fmt.Printf("Metric: %s\nLabel(s):\n", n.metric)
|
||||||
for i, l := range n.label {
|
for _, l := range n.label {
|
||||||
fmt.Printf("\t%s: %s\n", i, l)
|
fmt.Printf("\t%s: %s\n", l.Name, l.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("Might cause inconsistency while recording expressions.")
|
fmt.Println("Might cause inconsistency while recording expressions.")
|
||||||
|
@ -483,29 +484,52 @@ func checkRules(filename string) (int, []error) {
|
||||||
|
|
||||||
type compareRuleType struct {
|
type compareRuleType struct {
|
||||||
metric string
|
metric string
|
||||||
label map[string]string
|
label labels.Labels
|
||||||
|
}
|
||||||
|
|
||||||
|
type compareRuleTypes []compareRuleType
|
||||||
|
|
||||||
|
func (c compareRuleTypes) Len() int { return len(c) }
|
||||||
|
func (c compareRuleTypes) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||||
|
func (c compareRuleTypes) Less(i, j int) bool { return compare(c[i], c[j]) < 0 }
|
||||||
|
|
||||||
|
func compare(a, b compareRuleType) int {
|
||||||
|
if res := strings.Compare(a.metric, b.metric); res != 0 {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels.Compare(a.label, b.label)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkDuplicates(groups []rulefmt.RuleGroup) []compareRuleType {
|
func checkDuplicates(groups []rulefmt.RuleGroup) []compareRuleType {
|
||||||
var duplicates []compareRuleType
|
var duplicates []compareRuleType
|
||||||
|
var rules compareRuleTypes
|
||||||
|
|
||||||
for _, group := range groups {
|
for _, group := range groups {
|
||||||
for index, rule := range group.Rules {
|
|
||||||
inst := compareRuleType{
|
for _, rule := range group.Rules {
|
||||||
|
rules = append(rules, compareRuleType{
|
||||||
metric: ruleMetric(rule),
|
metric: ruleMetric(rule),
|
||||||
label: rule.Labels,
|
label: labels.FromMap(rule.Labels),
|
||||||
}
|
})
|
||||||
for i := 0; i < index; i++ {
|
|
||||||
t := compareRuleType{
|
|
||||||
metric: ruleMetric(group.Rules[i]),
|
|
||||||
label: group.Rules[i].Labels,
|
|
||||||
}
|
|
||||||
if reflect.DeepEqual(t, inst) {
|
|
||||||
duplicates = append(duplicates, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(rules) < 2 {
|
||||||
|
return duplicates
|
||||||
|
}
|
||||||
|
sort.Sort(rules)
|
||||||
|
|
||||||
|
last := rules[0]
|
||||||
|
for i := 1; i < len(rules); i++ {
|
||||||
|
if compare(last, rules[i]) == 0 {
|
||||||
|
// Don't add a duplicated rule multiple times.
|
||||||
|
if len(duplicates) == 0 || compare(last, duplicates[len(duplicates)-1]) != 0 {
|
||||||
|
duplicates = append(duplicates, rules[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last = rules[i]
|
||||||
|
}
|
||||||
|
|
||||||
return duplicates
|
return duplicates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/prometheus/prometheus/pkg/labels"
|
||||||
"github.com/prometheus/prometheus/pkg/rulefmt"
|
"github.com/prometheus/prometheus/pkg/rulefmt"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -136,6 +137,7 @@ func TestCheckDuplicates(t *testing.T) {
|
||||||
expectedDups: []compareRuleType{
|
expectedDups: []compareRuleType{
|
||||||
{
|
{
|
||||||
metric: "job:test:count_over_time1m",
|
metric: "job:test:count_over_time1m",
|
||||||
|
label: labels.New(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue