mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
PromTool: Support Scrape Interval Lint Checking
Signed-off-by: zhaowang <zhaowang@apac.freewheel.com>
This commit is contained in:
parent
5fd2717aec
commit
fcc35ba551
|
@ -68,11 +68,15 @@ const (
|
|||
// Exit code 3 is used for "one or more lint issues detected".
|
||||
lintErrExitCode = 3
|
||||
|
||||
lintOptionAll = "all"
|
||||
lintOptionDuplicateRules = "duplicate-rules"
|
||||
lintOptionNone = "none"
|
||||
checkHealth = "/-/healthy"
|
||||
checkReadiness = "/-/ready"
|
||||
lintOptionAll = "all"
|
||||
lintOptionDuplicateRules = "duplicate-rules"
|
||||
lintOptionLongScrapeInterval = "long-scrape-inerval"
|
||||
lintOptionNone = "none"
|
||||
checkHealth = "/-/healthy"
|
||||
checkReadiness = "/-/ready"
|
||||
|
||||
// Remove when the lookback delta can be set as a command line flag on PromTool.
|
||||
defaultLookbackDelta = 5 * time.Minute
|
||||
)
|
||||
|
||||
var lintOptions = []string{lintOptionAll, lintOptionDuplicateRules, lintOptionNone}
|
||||
|
@ -443,9 +447,10 @@ func checkExperimental(f bool) {
|
|||
var errLint = fmt.Errorf("lint error")
|
||||
|
||||
type lintConfig struct {
|
||||
all bool
|
||||
duplicateRules bool
|
||||
fatal bool
|
||||
all bool
|
||||
duplicateRules bool
|
||||
longScrapeInterval bool
|
||||
fatal bool
|
||||
}
|
||||
|
||||
func newLintConfig(stringVal string, fatal bool) lintConfig {
|
||||
|
@ -459,6 +464,8 @@ func newLintConfig(stringVal string, fatal bool) lintConfig {
|
|||
ls.all = true
|
||||
case lintOptionDuplicateRules:
|
||||
ls.duplicateRules = true
|
||||
case lintOptionLongScrapeInterval:
|
||||
ls.longScrapeInterval = true
|
||||
case lintOptionNone:
|
||||
default:
|
||||
fmt.Printf("WARNING: unknown lint option %s\n", setting)
|
||||
|
@ -471,6 +478,10 @@ func (ls lintConfig) lintDuplicateRules() bool {
|
|||
return ls.all || ls.duplicateRules
|
||||
}
|
||||
|
||||
func (ls lintConfig) lintLongScrapeInterval() bool {
|
||||
return ls.all || ls.longScrapeInterval
|
||||
}
|
||||
|
||||
// CheckServerStatus - healthy & ready.
|
||||
func CheckServerStatus(serverURL *url.URL, checkEndpoint string, roundTripper http.RoundTripper) error {
|
||||
if serverURL.Scheme == "" {
|
||||
|
@ -514,10 +525,10 @@ func CheckConfig(agentMode, checkSyntaxOnly bool, lintSettings lintConfig, files
|
|||
hasErrors := false
|
||||
|
||||
for _, f := range files {
|
||||
ruleFiles, err := checkConfig(agentMode, f, checkSyntaxOnly)
|
||||
ruleFiles, err := checkConfig(agentMode, f, checkSyntaxOnly, lintSettings)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, " FAILED:", err)
|
||||
hasErrors = true
|
||||
hasErrors = !errors.Is(err, errLint)
|
||||
failed = true
|
||||
} else {
|
||||
if len(ruleFiles) > 0 {
|
||||
|
@ -571,7 +582,7 @@ func checkFileExists(fn string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func checkConfig(agentMode bool, filename string, checkSyntaxOnly bool) ([]string, error) {
|
||||
func checkConfig(agentMode bool, filename string, checkSyntaxOnly bool, lintSettings lintConfig) ([]string, error) {
|
||||
fmt.Println("Checking", filename)
|
||||
|
||||
cfg, err := config.LoadFile(filename, agentMode, false, log.NewNopLogger())
|
||||
|
@ -611,6 +622,13 @@ func checkConfig(agentMode bool, filename string, checkSyntaxOnly bool) ([]strin
|
|||
}
|
||||
|
||||
for _, scfg := range scfgs {
|
||||
if lintSettings.lintLongScrapeInterval() {
|
||||
if scfg.ScrapeInterval >= model.Duration(defaultLookbackDelta) {
|
||||
errMessage := fmt.Sprintf("Long Scrape Interval found. Data point will be marked as stale. Job: %s. Interval: %s", scfg.JobName, scfg.ScrapeInterval.String())
|
||||
return nil, fmt.Errorf("%w %s", errLint, errMessage)
|
||||
}
|
||||
}
|
||||
|
||||
if !checkSyntaxOnly && scfg.HTTPClientConfig.Authorization != nil {
|
||||
if err := checkFileExists(scfg.HTTPClientConfig.Authorization.CredentialsFile); err != nil {
|
||||
return nil, fmt.Errorf("error checking authorization credentials or bearer token file %q: %w", scfg.HTTPClientConfig.Authorization.CredentialsFile, err)
|
||||
|
|
|
@ -219,7 +219,7 @@ func TestCheckTargetConfig(t *testing.T) {
|
|||
}
|
||||
for _, test := range cases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
_, err := checkConfig(false, "testdata/"+test.file, false)
|
||||
_, err := checkConfig(false, "testdata/"+test.file, false, newLintConfig(lintOptionNone, false))
|
||||
if test.err != "" {
|
||||
require.Equalf(t, test.err, err.Error(), "Expected error %q, got %q", test.err, err.Error())
|
||||
return
|
||||
|
@ -302,7 +302,7 @@ func TestCheckConfigSyntax(t *testing.T) {
|
|||
}
|
||||
for _, test := range cases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
_, err := checkConfig(false, "testdata/"+test.file, test.syntaxOnly)
|
||||
_, err := checkConfig(false, "testdata/"+test.file, test.syntaxOnly, newLintConfig(lintOptionNone, false))
|
||||
expectedErrMsg := test.err
|
||||
if strings.Contains(runtime.GOOS, "windows") {
|
||||
expectedErrMsg = test.errWindows
|
||||
|
@ -336,7 +336,7 @@ func TestAuthorizationConfig(t *testing.T) {
|
|||
|
||||
for _, test := range cases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
_, err := checkConfig(false, "testdata/"+test.file, false)
|
||||
_, err := checkConfig(false, "testdata/"+test.file, false, newLintConfig(lintOptionNone, false))
|
||||
if test.err != "" {
|
||||
require.Contains(t, err.Error(), test.err, "Expected error to contain %q, got %q", test.err, err.Error())
|
||||
return
|
||||
|
@ -414,7 +414,7 @@ func TestExitCodes(t *testing.T) {
|
|||
t.Run(strconv.FormatBool(lintFatal), func(t *testing.T) {
|
||||
args := []string{"-test.main", "check", "config", "testdata/" + c.file}
|
||||
if lintFatal {
|
||||
args = append(args, "--lint-fatal")
|
||||
args = append(args, "--lint-fatal", "--lint=all")
|
||||
}
|
||||
tool := exec.Command(promtoolPath, args...)
|
||||
err := tool.Run()
|
||||
|
@ -531,6 +531,13 @@ func TestCheckRules(t *testing.T) {
|
|||
exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, true))
|
||||
require.Equal(t, lintErrExitCode, exitCode, "")
|
||||
})
|
||||
|
||||
t.Run("config-lint-fatal", func(t *testing.T) {
|
||||
_, err := checkConfig(false, "./testdata/prometheus-config.lint.yml", false, newLintConfig(lintOptionLongScrapeInterval, false))
|
||||
expectedErrMsg := "lint error Long Scrape Interval found. Data point will be marked as stale. Job: long_scrape_interval_test. Interval: 1h"
|
||||
require.Equalf(t, expectedErrMsg, err.Error(), "Expected error %q, got %q", expectedErrMsg, err.Error())
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
func TestCheckRulesWithRuleFiles(t *testing.T) {
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
rule_files:
|
||||
- prometheus-rules.lint.yml
|
||||
scrape_configs:
|
||||
- job_name: long_scrape_interval_test
|
||||
scrape_interval: 1h
|
Loading…
Reference in a new issue