diff --git a/cmd/pint/tests/0054_watch_metrics_prometheus.txt b/cmd/pint/tests/0054_watch_metrics_prometheus.txt index 104fb79d..c486437b 100644 --- a/cmd/pint/tests/0054_watch_metrics_prometheus.txt +++ b/cmd/pint/tests/0054_watch_metrics_prometheus.txt @@ -92,15 +92,15 @@ pint_last_run_time_seconds # TYPE pint_problem gauge pint_problem{filename="rules/1.yml",kind="recording",name="aggregate",owner="",problem="Couldn't run \"promql/counter\" checks due to `prom2` Prometheus server at http://127.0.0.1:1054 connection error: `connection refused`.",reporter="promql/counter",severity="bug"} pint_problem{filename="rules/1.yml",kind="recording",name="aggregate",owner="",problem="Couldn't run \"promql/range_query\" checks due to `prom2` Prometheus server at http://127.0.0.1:1054 connection error: `connection refused`.",reporter="promql/range_query",severity="bug"} -pint_problem{filename="rules/1.yml",kind="recording",name="aggregate",owner="",problem="Couldn't run \"promql/rate\" checks due to `prom1` Prometheus server at http://127.0.0.1:7054 connection error: `server_error: server error: 500`.",reporter="promql/rate",severity="bug"} +pint_problem{filename="rules/1.yml",kind="recording",name="aggregate",owner="",problem="Couldn't run \"promql/rate\" checks due to `prom1` Prometheus server at http://127.0.0.1:7054 connection error: `server_error: 500 Internal Server Error`.",reporter="promql/rate",severity="bug"} pint_problem{filename="rules/1.yml",kind="recording",name="aggregate",owner="",problem="Couldn't run \"promql/rate\" checks due to `prom2` Prometheus server at http://127.0.0.1:1054 connection error: `connection refused`.",reporter="promql/rate",severity="bug"} pint_problem{filename="rules/1.yml",kind="recording",name="aggregate",owner="",problem="Couldn't run \"promql/series\" checks due to `prom2` Prometheus server at http://127.0.0.1:1054 connection error: `connection refused`.",reporter="promql/series",severity="bug"} pint_problem{filename="rules/1.yml",kind="recording",name="aggregate",owner="",problem="`prom1` Prometheus server at http://127.0.0.1:7054 failed with: `bad_data: bogus query`.",reporter="promql/series",severity="bug"} pint_problem{filename="rules/1.yml",kind="recording",name="broken",owner="",problem="Prometheus failed to parse the query with this PromQL error: no arguments for aggregate expression provided.",reporter="promql/syntax",severity="fatal"} -pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="Couldn't run \"alerts/external_labels\" checks due to `prom1` Prometheus server at http://127.0.0.1:7054 connection error: `server_error: server error: 500`.",reporter="alerts/external_labels",severity="bug"} +pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="Couldn't run \"alerts/external_labels\" checks due to `prom1` Prometheus server at http://127.0.0.1:7054 connection error: `server_error: 500 Internal Server Error`.",reporter="alerts/external_labels",severity="bug"} pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="Couldn't run \"alerts/external_labels\" checks due to `prom2` Prometheus server at http://127.0.0.1:1054 connection error: `connection refused`.",reporter="alerts/external_labels",severity="bug"} pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="Couldn't run \"promql/range_query\" checks due to `prom2` Prometheus server at http://127.0.0.1:1054 connection error: `connection refused`.",reporter="promql/range_query",severity="bug"} -pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="Couldn't run \"promql/rate\" checks due to `prom1` Prometheus server at http://127.0.0.1:7054 connection error: `server_error: server error: 500`.",reporter="promql/rate",severity="bug"} +pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="Couldn't run \"promql/rate\" checks due to `prom1` Prometheus server at http://127.0.0.1:7054 connection error: `server_error: 500 Internal Server Error`.",reporter="promql/rate",severity="bug"} pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="Couldn't run \"promql/rate\" checks due to `prom2` Prometheus server at http://127.0.0.1:1054 connection error: `connection refused`.",reporter="promql/rate",severity="bug"} pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="Couldn't run \"promql/series\" checks due to `prom2` Prometheus server at http://127.0.0.1:1054 connection error: `connection refused`.",reporter="promql/series",severity="bug"} pint_problem{filename="rules/2.yml",kind="alerting",name="comparison",owner="bob and alice",problem="`prom1` Prometheus server at http://127.0.0.1:7054 failed with: `bad_data: bogus query`.",reporter="promql/series",severity="bug"} diff --git a/cmd/pint/tests/0056_prometheus_required.txt b/cmd/pint/tests/0056_prometheus_required.txt index bb22d66e..7ce11824 100644 --- a/cmd/pint/tests/0056_prometheus_required.txt +++ b/cmd/pint/tests/0056_prometheus_required.txt @@ -3,8 +3,8 @@ http start prometheus 127.0.0.1:7056 exec pint -l debug --no-color lint rules ! stdout . -stderr 'level=ERROR msg="Query returned an error" err="server error: 500" uri=http://127.0.0.1:7056 query=count\(up\)' -stderr 'level=ERROR msg="Query returned an error" err="server error: 500" uri=http://127.0.0.1:7056 query=/api/v1/status/config' +stderr 'level=ERROR msg="Query returned an error" err="500 Internal Server Error" uri=http://127.0.0.1:7056 query=count\(up\)' +stderr 'level=ERROR msg="Query returned an error" err="500 Internal Server Error" uri=http://127.0.0.1:7056 query=/api/v1/status/config' stderr 'level=INFO msg="Problems found" Warning=[0-9]+' -- rules/1.yaml -- diff --git a/cmd/pint/tests/0104_file_ignore_prom.txt b/cmd/pint/tests/0104_file_ignore_prom.txt index 5c3898d4..16627763 100644 --- a/cmd/pint/tests/0104_file_ignore_prom.txt +++ b/cmd/pint/tests/0104_file_ignore_prom.txt @@ -4,9 +4,9 @@ http start prometheus 127.0.0.1:7104 ! exec pint --no-color lint rules ! stdout . -stderr 'level=ERROR msg="Query returned an error" err="server error: 502" uri=http://127.0.0.1:7104 query=/api/v1/status/config' -stderr 'level=ERROR msg="Query returned an error" err="server error: 502" uri=http://127.0.0.1:7104 query=/api/v1/status/flags' -stderr 'level=ERROR msg="Query returned an error" err="server error: 502" uri=http://127.0.0.1:7104 query=count\(foo\)' +stderr 'level=ERROR msg="Query returned an error" err="502 Bad Gateway" uri=http://127.0.0.1:7104 query=/api/v1/status/config' +stderr 'level=ERROR msg="Query returned an error" err="502 Bad Gateway" uri=http://127.0.0.1:7104 query=/api/v1/status/flags' +stderr 'level=ERROR msg="Query returned an error" err="502 Bad Gateway" uri=http://127.0.0.1:7104 query=count\(foo\)' stderr 'level=INFO msg="Problems found" Bug=3' -- rules/0001.yml -- # This should skip all online checks diff --git a/internal/checks/promql_series_test.go b/internal/checks/promql_series_test.go index 8d2c91c5..878a0a8a 100644 --- a/internal/checks/promql_series_test.go +++ b/internal/checks/promql_series_test.go @@ -3,6 +3,7 @@ package checks_test import ( "context" "fmt" + "net/http" "testing" "time" @@ -4179,6 +4180,60 @@ func TestSeriesCheck(t *testing.T) { }, }, }, + { + description: "unsupported query", + content: "- record: foo\n expr: sum(foo)\n", + checker: newSeriesCheck, + prometheus: newSimpleProm, + problems: func(uri string) []checks.Problem { + return []checks.Problem{ + { + Lines: parser.LineRange{ + First: 2, + Last: 2, + }, + Reporter: checks.SeriesCheckName, + Text: checkErrorBadData("prom", uri, "client_error: 404 Not Found"), + Severity: checks.Bug, + }, + } + }, + mocks: []*prometheusMock{ + { + conds: []requestCondition{requireQueryPath}, + resp: httpResponse{code: http.StatusNotFound, body: "Not Found"}, + }, + }, + }, + { + description: "unsupported range query", + content: "- record: foo\n expr: sum(foo)\n", + checker: newSeriesCheck, + prometheus: newSimpleProm, + problems: func(uri string) []checks.Problem { + return []checks.Problem{ + { + Lines: parser.LineRange{ + First: 2, + Last: 2, + }, + Reporter: checks.SeriesCheckName, + Text: checkErrorBadData("prom", uri, "client_error: 404 Not Found"), + Severity: checks.Bug, + }, + } + }, + mocks: []*prometheusMock{ + { + conds: []requestCondition{requireQueryPath}, + resp: respondWithEmptyVector(), + }, + { + conds: []requestCondition{requireRangeQueryPath}, + resp: httpResponse{code: http.StatusNotFound, body: "Not Found"}, + }, + }, + }, } runTests(t, testCases) } diff --git a/internal/promapi/config_test.go b/internal/promapi/config_test.go index c5cc3a61..14de089e 100644 --- a/internal/promapi/config_test.go +++ b/internal/promapi/config_test.go @@ -112,7 +112,7 @@ func TestConfig(t *testing.T) { { prefix: "/error", timeout: time.Second, - err: "server_error: server error: 500", + err: "server_error: 500 Internal Server Error", }, { prefix: "/badYaml", diff --git a/internal/promapi/errors.go b/internal/promapi/errors.go index 70a1e716..810359f0 100644 --- a/internal/promapi/errors.go +++ b/internal/promapi/errors.go @@ -115,14 +115,25 @@ func tryDecodingAPIError(resp *http.Response) error { slog.Debug("Trying to parse Prometheus error response", slog.Int("code", resp.StatusCode)) if resp.StatusCode == http.StatusNotFound { - apiPath := "some API endpoints" + var apiPath string + msg := "some API endpoints" if resp.Request != nil { - apiPath = "`" + resp.Request.URL.Path + "` API endpoint" + switch { + case strings.HasSuffix(resp.Request.URL.Path, APIPathConfig): + apiPath = APIPathConfig + case strings.HasSuffix(resp.Request.URL.Path, APIPathFlags): + apiPath = APIPathFlags + case strings.HasSuffix(resp.Request.URL.Path, APIPathMetadata): + apiPath = APIPathMetadata + } + msg = "`" + apiPath + "` API endpoint" } - return APIError{ - Status: "", - ErrorType: ErrAPIUnsupported, - Err: "this server doesn't seem to support " + apiPath, + if apiPath != "" { + return APIError{ + Status: "", + ErrorType: ErrAPIUnsupported, + Err: "this server doesn't seem to support " + msg, + } } } @@ -143,9 +154,9 @@ func tryDecodingAPIError(resp *http.Response) error { if err := decoder.Stream(dec); err != nil { switch resp.StatusCode / 100 { case 4: - return APIError{Status: "error", ErrorType: v1.ErrClient, Err: fmt.Sprintf("client error: %d", resp.StatusCode)} + return APIError{Status: "error", ErrorType: v1.ErrClient, Err: resp.Status} case 5: - return APIError{Status: "error", ErrorType: v1.ErrServer, Err: fmt.Sprintf("server error: %d", resp.StatusCode)} + return APIError{Status: "error", ErrorType: v1.ErrServer, Err: resp.Status} } return APIError{Status: "error", ErrorType: v1.ErrBadResponse, Err: fmt.Sprintf("bad response code: %d", resp.StatusCode)} } diff --git a/internal/promapi/flags_test.go b/internal/promapi/flags_test.go index 58c22777..c791c61a 100644 --- a/internal/promapi/flags_test.go +++ b/internal/promapi/flags_test.go @@ -82,7 +82,7 @@ func TestFlags(t *testing.T) { { prefix: "/error", timeout: time.Second, - err: "server_error: server error: 500", + err: "server_error: 500 Internal Server Error", }, { prefix: "/badYaml", diff --git a/internal/promapi/metadata_test.go b/internal/promapi/metadata_test.go index 58e12e66..d647e289 100644 --- a/internal/promapi/metadata_test.go +++ b/internal/promapi/metadata_test.go @@ -111,7 +111,7 @@ func TestMetadata(t *testing.T) { { metric: "error", timeout: time.Second, - err: "server_error: server error: 500", + err: "server_error: 500 Internal Server Error", }, { metric: "once",