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
|
@ -70,9 +70,13 @@ const (
|
||||||
|
|
||||||
lintOptionAll = "all"
|
lintOptionAll = "all"
|
||||||
lintOptionDuplicateRules = "duplicate-rules"
|
lintOptionDuplicateRules = "duplicate-rules"
|
||||||
|
lintOptionLongScrapeInterval = "long-scrape-inerval"
|
||||||
lintOptionNone = "none"
|
lintOptionNone = "none"
|
||||||
checkHealth = "/-/healthy"
|
checkHealth = "/-/healthy"
|
||||||
checkReadiness = "/-/ready"
|
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}
|
var lintOptions = []string{lintOptionAll, lintOptionDuplicateRules, lintOptionNone}
|
||||||
|
@ -445,6 +449,7 @@ var errLint = fmt.Errorf("lint error")
|
||||||
type lintConfig struct {
|
type lintConfig struct {
|
||||||
all bool
|
all bool
|
||||||
duplicateRules bool
|
duplicateRules bool
|
||||||
|
longScrapeInterval bool
|
||||||
fatal bool
|
fatal bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,6 +464,8 @@ func newLintConfig(stringVal string, fatal bool) lintConfig {
|
||||||
ls.all = true
|
ls.all = true
|
||||||
case lintOptionDuplicateRules:
|
case lintOptionDuplicateRules:
|
||||||
ls.duplicateRules = true
|
ls.duplicateRules = true
|
||||||
|
case lintOptionLongScrapeInterval:
|
||||||
|
ls.longScrapeInterval = true
|
||||||
case lintOptionNone:
|
case lintOptionNone:
|
||||||
default:
|
default:
|
||||||
fmt.Printf("WARNING: unknown lint option %s\n", setting)
|
fmt.Printf("WARNING: unknown lint option %s\n", setting)
|
||||||
|
@ -471,6 +478,10 @@ func (ls lintConfig) lintDuplicateRules() bool {
|
||||||
return ls.all || ls.duplicateRules
|
return ls.all || ls.duplicateRules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ls lintConfig) lintLongScrapeInterval() bool {
|
||||||
|
return ls.all || ls.longScrapeInterval
|
||||||
|
}
|
||||||
|
|
||||||
// CheckServerStatus - healthy & ready.
|
// CheckServerStatus - healthy & ready.
|
||||||
func CheckServerStatus(serverURL *url.URL, checkEndpoint string, roundTripper http.RoundTripper) error {
|
func CheckServerStatus(serverURL *url.URL, checkEndpoint string, roundTripper http.RoundTripper) error {
|
||||||
if serverURL.Scheme == "" {
|
if serverURL.Scheme == "" {
|
||||||
|
@ -514,10 +525,10 @@ func CheckConfig(agentMode, checkSyntaxOnly bool, lintSettings lintConfig, files
|
||||||
hasErrors := false
|
hasErrors := false
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
ruleFiles, err := checkConfig(agentMode, f, checkSyntaxOnly)
|
ruleFiles, err := checkConfig(agentMode, f, checkSyntaxOnly, lintSettings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, " FAILED:", err)
|
fmt.Fprintln(os.Stderr, " FAILED:", err)
|
||||||
hasErrors = true
|
hasErrors = !errors.Is(err, errLint)
|
||||||
failed = true
|
failed = true
|
||||||
} else {
|
} else {
|
||||||
if len(ruleFiles) > 0 {
|
if len(ruleFiles) > 0 {
|
||||||
|
@ -571,7 +582,7 @@ func checkFileExists(fn string) error {
|
||||||
return err
|
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)
|
fmt.Println("Checking", filename)
|
||||||
|
|
||||||
cfg, err := config.LoadFile(filename, agentMode, false, log.NewNopLogger())
|
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 {
|
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 !checkSyntaxOnly && scfg.HTTPClientConfig.Authorization != nil {
|
||||||
if err := checkFileExists(scfg.HTTPClientConfig.Authorization.CredentialsFile); err != 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)
|
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 {
|
for _, test := range cases {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
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 != "" {
|
if test.err != "" {
|
||||||
require.Equalf(t, test.err, err.Error(), "Expected error %q, got %q", test.err, err.Error())
|
require.Equalf(t, test.err, err.Error(), "Expected error %q, got %q", test.err, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -302,7 +302,7 @@ func TestCheckConfigSyntax(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, test := range cases {
|
for _, test := range cases {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
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
|
expectedErrMsg := test.err
|
||||||
if strings.Contains(runtime.GOOS, "windows") {
|
if strings.Contains(runtime.GOOS, "windows") {
|
||||||
expectedErrMsg = test.errWindows
|
expectedErrMsg = test.errWindows
|
||||||
|
@ -336,7 +336,7 @@ func TestAuthorizationConfig(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range cases {
|
for _, test := range cases {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
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 != "" {
|
if test.err != "" {
|
||||||
require.Contains(t, err.Error(), test.err, "Expected error to contain %q, got %q", test.err, err.Error())
|
require.Contains(t, err.Error(), test.err, "Expected error to contain %q, got %q", test.err, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -414,7 +414,7 @@ func TestExitCodes(t *testing.T) {
|
||||||
t.Run(strconv.FormatBool(lintFatal), func(t *testing.T) {
|
t.Run(strconv.FormatBool(lintFatal), func(t *testing.T) {
|
||||||
args := []string{"-test.main", "check", "config", "testdata/" + c.file}
|
args := []string{"-test.main", "check", "config", "testdata/" + c.file}
|
||||||
if lintFatal {
|
if lintFatal {
|
||||||
args = append(args, "--lint-fatal")
|
args = append(args, "--lint-fatal", "--lint=all")
|
||||||
}
|
}
|
||||||
tool := exec.Command(promtoolPath, args...)
|
tool := exec.Command(promtoolPath, args...)
|
||||||
err := tool.Run()
|
err := tool.Run()
|
||||||
|
@ -531,6 +531,13 @@ func TestCheckRules(t *testing.T) {
|
||||||
exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, true))
|
exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, true))
|
||||||
require.Equal(t, lintErrExitCode, exitCode, "")
|
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) {
|
func TestCheckRulesWithRuleFiles(t *testing.T) {
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
rule_files:
|
scrape_configs:
|
||||||
- prometheus-rules.lint.yml
|
- job_name: long_scrape_interval_test
|
||||||
|
scrape_interval: 1h
|
Loading…
Reference in a new issue