Skip to content

Commit 4f0a9a3

Browse files
Merge branch 'master' into ticket6702
Signed-off-by: 7h3-3mp7y-m4n <[email protected]>
2 parents bab3d91 + ca36512 commit 4f0a9a3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2382
-350
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Changelog
22

33
## master / unreleased
4+
* [FEATURE] Query Frontend: Add support /api/v1/format_query API for formatting queries. #6893
45
* [CHANGE] StoreGateway/Alertmanager: Add default 5s connection timeout on client. #6603
56
* [CHANGE] Ingester: Remove EnableNativeHistograms config flag and instead gate keep through new per-tenant limit at ingestion. #6718
67
* [CHANGE] Validate a tenantID when to use a single tenant resolver. #6727
@@ -19,6 +20,7 @@
1920
* [FEATURE] Compactor: Add support for percentage based sharding for compactors. #6738
2021
* [FEATURE] Querier: Allow choosing PromQL engine via header. #6777
2122
* [FEATURE] Config: Name validation scheme for metric and label names can be set using the config file (`name_validation_scheme`) as well as a CLI flag (`-name.validation_scheme`)
23+
* [FEATURE] Querier: Support for configuring query optimizers and enabling XFunctions in the Thanos engine. #6873
2224
* [ENHANCEMENT] Tenant Federation: Add a # of query result limit logic when the `-tenant-federation.regex-matcher-enabled` is enabled. #6845
2325
* [ENHANCEMENT] Query Frontend: Add a `cortex_slow_queries_total` metric to track # of slow queries per user. #6859
2426
* [ENHANCEMENT] Query Frontend: Change to return 400 when the tenant resolving fail. #6715
@@ -57,6 +59,8 @@
5759
* [ENHANCEMENT] Distributor: Add native histograms max sample size bytes limit validation. #6834
5860
* [ENHANCEMENT] Querier: Support caching parquet labels file in parquet queryable. #6835
5961
* [ENHANCEMENT] Querier: Support query limits in parquet queryable. #6870
62+
* [ENHANCEMENT] Ring: Add zone label to ring_members metric. #6900
63+
* [ENHANCEMENT] Ingester: Add new metric `cortex_ingester_push_errors_total` to track reasons for ingester request failures. #6901
6064
* [BUGFIX] Ingester: Avoid error or early throttling when READONLY ingesters are present in the ring #6517
6165
* [BUGFIX] Ingester: Fix labelset data race condition. #6573
6266
* [BUGFIX] Compactor: Cleaner should not put deletion marker for blocks with no-compact marker. #6576
@@ -75,6 +79,7 @@
7579
* [BUGFIX] Ingester: Allow shipper to skip corrupted blocks. #6786
7680
* [BUGFIX] Compactor: Delete the prefix `blocks_meta` from the metadata fetcher metrics. #6832
7781
* [BUGFIX] Store Gateway: Avoid race condition by deduplicating entries in bucket stores user scan. #6863
82+
* [BUGFIX] Runtime-config: Change to check tenant limit validation when loading runtime config only for `all`, `distributor`, `querier`, and `ruler` targets. #6880
7883

7984
## 1.19.0 2025-02-27
8085

docs/api/_index.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ For the sake of clarity, in this document we have grouped API endpoints by servi
3737
| [Instant query](#instant-query) | Querier, Query-frontend || `GET,POST <prometheus-http-prefix>/api/v1/query` |
3838
| [Range query](#range-query) | Querier, Query-frontend || `GET,POST <prometheus-http-prefix>/api/v1/query_range` |
3939
| [Exemplar query](#exemplar-query) | Querier, Query-frontend || `GET,POST <prometheus-http-prefix>/api/v1/query_exemplars` |
40+
| [Format query](#format-query) | Querier, Query-frontend || `GET,POST <prometheus-http-prefix>/api/v1/format-query` |
4041
| [Get series by label matchers](#get-series-by-label-matchers) | Querier, Query-frontend || `GET,POST <prometheus-http-prefix>/api/v1/series` |
4142
| [Get label names](#get-label-names) | Querier, Query-frontend || `GET,POST <prometheus-http-prefix>/api/v1/labels` |
4243
| [Get label values](#get-label-values) | Querier, Query-frontend || `GET <prometheus-http-prefix>/api/v1/label/{name}/values` |
@@ -368,6 +369,21 @@ _For more information, please check out the Prometheus [exemplar query](https://
368369

369370
_Requires [authentication](#authentication)._
370371

372+
### Format query
373+
374+
```
375+
GET,POST <prometheus-http-prefix>/api/v1/format_query
376+
377+
# Legacy
378+
GET,POST <legacy-http-prefix>/api/v1/format_query
379+
```
380+
381+
Prometheus-compatible format query endpoint. The endpoint formats a PromQL expression in a prettified way.
382+
383+
_For more information, please check out the Prometheus [fomatting query expressions](https://prometheus.io/docs/prometheus/latest/querying/api/#formatting-query-expressions) documentation._
384+
385+
_Requires [authentication](#authentication)._
386+
371387
### Get series by label matchers
372388

373389
```

docs/blocks-storage/querier.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,22 @@ querier:
252252
# CLI flag: -querier.shuffle-sharding-ingesters-lookback-period
253253
[shuffle_sharding_ingesters_lookback_period: <duration> | default = 0s]
254254

255-
# Experimental. Use Thanos promql engine
256-
# https://github.com/thanos-io/promql-engine rather than the Prometheus promql
257-
# engine.
258-
# CLI flag: -querier.thanos-engine
259-
[thanos_engine: <boolean> | default = false]
255+
thanos_engine:
256+
# Experimental. Use Thanos promql engine
257+
# https://github.com/thanos-io/promql-engine rather than the Prometheus
258+
# promql engine.
259+
# CLI flag: -querier.thanos-engine
260+
[enabled: <boolean> | default = false]
261+
262+
# Enable xincrease, xdelta, xrate etc from Thanos engine.
263+
# CLI flag: -querier.enable-x-functions
264+
[enable_x_functions: <boolean> | default = false]
265+
266+
# Logical plan optimizers. Multiple optimizers can be provided as a
267+
# comma-separated list. Supported values: default, all, propagate-matchers,
268+
# sort-matchers, merge-selects, detect-histogram-stats
269+
# CLI flag: -querier.optimizers
270+
[optimizers: <string> | default = "default"]
260271

261272
# If enabled, ignore max query length check at Querier select method. Users
262273
# can choose to ignore it since the validation can be done before Querier

docs/configuration/arguments.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ The next three options only apply when the querier is used together with the Que
9797

9898
Set this flag to `true` for the new behaviour.
9999

100-
Important to note is that when setting this flag to `true`, it has to be set on both the distributor and the querier (called `-distributor.shard-by-all-labels` on Querier as well). If the flag is only set on the distributor and not on the querier, you will get incomplete query results because not all ingesters are queried.
100+
Important to note is that when setting this flag to `true`, it has to be set on the distributor, the querier, and the ruler (called `-distributor.shard-by-all-labels` on Querier as well). If the flag is only set on the distributor and not on the querier, you will get incomplete query results because not all ingesters are queried.
101101

102102
**Upgrade notes**: As this flag also makes all queries always read from all ingesters, the upgrade path is pretty trivial; just enable the flag. When you do enable it, you'll see a spike in the number of active series as the writes are "reshuffled" amongst the ingesters, but over the next stale period all the old series will be flushed, and you should end up with much better load balancing. With this flag enabled in the queriers, reads will always catch all the data from all ingesters.
103103

@@ -122,6 +122,8 @@ The KVStore client is used by both the Ring and HA Tracker (HA Tracker doesn't s
122122
The prefix for the keys in the store. Should end with a /. For example with a prefix of foo/, the key bar would be stored under foo/bar.
123123
- `{ring,distributor.ha-tracker}.store`
124124
Backend storage to use for the HA Tracker (consul, etcd, inmemory, multi).
125+
126+
**Warning:** The `inmemory` store will not work correctly with multiple distributors as each distributor can have a different state, causing injestion errors.
125127
- `{ring,distributor.ring}.store`
126128
Backend storage to use for the Ring (consul, etcd, inmemory, memberlist, multi).
127129

docs/configuration/config-file-reference.md

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4307,11 +4307,22 @@ store_gateway_client:
43074307
# CLI flag: -querier.shuffle-sharding-ingesters-lookback-period
43084308
[shuffle_sharding_ingesters_lookback_period: <duration> | default = 0s]
43094309

4310-
# Experimental. Use Thanos promql engine
4311-
# https://github.com/thanos-io/promql-engine rather than the Prometheus promql
4312-
# engine.
4313-
# CLI flag: -querier.thanos-engine
4314-
[thanos_engine: <boolean> | default = false]
4310+
thanos_engine:
4311+
# Experimental. Use Thanos promql engine
4312+
# https://github.com/thanos-io/promql-engine rather than the Prometheus promql
4313+
# engine.
4314+
# CLI flag: -querier.thanos-engine
4315+
[enabled: <boolean> | default = false]
4316+
4317+
# Enable xincrease, xdelta, xrate etc from Thanos engine.
4318+
# CLI flag: -querier.enable-x-functions
4319+
[enable_x_functions: <boolean> | default = false]
4320+
4321+
# Logical plan optimizers. Multiple optimizers can be provided as a
4322+
# comma-separated list. Supported values: default, all, propagate-matchers,
4323+
# sort-matchers, merge-selects, detect-histogram-stats
4324+
# CLI flag: -querier.optimizers
4325+
[optimizers: <string> | default = "default"]
43154326

43164327
# If enabled, ignore max query length check at Querier select method. Users can
43174328
# choose to ignore it since the validation can be done before Querier evaluation
@@ -5028,6 +5039,23 @@ ring:
50285039
# ruler.enable-ha-evaluation is true.
50295040
# CLI flag: -ruler.liveness-check-timeout
50305041
[liveness_check_timeout: <duration> | default = 1s]
5042+
5043+
thanos_engine:
5044+
# Experimental. Use Thanos promql engine
5045+
# https://github.com/thanos-io/promql-engine rather than the Prometheus promql
5046+
# engine.
5047+
# CLI flag: -ruler.thanos-engine
5048+
[enabled: <boolean> | default = false]
5049+
5050+
# Enable xincrease, xdelta, xrate etc from Thanos engine.
5051+
# CLI flag: -ruler.enable-x-functions
5052+
[enable_x_functions: <boolean> | default = false]
5053+
5054+
# Logical plan optimizers. Multiple optimizers can be provided as a
5055+
# comma-separated list. Supported values: default, all, propagate-matchers,
5056+
# sort-matchers, merge-selects, detect-histogram-stats
5057+
# CLI flag: -ruler.optimizers
5058+
[optimizers: <string> | default = "default"]
50315059
```
50325060
50335061
### `ruler_storage_config`

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ require (
5252
github.com/stretchr/testify v1.10.0
5353
github.com/thanos-io/objstore v0.0.0-20250317105316-a0136a6f898d
5454
github.com/thanos-io/promql-engine v0.0.0-20250611170940-015ebeb7b5ff
55-
github.com/thanos-io/thanos v0.39.1
55+
github.com/thanos-io/thanos v0.39.2
5656
github.com/uber/jaeger-client-go v2.30.0+incompatible
5757
github.com/weaveworks/common v0.0.0-20230728070032-dd9e68f319d5
5858
go.etcd.io/etcd/api/v3 v3.5.17
@@ -83,7 +83,7 @@ require (
8383
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
8484
github.com/oklog/ulid/v2 v2.1.1
8585
github.com/parquet-go/parquet-go v0.25.1
86-
github.com/prometheus-community/parquet-common v0.0.0-20250710090957-8fdc99f06643
86+
github.com/prometheus-community/parquet-common v0.0.0-20250716185251-4cfa597e936c
8787
github.com/prometheus/procfs v0.16.1
8888
github.com/sercand/kuberesolver/v5 v5.1.1
8989
github.com/tjhop/slog-gokit v0.1.4

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -814,8 +814,8 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
814814
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
815815
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
816816
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
817-
github.com/prometheus-community/parquet-common v0.0.0-20250710090957-8fdc99f06643 h1:XoOXq+q+CcY8MZqAVoPtdG3R6o84aeZpZFDM+C9DJXg=
818-
github.com/prometheus-community/parquet-common v0.0.0-20250710090957-8fdc99f06643/go.mod h1:zJNGzMKctJoOESjRVaNTlPis3C9VcY3cRzNxj6ll3Is=
817+
github.com/prometheus-community/parquet-common v0.0.0-20250716185251-4cfa597e936c h1:yDtT3c2klcWJj6A0osq72qM8rd1ohtl/J3rHD3FHuNw=
818+
github.com/prometheus-community/parquet-common v0.0.0-20250716185251-4cfa597e936c/go.mod h1:MbAv/yCv9GORLj0XvXgRF913R9Jc04+BvVq4VJpPCi0=
819819
github.com/prometheus-community/prom-label-proxy v0.11.1 h1:jX+m+BQCNM0z3/P6V6jVxbiDKgugvk91SaICD6bVhT4=
820820
github.com/prometheus-community/prom-label-proxy v0.11.1/go.mod h1:uTeQW+wZ/VPV1LL3IPfvUE++wR2nPLex+Y4RE38Cpis=
821821
github.com/prometheus/alertmanager v0.28.1 h1:BK5pCoAtaKg01BYRUJhEDV1tqJMEtYBGzPw8QdvnnvA=
@@ -932,8 +932,8 @@ github.com/thanos-io/objstore v0.0.0-20241111205755-d1dd89d41f97 h1:VjG0mwhN1Dkn
932932
github.com/thanos-io/objstore v0.0.0-20241111205755-d1dd89d41f97/go.mod h1:vyzFrBXgP+fGNG2FopEGWOO/zrIuoy7zt3LpLeezRsw=
933933
github.com/thanos-io/promql-engine v0.0.0-20250611170940-015ebeb7b5ff h1:obQDLbgnae6rLPngWwQ6q/ifQZeDEmVvxHIJ6arJCDs=
934934
github.com/thanos-io/promql-engine v0.0.0-20250611170940-015ebeb7b5ff/go.mod h1:IQjuIvDzOOVE2MGDs88Q65GYmmKrpmIsDkMVOqs5reo=
935-
github.com/thanos-io/thanos v0.39.1 h1:JXFKPgvmf7XohV8ylasxERkRLgxqwbhuu6JkrWIgrio=
936-
github.com/thanos-io/thanos v0.39.1/go.mod h1:bvUPJNIx2LBXme6yBinRiGqQinxlGikLlK7PGeFQPkQ=
935+
github.com/thanos-io/thanos v0.39.2 h1:edN03y7giEc6lD17HJhYcv8ELapXxElmhJnFIYJ2GqQ=
936+
github.com/thanos-io/thanos v0.39.2/go.mod h1:bvUPJNIx2LBXme6yBinRiGqQinxlGikLlK7PGeFQPkQ=
937937
github.com/thanos-io/thanos-prometheus v0.0.0-20250610133519-082594458a88 h1:5uf08MPb6xrVo4rxmBDh9/1SLthbZGY9zLeF3oMixh8=
938938
github.com/thanos-io/thanos-prometheus v0.0.0-20250610133519-082594458a88/go.mod h1:WEq2ogBPZoLjj9x5K67VEk7ECR0nRD9XCjaOt1lsYck=
939939
github.com/tjhop/slog-gokit v0.1.4 h1:uj/vbDt3HaF0Py8bHPV4ti/s0utnO0miRbO277FLBKM=

integration/format_query_api_test.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//go:build requires_docker
2+
// +build requires_docker
3+
4+
package integration
5+
6+
import (
7+
"encoding/json"
8+
"fmt"
9+
"io"
10+
"net/http"
11+
"testing"
12+
13+
"github.com/stretchr/testify/require"
14+
15+
"github.com/cortexproject/cortex/integration/e2e"
16+
e2edb "github.com/cortexproject/cortex/integration/e2e/db"
17+
"github.com/cortexproject/cortex/integration/e2ecortex"
18+
)
19+
20+
func TestFormatQueryAPI(t *testing.T) {
21+
s, err := e2e.NewScenario(networkName)
22+
require.NoError(t, err)
23+
defer s.Close()
24+
25+
// Start dependencies.
26+
consul := e2edb.NewConsul()
27+
minio := e2edb.NewMinio(9000, bucketName)
28+
require.NoError(t, s.StartAndWaitReady(consul, minio))
29+
30+
flags := mergeFlags(BlocksStorageFlags(), map[string]string{
31+
"-auth.enabled": "true",
32+
})
33+
34+
// Start the query-frontend.
35+
queryFrontend := e2ecortex.NewQueryFrontend("query-frontend", flags, "")
36+
require.NoError(t, s.Start(queryFrontend))
37+
38+
querier := e2ecortex.NewQuerier("querier", e2ecortex.RingStoreConsul, consul.NetworkHTTPEndpoint(), mergeFlags(flags, map[string]string{
39+
"-querier.frontend-address": queryFrontend.NetworkGRPCEndpoint(),
40+
}), "")
41+
require.NoError(t, s.StartAndWaitReady(querier))
42+
43+
// Start querier without frontend.
44+
querierDirect := e2ecortex.NewQuerier("querier-direct", e2ecortex.RingStoreConsul, consul.NetworkHTTPEndpoint(), flags, "")
45+
require.NoError(t, s.StartAndWaitReady(querierDirect))
46+
47+
require.NoError(t, s.WaitReady(queryFrontend))
48+
49+
testCases := []struct {
50+
name string
51+
query string
52+
expectedResp string
53+
expectError bool
54+
method string
55+
useOnlyQuerier bool
56+
}{
57+
{
58+
name: "Valid query for GET method",
59+
query: "foo/bar",
60+
expectedResp: "foo / bar",
61+
expectError: false,
62+
method: "GET",
63+
},
64+
{
65+
name: "Valid query for POST method",
66+
query: "foo/bar",
67+
expectedResp: "foo / bar",
68+
expectError: false,
69+
method: "POST",
70+
},
71+
{
72+
name: "Invalid query for GET method",
73+
query: "invalid_expression/",
74+
expectError: true,
75+
method: "GET",
76+
},
77+
{
78+
name: "Invalid query for POST method",
79+
query: "invalid_expression/",
80+
expectError: true,
81+
method: "POST",
82+
},
83+
{
84+
name: "Valid query using only querier (GET)",
85+
query: "foo/bar",
86+
expectedResp: "foo / bar",
87+
expectError: false,
88+
method: "GET",
89+
useOnlyQuerier: true,
90+
},
91+
}
92+
var parsed struct {
93+
Data string `json:"data"`
94+
}
95+
96+
for _, tc := range testCases {
97+
t.Run(tc.name, func(t *testing.T) {
98+
var endpoint string
99+
if tc.useOnlyQuerier {
100+
endpoint = fmt.Sprintf("http://%s/api/prom/api/v1/format_query?query=%s", querierDirect.HTTPEndpoint(), tc.query)
101+
} else {
102+
endpoint = fmt.Sprintf("http://%s/api/prom/api/v1/format_query?query=%s", queryFrontend.HTTPEndpoint(), tc.query)
103+
}
104+
105+
req, err := http.NewRequest(tc.method, endpoint, nil)
106+
req.Header.Set("X-Scope-OrgID", "user-1")
107+
require.NoError(t, err)
108+
109+
resp, err := http.DefaultClient.Do(req)
110+
require.NoError(t, err)
111+
defer resp.Body.Close()
112+
113+
if tc.expectError {
114+
require.NotEqual(t, 200, resp.StatusCode)
115+
return
116+
} else {
117+
require.Equal(t, 200, resp.StatusCode)
118+
}
119+
120+
body, err := io.ReadAll(resp.Body)
121+
require.NoError(t, err)
122+
123+
require.NoError(t, json.Unmarshal(body, &parsed))
124+
require.Equal(t, tc.expectedResp, parsed.Data)
125+
})
126+
}
127+
}

0 commit comments

Comments
 (0)