From b57deb6eb02f7333c2c5da5c908f1264fa9a4e06 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Wed, 20 Jul 2022 14:55:09 +0200 Subject: [PATCH] Add /api/v1/format_query API endpoint for formatting queries (#11036) * Add /api/v1/format_query API endpoint for formatting queries This uses the formatting functionality introduced in https://github.com/prometheus/prometheus/pull/10544. I've chosen "query" instead of "expr" in both the endpoint and parameter names to stay consistent with the existing API endpoints. Otherwise, I would have preferred to use the term "expr". Signed-off-by: Julius Volz * Add docs for /api/v1/format_query endpoint Signed-off-by: Julius Volz * Add note that formatting expressions removes comments Signed-off-by: Julius Volz --- docs/querying/api.md | 29 +++++++++++++++++++++++++++++ web/api/v1/api.go | 12 ++++++++++++ web/api/v1/api_test.go | 14 ++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/docs/querying/api.md b/docs/querying/api.md index 8428fc3323..5d6024e511 100644 --- a/docs/querying/api.md +++ b/docs/querying/api.md @@ -206,6 +206,35 @@ $ curl 'http://localhost:9090/api/v1/query_range?query=up&start=2015-07-01T20:10 } ``` +## Formatting query expressions + +The following endpoint formats a PromQL expression in a prettified way: + +``` +GET /api/v1/format_query +POST /api/v1/format_query +``` + +URL query parameters: + +- `query=`: Prometheus expression query string. + +You can URL-encode these parameters directly in the request body by using the `POST` method and +`Content-Type: application/x-www-form-urlencoded` header. This is useful when specifying a large +query that may breach server-side URL character limits. + +The `data` section of the query result is a string containing the formatted query expression. Note that any comments are removed in the formatted string. + +The following example formats the expression `foo/bar`: + +```json +$ curl 'http://localhost:9090/api/v1/format_query?query=foo/bar' +{ + "status" : "success", + "data" : "foo / bar" +} +``` + ## Querying metadata Prometheus offers a set of API endpoints to query metadata about series and their labels. diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 0ad24abdbf..3c4a342910 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -323,6 +323,9 @@ func (api *API) Register(r *route.Router) { r.Get("/query_exemplars", wrapAgent(api.queryExemplars)) r.Post("/query_exemplars", wrapAgent(api.queryExemplars)) + r.Get("/format_query", wrapAgent(api.formatQuery)) + r.Post("/format_query", wrapAgent(api.formatQuery)) + r.Get("/labels", wrapAgent(api.labelNames)) r.Post("/labels", wrapAgent(api.labelNames)) r.Get("/label/:name/values", wrapAgent(api.labelValues)) @@ -428,6 +431,15 @@ func (api *API) query(r *http.Request) (result apiFuncResult) { }, nil, res.Warnings, qry.Close} } +func (api *API) formatQuery(r *http.Request) (result apiFuncResult) { + expr, err := parser.ParseExpr(r.FormValue("query")) + if err != nil { + return invalidParamError(err, "query") + } + + return apiFuncResult{expr.Pretty(0), nil, nil, nil} +} + func extractQueryOpts(r *http.Request) *promql.QueryOpts { return &promql.QueryOpts{ EnablePerStepStats: r.FormValue("stats") == "all", diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 8df755a1ff..a904e47db3 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -930,6 +930,20 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E }, errType: errorBadData, }, + { + endpoint: api.formatQuery, + query: url.Values{ + "query": []string{"foo+bar"}, + }, + response: "foo + bar", + }, + { + endpoint: api.formatQuery, + query: url.Values{ + "query": []string{"invalid_expression/"}, + }, + errType: errorBadData, + }, { endpoint: api.series, query: url.Values{