Skip to content

Commit 356b646

Browse files
committed
add storage wall time to querier stats
Signed-off-by: Ben Ye <[email protected]>
1 parent 2cd304b commit 356b646

File tree

8 files changed

+183
-53
lines changed

8 files changed

+183
-53
lines changed

pkg/frontend/transport/handler.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ func (f *Handler) reportSlowQuery(r *http.Request, queryString url.Values, query
289289

290290
func (f *Handler) reportQueryStats(r *http.Request, userID string, queryString url.Values, queryResponseTime time.Duration, stats *querier_stats.QueryStats, error error, statusCode int, resp *http.Response) {
291291
wallTime := stats.LoadWallTime()
292+
queryStorageWallTime := stats.LoadQueryStorageWallTime()
292293
numSeries := stats.LoadFetchedSeries()
293294
numChunks := stats.LoadFetchedChunks()
294295
numSamples := stats.LoadFetchedSamples()
@@ -356,6 +357,11 @@ func (f *Handler) reportQueryStats(r *http.Request, userID string, queryString u
356357
if priority, ok := stats.LoadPriority(); ok {
357358
logMessage = append(logMessage, "priority", priority)
358359
}
360+
if sws := queryStorageWallTime.Seconds(); sws > 0 {
361+
// Only include query storage wall time field if set. This value can be 0
362+
// for query APIs that don't call `Querier` interface.
363+
logMessage = append(logMessage, "query_storage_wall_time_seconds", sws)
364+
}
359365

360366
if error != nil {
361367
s, ok := status.FromError(error)

pkg/frontend/transport/handler_test.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,16 +326,17 @@ func TestReportQueryStatsFormat(t *testing.T) {
326326
"should include query stats": {
327327
queryStats: &querier_stats.QueryStats{
328328
Stats: querier_stats.Stats{
329-
WallTime: 3 * time.Second,
330-
FetchedSeriesCount: 100,
331-
FetchedChunksCount: 200,
332-
FetchedSamplesCount: 300,
333-
FetchedChunkBytes: 1024,
334-
FetchedDataBytes: 2048,
335-
SplitQueries: 10,
329+
WallTime: 3 * time.Second,
330+
QueryStorageWallTime: 100 * time.Minute,
331+
FetchedSeriesCount: 100,
332+
FetchedChunksCount: 200,
333+
FetchedSamplesCount: 300,
334+
FetchedChunkBytes: 1024,
335+
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 split_queries=10 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 query_storage_wall_time_seconds=6000`,
339340
},
340341
"should include user agent": {
341342
header: http.Header{"User-Agent": []string{"Grafana"}},

pkg/querier/querier.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/cortexproject/cortex/pkg/querier/iterators"
3131
"github.com/cortexproject/cortex/pkg/querier/lazyquery"
3232
seriesset "github.com/cortexproject/cortex/pkg/querier/series"
33+
querier_stats "github.com/cortexproject/cortex/pkg/querier/stats"
3334
"github.com/cortexproject/cortex/pkg/tenant"
3435
"github.com/cortexproject/cortex/pkg/util"
3536
"github.com/cortexproject/cortex/pkg/util/flagext"
@@ -284,10 +285,11 @@ type querier struct {
284285
limiterHolder *limiterHolder
285286
}
286287

287-
func (q querier) setupFromCtx(ctx context.Context) (context.Context, string, int64, int64, storage.Querier, []storage.Querier, error) {
288+
func (q querier) setupFromCtx(ctx context.Context) (context.Context, *querier_stats.QueryStats, string, int64, int64, storage.Querier, []storage.Querier, error) {
289+
stats := querier_stats.FromContext(ctx)
288290
userID, err := tenant.TenantID(ctx)
289291
if err != nil {
290-
return ctx, userID, 0, 0, nil, nil, err
292+
return ctx, stats, userID, 0, 0, nil, nil, err
291293
}
292294

293295
q.limiterHolder.limiterInitializer.Do(func() {
@@ -298,12 +300,12 @@ func (q querier) setupFromCtx(ctx context.Context) (context.Context, string, int
298300

299301
mint, maxt, err := validateQueryTimeRange(ctx, userID, q.mint, q.maxt, q.limits, q.maxQueryIntoFuture)
300302
if err != nil {
301-
return ctx, userID, 0, 0, nil, nil, err
303+
return ctx, stats, userID, 0, 0, nil, nil, err
302304
}
303305

304306
dqr, err := q.distributor.Querier(mint, maxt)
305307
if err != nil {
306-
return ctx, userID, 0, 0, nil, nil, err
308+
return ctx, stats, userID, 0, 0, nil, nil, err
307309
}
308310
metadataQuerier := dqr
309311

@@ -319,23 +321,27 @@ func (q querier) setupFromCtx(ctx context.Context) (context.Context, string, int
319321

320322
cqr, err := s.Querier(mint, maxt)
321323
if err != nil {
322-
return ctx, userID, 0, 0, nil, nil, err
324+
return ctx, stats, userID, 0, 0, nil, nil, err
323325
}
324326

325327
queriers = append(queriers, cqr)
326328
}
327-
return ctx, userID, mint, maxt, metadataQuerier, queriers, nil
329+
return ctx, stats, userID, mint, maxt, metadataQuerier, queriers, nil
328330
}
329331

330332
// Select implements storage.Querier interface.
331333
// The bool passed is ignored because the series is always sorted.
332334
func (q querier) Select(ctx context.Context, sortSeries bool, sp *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet {
333-
ctx, userID, mint, maxt, metadataQuerier, queriers, err := q.setupFromCtx(ctx)
335+
ctx, stats, userID, mint, maxt, metadataQuerier, queriers, err := q.setupFromCtx(ctx)
334336
if err == errEmptyTimeRange {
335337
return storage.EmptySeriesSet()
336338
} else if err != nil {
337339
return storage.ErrSeriesSet(err)
338340
}
341+
startT := time.Now()
342+
defer func() {
343+
stats.AddQueryStorageWallTime(time.Since(startT))
344+
}()
339345

340346
log, ctx := spanlogger.New(ctx, "querier.Select")
341347
defer log.Span.Finish()
@@ -426,12 +432,17 @@ func (q querier) Select(ctx context.Context, sortSeries bool, sp *storage.Select
426432

427433
// LabelValues implements storage.Querier.
428434
func (q querier) LabelValues(ctx context.Context, name string, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) {
429-
ctx, _, _, _, metadataQuerier, queriers, err := q.setupFromCtx(ctx)
435+
ctx, stats, _, _, _, metadataQuerier, queriers, err := q.setupFromCtx(ctx)
430436
if err == errEmptyTimeRange {
431437
return nil, nil, nil
432438
} else if err != nil {
433439
return nil, nil, err
434440
}
441+
startT := time.Now()
442+
defer func() {
443+
stats.AddQueryStorageWallTime(time.Since(startT))
444+
}()
445+
435446
if !q.queryStoreForLabels {
436447
return metadataQuerier.LabelValues(ctx, name, matchers...)
437448
}
@@ -475,12 +486,16 @@ func (q querier) LabelValues(ctx context.Context, name string, matchers ...*labe
475486
}
476487

477488
func (q querier) LabelNames(ctx context.Context, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) {
478-
ctx, _, _, _, metadataQuerier, queriers, err := q.setupFromCtx(ctx)
489+
ctx, stats, _, _, _, metadataQuerier, queriers, err := q.setupFromCtx(ctx)
479490
if err == errEmptyTimeRange {
480491
return nil, nil, nil
481492
} else if err != nil {
482493
return nil, nil, err
483494
}
495+
startT := time.Now()
496+
defer func() {
497+
stats.AddQueryStorageWallTime(time.Since(startT))
498+
}()
484499

485500
if !q.queryStoreForLabels {
486501
return metadataQuerier.LabelNames(ctx, matchers...)

pkg/querier/stats/stats.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,24 @@ func (s *QueryStats) LoadFetchedChunks() uint64 {
184184
return atomic.LoadUint64(&s.FetchedChunksCount)
185185
}
186186

187+
// AddQueryStorageWallTime adds some time to the counter.
188+
func (s *QueryStats) AddQueryStorageWallTime(t time.Duration) {
189+
if s == nil {
190+
return
191+
}
192+
193+
atomic.AddInt64((*int64)(&s.QueryStorageWallTime), int64(t))
194+
}
195+
196+
// LoadQueryStorageWallTime returns current query storage wall time.
197+
func (s *QueryStats) LoadQueryStorageWallTime() time.Duration {
198+
if s == nil {
199+
return 0
200+
}
201+
202+
return time.Duration(atomic.LoadInt64((*int64)(&s.QueryStorageWallTime)))
203+
}
204+
187205
func (s *QueryStats) AddSplitQueries(count uint64) {
188206
if s == nil {
189207
return
@@ -259,6 +277,7 @@ func (s *QueryStats) Merge(other *QueryStats) {
259277
}
260278

261279
s.AddWallTime(other.LoadWallTime())
280+
s.AddQueryStorageWallTime(other.LoadQueryStorageWallTime())
262281
s.AddFetchedSeries(other.LoadFetchedSeries())
263282
s.AddFetchedChunkBytes(other.LoadFetchedChunkBytes())
264283
s.AddFetchedDataBytes(other.LoadFetchedDataBytes())

pkg/querier/stats/stats.pb.go

Lines changed: 95 additions & 36 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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ message Stats {
3131
// The total number of split queries sent after going through all the middlewares.
3232
// It includes the number of requests that might be discarded by the queue.
3333
uint64 split_queries = 9;
34+
// The sum of wall time spent in the querier to fetch and merge data from storage.
35+
google.protobuf.Duration query_storage_wall_time = 10 [(gogoproto.stdduration) = true, (gogoproto.nullable) = false];
3436
}

0 commit comments

Comments
 (0)