From da74f976969c661de9af7974dcddbba8d7cc531d Mon Sep 17 00:00:00 2001 From: Lukasz Mierzwa Date: Thu, 2 Jan 2025 16:57:31 +0000 Subject: [PATCH] Store API paths in one place --- cmd/pint/bench_test.go | 11 ++++++----- internal/checks/base_test.go | 10 +++++----- internal/checks/promql_series_test.go | 10 +++++----- internal/promapi/config.go | 15 +++++++++------ internal/promapi/config_test.go | 14 +++++++------- internal/promapi/flags.go | 13 ++++++++----- internal/promapi/flags_test.go | 12 ++++++------ internal/promapi/metadata.go | 8 ++++++-- internal/promapi/query.go | 8 ++++++-- internal/promapi/range.go | 8 ++++++-- 10 files changed, 64 insertions(+), 45 deletions(-) diff --git a/cmd/pint/bench_test.go b/cmd/pint/bench_test.go index 178ef536..f6335363 100644 --- a/cmd/pint/bench_test.go +++ b/cmd/pint/bench_test.go @@ -17,6 +17,7 @@ import ( "github.com/cloudflare/pint/internal/git" "github.com/cloudflare/pint/internal/log" "github.com/cloudflare/pint/internal/parser" + "github.com/cloudflare/pint/internal/promapi" ) func BenchmarkFindEntries(b *testing.B) { @@ -50,23 +51,23 @@ func BenchmarkCheckRules(b *testing.B) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { - case "/api/v1/status/config": + case promapi.APIPathConfig: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"yaml":"global:\n scrape_interval: 30s\n"}}`)) - case "/api/v1/status/flags": + case promapi.APIPathFlags: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"storage.tsdb.retention.time": "1d"}}`)) - case "/api/v1/metadata": + case promapi.APIPathMetadata: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{}}`)) - case "/api/v1/query": + case promapi.APIPathQuery: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"resultType":"vector","result":[]}}`)) - case "/api/v1/query_range": + case promapi.APIPathQueryRange: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"resultType":"matrix","result":[]}}`)) diff --git a/internal/checks/base_test.go b/internal/checks/base_test.go index d77b882a..c3372d4b 100644 --- a/internal/checks/base_test.go +++ b/internal/checks/base_test.go @@ -285,11 +285,11 @@ func (fc formCond) isMatch(r *http.Request) bool { } var ( - requireConfigPath = requestPathCond{path: "/api/v1/status/config"} - requireFlagsPath = requestPathCond{path: "/api/v1/status/flags"} - requireQueryPath = requestPathCond{path: "/api/v1/query"} - requireRangeQueryPath = requestPathCond{path: "/api/v1/query_range"} - requireMetadataPath = requestPathCond{path: "/api/v1/metadata"} + requireConfigPath = requestPathCond{path: promapi.APIPathConfig} + requireFlagsPath = requestPathCond{path: promapi.APIPathFlags} + requireQueryPath = requestPathCond{path: promapi.APIPathQuery} + requireRangeQueryPath = requestPathCond{path: promapi.APIPathQueryRange} + requireMetadataPath = requestPathCond{path: promapi.APIPathMetadata} ) type promError struct { diff --git a/internal/checks/promql_series_test.go b/internal/checks/promql_series_test.go index 52b2351d..8d2c91c5 100644 --- a/internal/checks/promql_series_test.go +++ b/internal/checks/promql_series_test.go @@ -3975,7 +3975,7 @@ func TestSeriesCheck(t *testing.T) { }, mocks: []*prometheusMock{ { - conds: []requestCondition{requestPathCond{path: "/other/api/v1/query"}}, + conds: []requestCondition{requestPathCond{path: "/other" + promapi.APIPathQuery}}, resp: respondWithEmptyVector(), }, { @@ -4016,7 +4016,7 @@ func TestSeriesCheck(t *testing.T) { }, mocks: []*prometheusMock{ { - conds: []requestCondition{requestPathCond{path: "/other/api/v1/query"}}, + conds: []requestCondition{requestPathCond{path: "/other" + promapi.APIPathQuery}}, resp: respondWithSingleInstantVector(), }, { @@ -4057,7 +4057,7 @@ func TestSeriesCheck(t *testing.T) { }, mocks: []*prometheusMock{ { - conds: []requestCondition{requestPathCond{path: "/other/api/v1/query"}}, + conds: []requestCondition{requestPathCond{path: "/other" + promapi.APIPathQuery}}, resp: respondWithSingleInstantVector(), }, { @@ -4108,7 +4108,7 @@ func TestSeriesCheck(t *testing.T) { }, mocks: []*prometheusMock{ { - conds: []requestCondition{requestPathCond{path: "/other/api/v1/query"}}, + conds: []requestCondition{requestPathCond{path: "/other" + promapi.APIPathQuery}}, resp: sleepResponse{ sleep: time.Millisecond * 20, resp: respondWithSingleInstantVector(), @@ -4163,7 +4163,7 @@ func TestSeriesCheck(t *testing.T) { }, mocks: []*prometheusMock{ { - conds: []requestCondition{requestPathCond{path: "/other/api/v1/query"}}, + conds: []requestCondition{requestPathCond{path: "/other" + promapi.APIPathQuery}}, resp: sleepResponse{ sleep: time.Millisecond * 230, resp: respondWithSingleInstantVector(), diff --git a/internal/promapi/config.go b/internal/promapi/config.go index e9d534b9..96f0c91e 100644 --- a/internal/promapi/config.go +++ b/internal/promapi/config.go @@ -15,6 +15,10 @@ import ( "gopkg.in/yaml.v3" ) +const ( + APIPathConfig = "/api/v1/status/config" +) + type ConfigSectionGlobal struct { ExternalLabels map[string]string `yaml:"external_labels"` ScrapeInterval time.Duration `yaml:"scrape_interval"` @@ -62,18 +66,18 @@ func (q configQuery) Run() queryResult { qr.value, err = streamConfig(resp.Body) if err != nil { - prometheusQueryErrorsTotal.WithLabelValues(q.prom.name, "/api/v1/status/config", errReason(err)).Inc() + prometheusQueryErrorsTotal.WithLabelValues(q.prom.name, APIPathConfig, errReason(err)).Inc() qr.err = fmt.Errorf("failed to decode config data in %s response: %w", q.prom.safeURI, err) } return qr } func (q configQuery) Endpoint() string { - return "/api/v1/status/config" + return APIPathConfig } func (q configQuery) String() string { - return "/api/v1/status/config" + return APIPathConfig } func (q configQuery) CacheKey() uint64 { @@ -87,9 +91,8 @@ func (q configQuery) CacheTTL() time.Duration { func (p *Prometheus) Config(ctx context.Context, cacheTTL time.Duration) (*ConfigResult, error) { slog.Debug("Scheduling Prometheus configuration query", slog.String("uri", p.safeURI)) - key := "/api/v1/status/config" - p.locker.lock(key) - defer p.locker.unlock(key) + p.locker.lock(APIPathConfig) + defer p.locker.unlock(APIPathConfig) if cacheTTL == 0 { cacheTTL = time.Minute diff --git a/internal/promapi/config_test.go b/internal/promapi/config_test.go index 6be39f79..c5cc3a61 100644 --- a/internal/promapi/config_test.go +++ b/internal/promapi/config_test.go @@ -20,31 +20,31 @@ import ( func TestConfig(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { - case "/30s/api/v1/status/config": + case "/30s" + promapi.APIPathConfig: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"yaml":"global:\n scrape_interval: 30s\n"}}`)) - case "/1m/api/v1/status/config": + case "/1m" + promapi.APIPathConfig: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"yaml":"global:\n scrape_interval: 1m\n"}}`)) - case "/default/api/v1/status/config": + case "/default" + promapi.APIPathConfig: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"yaml":"global:\n {}\n"}}`)) - case "/once/api/v1/status/config": + case "/once" + promapi.APIPathConfig: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"yaml":"global:\n {}\n"}}`)) - case "/slow/api/v1/status/config": + case "/slow" + promapi.APIPathConfig: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") time.Sleep(time.Second * 2) _, _ = w.Write([]byte(`{"status":"success","data":{"yaml":"global:\n {}\n"}}`)) - case "/error/api/v1/status/config": + case "/error" + promapi.APIPathConfig: w.WriteHeader(500) _, _ = w.Write([]byte("fake error\n")) - case "/badYaml/api/v1/status/config": + case "/badYaml" + promapi.APIPathConfig: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"yaml":"invalid yaml"}}`)) diff --git a/internal/promapi/flags.go b/internal/promapi/flags.go index 3f641fd7..11e4b534 100644 --- a/internal/promapi/flags.go +++ b/internal/promapi/flags.go @@ -14,6 +14,10 @@ import ( "github.com/prymitive/current" ) +const ( + APIPathFlags = "/api/v1/status/flags" +) + type FlagsResult struct { Flags v1.FlagsResult URI string @@ -52,11 +56,11 @@ func (q flagsQuery) Run() queryResult { } func (q flagsQuery) Endpoint() string { - return "/api/v1/status/flags" + return APIPathFlags } func (q flagsQuery) String() string { - return "/api/v1/status/flags" + return APIPathFlags } func (q flagsQuery) CacheKey() uint64 { @@ -70,9 +74,8 @@ func (q flagsQuery) CacheTTL() time.Duration { func (p *Prometheus) Flags(ctx context.Context) (*FlagsResult, error) { slog.Debug("Scheduling Prometheus flags query", slog.String("uri", p.safeURI)) - key := "/api/v1/status/flags" - p.locker.lock(key) - defer p.locker.unlock(key) + p.locker.lock(APIPathFlags) + defer p.locker.unlock(APIPathFlags) resultChan := make(chan queryResult) p.queries <- queryRequest{ diff --git a/internal/promapi/flags_test.go b/internal/promapi/flags_test.go index 49dce5c1..58c22777 100644 --- a/internal/promapi/flags_test.go +++ b/internal/promapi/flags_test.go @@ -18,27 +18,27 @@ import ( func TestFlags(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { - case "/default/api/v1/status/flags": + case "/default" + promapi.APIPathFlags: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{}}`)) - case "/foo/api/v1/status/flags": + case "/foo" + promapi.APIPathFlags: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"foo":"bar"}}`)) - case "/once/api/v1/status/flags": + case "/once" + promapi.APIPathFlags: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{}}`)) - case "/slow/api/v1/status/flags": + case "/slow" + promapi.APIPathFlags: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") time.Sleep(time.Second * 2) _, _ = w.Write([]byte(`{"status":"success","data":{}}`)) - case "/error/api/v1/status/flags": + case "/error" + promapi.APIPathFlags: w.WriteHeader(500) _, _ = w.Write([]byte("fake error\n")) - case "/badYaml/api/v1/status/flags": + case "/badYaml" + promapi.APIPathFlags: w.WriteHeader(200) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"status":"success","data":{"xxx"}}`)) diff --git a/internal/promapi/metadata.go b/internal/promapi/metadata.go index 563b3fe5..a68a6b1c 100644 --- a/internal/promapi/metadata.go +++ b/internal/promapi/metadata.go @@ -14,6 +14,10 @@ import ( "github.com/prymitive/current" ) +const ( + APIPathMetadata = "/api/v1/metadata" +) + type MetadataResult struct { URI string Metadata []v1.Metadata @@ -58,7 +62,7 @@ func (q metadataQuery) Run() queryResult { } func (q metadataQuery) Endpoint() string { - return "/api/v1/metadata" + return APIPathMetadata } func (q metadataQuery) String() string { @@ -76,7 +80,7 @@ func (q metadataQuery) CacheTTL() time.Duration { func (p *Prometheus) Metadata(ctx context.Context, metric string) (*MetadataResult, error) { slog.Debug("Scheduling Prometheus metrics metadata query", slog.String("uri", p.safeURI), slog.String("metric", metric)) - key := "/api/v1/metadata/" + metric + key := APIPathMetadata + metric p.locker.lock(key) defer p.locker.unlock(key) diff --git a/internal/promapi/query.go b/internal/promapi/query.go index 5d937269..e3d8f519 100644 --- a/internal/promapi/query.go +++ b/internal/promapi/query.go @@ -17,6 +17,10 @@ import ( "github.com/prymitive/current" ) +const ( + APIPathQuery = "/api/v1/query" +) + type QueryResult struct { URI string Series []Sample @@ -63,7 +67,7 @@ func (q instantQuery) Run() queryResult { } func (q instantQuery) Endpoint() string { - return "/api/v1/query" + return APIPathQuery } func (q instantQuery) String() string { @@ -81,7 +85,7 @@ func (q instantQuery) CacheTTL() time.Duration { func (p *Prometheus) Query(ctx context.Context, expr string) (*QueryResult, error) { slog.Debug("Scheduling prometheus query", slog.String("uri", p.safeURI), slog.String("query", expr)) - key := "/api/v1/query/" + expr + key := APIPathQuery + expr p.locker.lock(key) defer p.locker.unlock(key) diff --git a/internal/promapi/range.go b/internal/promapi/range.go index 263acfdb..12f11e63 100644 --- a/internal/promapi/range.go +++ b/internal/promapi/range.go @@ -22,6 +22,10 @@ import ( "github.com/cloudflare/pint/internal/output" ) +const ( + APIPathQueryRange = "/api/v1/query_range" +) + type RangeQueryResult struct { URI string Series SeriesTimeRanges @@ -69,7 +73,7 @@ func (q rangeQuery) Run() queryResult { } func (q rangeQuery) Endpoint() string { - return "/api/v1/query_range" + return APIPathQueryRange } func (q rangeQuery) String() string { @@ -116,7 +120,7 @@ func (p *Prometheus) RangeQuery(ctx context.Context, expr string, params RangeQu slog.Int("slices", len(slices)), ) - key := fmt.Sprintf("/api/v1/query_range/%s/%s", expr, params.String()) + key := fmt.Sprintf("%s/%s/%s", APIPathQueryRange, expr, params.String()) p.locker.lock(key) defer p.locker.unlock(key)