Skip to content

Commit 605e1ed

Browse files
authored
Log split queries at query frontend (#5703)
* log split queries at query frontend Signed-off-by: Ben Ye <benye@amazon.com> * update changelog Signed-off-by: Ben Ye <benye@amazon.com> --------- Signed-off-by: Ben Ye <benye@amazon.com>
1 parent 3565a31 commit 605e1ed

File tree

7 files changed

+105
-35
lines changed

7 files changed

+105
-35
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* [ENHANCEMENT] Compactor: Add new compactor metric `cortex_compactor_start_duration_seconds`. #5683
1111
* [ENHANCEMENT] Upgraded Docker base images to `alpine:3.18`. #5684
1212
* [ENHANCEMENT] Index Cache: Multi level cache adds config `max_backfill_items` to cap max items to backfill per async operation. #5686
13+
* [ENHANCEMENT] Query Frontend: Log number of split queries in `query stats` log. #5703
1314

1415
## 1.16.0 2023-11-20
1516

pkg/frontend/transport/handler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ func (f *Handler) reportQueryStats(r *http.Request, userID string, queryString u
294294
numSamples := stats.LoadFetchedSamples()
295295
numChunkBytes := stats.LoadFetchedChunkBytes()
296296
numDataBytes := stats.LoadFetchedDataBytes()
297+
splitQueries := stats.LoadSplitQueries()
297298

298299
// Track stats.
299300
f.querySeconds.WithLabelValues(userID).Add(wallTime.Seconds())
@@ -324,6 +325,7 @@ func (f *Handler) reportQueryStats(r *http.Request, userID string, queryString u
324325
"fetched_samples_count", numSamples,
325326
"fetched_chunks_bytes", numChunkBytes,
326327
"fetched_data_bytes", numDataBytes,
328+
"split_queries", splitQueries,
327329
"status_code", statusCode,
328330
"response_size", contentLength,
329331
}, stats.LoadExtraFields()...)

pkg/frontend/transport/handler_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,11 @@ func TestReportQueryStatsFormat(t *testing.T) {
318318

319319
tests := map[string]testCase{
320320
"should not include query and header details if empty": {
321-
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 status_code=200 response_size=1000`,
321+
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 split_queries=0 status_code=200 response_size=1000`,
322322
},
323323
"should include query length and string at the end": {
324324
queryString: url.Values(map[string][]string{"query": {"up"}}),
325-
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 status_code=200 response_size=1000 query_length=2 param_query=up`,
325+
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 split_queries=0 status_code=200 response_size=1000 query_length=2 param_query=up`,
326326
},
327327
"should include query stats": {
328328
queryStats: &querier_stats.QueryStats{
@@ -333,22 +333,23 @@ func TestReportQueryStatsFormat(t *testing.T) {
333333
FetchedSamplesCount: 300,
334334
FetchedChunkBytes: 1024,
335335
FetchedDataBytes: 2048,
336+
SplitQueries: 10,
336337
},
337338
},
338-
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=3 fetched_series_count=100 fetched_chunks_count=200 fetched_samples_count=300 fetched_chunks_bytes=1024 fetched_data_bytes=2048 status_code=200 response_size=1000`,
339+
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=3 fetched_series_count=100 fetched_chunks_count=200 fetched_samples_count=300 fetched_chunks_bytes=1024 fetched_data_bytes=2048 split_queries=10 status_code=200 response_size=1000`,
339340
},
340341
"should include user agent": {
341342
header: http.Header{"User-Agent": []string{"Grafana"}},
342-
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 status_code=200 response_size=1000 user_agent=Grafana`,
343+
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 split_queries=0 status_code=200 response_size=1000 user_agent=Grafana`,
343344
},
344345
"should include response error": {
345346
responseErr: errors.New("foo_err"),
346-
expectedLog: `level=error msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 status_code=200 response_size=1000 error=foo_err`,
347+
expectedLog: `level=error msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 split_queries=0 status_code=200 response_size=1000 error=foo_err`,
347348
},
348349
"should include query priority": {
349350
queryString: url.Values(map[string][]string{"query": {"up"}}),
350351
header: http.Header{util.QueryPriorityHeaderKey: []string{"99"}},
351-
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 status_code=200 response_size=1000 query_length=2 priority=99 param_query=up`,
352+
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 split_queries=0 status_code=200 response_size=1000 query_length=2 priority=99 param_query=up`,
352353
},
353354
}
354355

pkg/frontend/transport/roundtripper.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88

99
"github.com/weaveworks/common/httpgrpc"
1010
"github.com/weaveworks/common/httpgrpc/server"
11+
12+
querier_stats "github.com/cortexproject/cortex/pkg/querier/stats"
1113
)
1214

1315
// GrpcRoundTripper is similar to http.RoundTripper, but works with HTTP requests converted to protobuf messages.
@@ -39,6 +41,8 @@ func (a *grpcRoundTripperAdapter) RoundTrip(r *http.Request) (*http.Response, er
3941
return nil, err
4042
}
4143

44+
stats := querier_stats.FromContext(r.Context())
45+
stats.AddSplitQueries(1)
4246
resp, err := a.roundTripper.RoundTripGRPC(r.Context(), req)
4347
if err != nil {
4448
return nil, err

pkg/querier/stats/stats.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,22 @@ func (s *QueryStats) LoadFetchedChunks() uint64 {
180180
return atomic.LoadUint64(&s.FetchedChunksCount)
181181
}
182182

183+
func (s *QueryStats) AddSplitQueries(count uint64) {
184+
if s == nil {
185+
return
186+
}
187+
188+
atomic.AddUint64(&s.SplitQueries, count)
189+
}
190+
191+
func (s *QueryStats) LoadSplitQueries() uint64 {
192+
if s == nil {
193+
return 0
194+
}
195+
196+
return atomic.LoadUint64(&s.SplitQueries)
197+
}
198+
183199
// Merge the provided Stats into this one.
184200
func (s *QueryStats) Merge(other *QueryStats) {
185201
if s == nil || other == nil {

pkg/querier/stats/stats.pb.go

Lines changed: 72 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/querier/stats/stats.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ message Stats {
2828
uint64 fetched_samples_count = 7;
2929
// The limit hit when executing the query
3030
string limit_hit = 8 [(gogoproto.nullable) = true];
31+
// The total number of split queries sent after going through all the middlewares.
32+
// It includes the number of requests that might be discarded by the queue.
33+
uint64 split_queries = 9;
3134
}

0 commit comments

Comments
 (0)