-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added thanos check rules command
Signed-off-by: Martin Chodur <[email protected]>
- Loading branch information
Showing
9 changed files
with
299 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package main | ||
|
||
import ( | ||
"io/ioutil" | ||
|
||
"github.com/go-kit/kit/log" | ||
"github.com/go-kit/kit/log/level" | ||
thanosrule "github.com/improbable-eng/thanos/pkg/rule" | ||
"github.com/oklog/run" | ||
"github.com/opentracing/opentracing-go" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/prometheus/pkg/rulefmt" | ||
"github.com/prometheus/tsdb" | ||
"gopkg.in/alecthomas/kingpin.v2" | ||
"gopkg.in/yaml.v2" | ||
) | ||
|
||
func registerChecks(m map[string]setupFunc, app *kingpin.Application, name string) { | ||
cmd := app.Command(name, "Linting tools for Thanos") | ||
registerCheckRules(m, cmd, name) | ||
} | ||
|
||
func registerCheckRules(m map[string]setupFunc, root *kingpin.CmdClause, name string) { | ||
checkRulesCmd := root.Command("rules", "Check if the rule files are valid or not.") | ||
ruleFiles := checkRulesCmd.Arg( | ||
"rule-files", | ||
"The rule files to check.", | ||
).Required().ExistingFiles() | ||
|
||
m[name+" rules"] = func(g *run.Group, logger log.Logger, reg *prometheus.Registry, _ opentracing.Tracer, _ bool) error { | ||
// Dummy actor to immediately kill the group after the run function returns. | ||
g.Add(func() error { return nil }, func(error) {}) | ||
return checkRulesFiles(logger, ruleFiles) | ||
} | ||
} | ||
|
||
func checkRulesFiles(logger log.Logger, files *[]string) error { | ||
failed := tsdb.MultiError{} | ||
|
||
for _, f := range *files { | ||
n, errs := checkRules(logger, f) | ||
if errs.Err() != nil { | ||
level.Error(logger).Log("result", "FAILED") | ||
for _, e := range errs { | ||
level.Error(logger).Log("error", e.Error()) | ||
failed.Add(e) | ||
} | ||
level.Info(logger).Log() | ||
continue | ||
} | ||
level.Info(logger).Log("result", "SUCCESS", "rules found", n) | ||
} | ||
if failed.Err() != nil { | ||
return failed | ||
} | ||
return nil | ||
} | ||
|
||
func checkRules(logger log.Logger, filename string) (int, tsdb.MultiError) { | ||
level.Info(logger).Log("msg", "checking", "filename", filename) | ||
checkErrors := tsdb.MultiError{} | ||
|
||
b, err := ioutil.ReadFile(filename) | ||
if err != nil { | ||
checkErrors.Add(err) | ||
return 0, checkErrors | ||
} | ||
|
||
var rgs thanosrule.RuleGroups | ||
if err := yaml.Unmarshal(b, &rgs); err != nil { | ||
checkErrors.Add(err) | ||
return 0, checkErrors | ||
} | ||
|
||
// We need to convert Thanos rules to Prometheus rules so we can use their validation. | ||
promRgs := thanosRuleGroupsToPromRuleGroups(rgs) | ||
if errs := promRgs.Validate(); errs != nil { | ||
for _, e := range errs { | ||
checkErrors.Add(e) | ||
} | ||
return 0, checkErrors | ||
} | ||
|
||
numRules := 0 | ||
for _, rg := range rgs.Groups { | ||
numRules += len(rg.Rules) | ||
} | ||
|
||
return numRules, checkErrors | ||
} | ||
|
||
func thanosRuleGroupsToPromRuleGroups(ruleGroups thanosrule.RuleGroups) rulefmt.RuleGroups { | ||
promRuleGroups := rulefmt.RuleGroups{Groups: []rulefmt.RuleGroup{}} | ||
for _, g := range ruleGroups.Groups { | ||
group := rulefmt.RuleGroup{ | ||
Name: g.Name, | ||
Interval: g.Interval, | ||
Rules: []rulefmt.Rule{}, | ||
} | ||
for _, r := range g.Rules { | ||
group.Rules = append( | ||
group.Rules, | ||
rulefmt.Rule{ | ||
Record: r.Record, | ||
Alert: r.Alert, | ||
Expr: r.Expr, | ||
For: r.For, | ||
Labels: r.Labels, | ||
Annotations: r.Annotations, | ||
}, | ||
) | ||
} | ||
promRuleGroups.Groups = append( | ||
promRuleGroups.Groups, | ||
group, | ||
) | ||
} | ||
return promRuleGroups | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/go-kit/kit/log" | ||
"github.com/improbable-eng/thanos/pkg/testutil" | ||
) | ||
|
||
func Test_checkRules(t *testing.T) { | ||
|
||
validFiles := []string{ | ||
"./testdata/rules-files/valid.yaml", | ||
} | ||
|
||
invalidFiles := [][]string{ | ||
[]string{"./testdata/rules-files/non-existing-file.yaml"}, | ||
[]string{"./testdata/rules-files/invalid-yaml-format.yaml"}, | ||
[]string{"./testdata/rules-files/invalid-rules-data.yaml"}, | ||
} | ||
|
||
logger := log.NewNopLogger() | ||
|
||
testutil.Ok(t, checkRulesFiles(logger, &validFiles)) | ||
|
||
for _, fn := range invalidFiles { | ||
testutil.NotOk(t, checkRulesFiles(logger, &fn)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
groups: | ||
- name: null | ||
partial_response_strategy: "warn" | ||
interval: 2m | ||
rules: | ||
- alert: TestAlert | ||
partial_response_strategy: "warn" | ||
expr: 1 | ||
labels: | ||
key: value | ||
annotations: | ||
key: value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
groups: | ||
- name: test | ||
invalid_yaml_reason |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
groups: | ||
- name: test-alert-group | ||
partial_response_strategy: "warn" | ||
interval: 2m | ||
rules: | ||
- alert: TestAlert | ||
partial_response_strategy: "warn" | ||
expr: 1 | ||
labels: | ||
key: value | ||
annotations: | ||
key: value | ||
|
||
- name: test-rule-group | ||
partial_response_strategy: "warn" | ||
interval: 2m | ||
rules: | ||
- record: test_metric | ||
expr: 1 | ||
partial_response_strategy: "warn" |
Oops, something went wrong.