Skip to content

Commit

Permalink
Added negative offset check for caching queries
Browse files Browse the repository at this point in the history
Signed-off-by: pawarpranav83 <[email protected]>
  • Loading branch information
pawarpranav83 committed Dec 27, 2023
1 parent a1b1954 commit e310a35
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## master / unreleased
* [BUGFIX] Query Frontend: queries with negative offset should check whether it is cacheable or not #5719
* [CHANGE] Azure Storage: Upgraded objstore dependency and support Azure Workload Identity Authentication. Added `connection_string` to support authenticating via SAS token. Marked `msi_resource` config as deprecating. #5645
* [CHANGE] Store Gateway: Add a new fastcache based inmemory index cache. #5619
* [CHANGE] Index Cache: Multi level cache backfilling operation becomes async. Added `-blocks-storage.bucket-store.index-cache.multilevel.max-async-concurrency` and `-blocks-storage.bucket-store.index-cache.multilevel.max-async-buffer-size` configs and metric `cortex_store_multilevel_index_cache_backfill_dropped_items_total` for number of dropped items. #5661
Expand Down
44 changes: 44 additions & 0 deletions pkg/querier/tripperware/queryrange/results_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ func (s resultsCache) shouldCacheResponse(ctx context.Context, req tripperware.R
if !s.isAtModifierCachable(ctx, req, maxCacheTime) {
return false
}
if !s.isOffsetCachable(ctx, req) {
return false
}

return true
}
Expand Down Expand Up @@ -321,6 +324,47 @@ func (s resultsCache) isAtModifierCachable(ctx context.Context, r tripperware.Re
return atModCachable
}

var negativeOffset = errors.New("negative offset")

// isOffsetCachable returns true if the offset is positive, result is safe to cache.
// and false when offset is negative, result is not cached.
func (s resultsCache) isOffsetCachable(ctx context.Context, r tripperware.Request) bool {
query := r.GetQuery()
if !strings.Contains(query, "offset") {
return true
}
expr, err := parser.ParseExpr(query)
if err != nil {
level.Warn(util_log.WithContext(ctx, s.logger)).Log("msg", "failed to parse query, considering offset as not cachable", "query", query, "err", err)
return false
}

offsetCachable := true
parser.Inspect(expr, func(n parser.Node, _ []parser.Node) error {
switch e := n.(type) {
case *parser.VectorSelector:
if e.OriginalOffset < 0 {
offsetCachable = false
return negativeOffset
}
case *parser.MatrixSelector:
offset := e.VectorSelector.(*parser.VectorSelector).OriginalOffset
if offset < 0 {
offsetCachable = false
return negativeOffset
}
case *parser.SubqueryExpr:
if e.OriginalOffset < 0 {
offsetCachable = false
return negativeOffset
}
}
return nil
})

return offsetCachable
}

func getHeaderValuesWithName(r tripperware.Response, headerName string) (headerValues []string) {
for name, hv := range r.HTTPHeaders() {
if name != headerName {
Expand Down
39 changes: 39 additions & 0 deletions pkg/querier/tripperware/queryrange/results_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,45 @@ func TestShouldCache(t *testing.T) {
input: tripperware.Response(&PrometheusResponse{}),
expected: false,
},
// offset on vector selectors.
{
name: "positive offset on vector selector",
request: &PrometheusRequest{Query: "metric offset 10ms", End: 125000},
input: tripperware.Response(&PrometheusResponse{}),
expected: true,
},
{
name: "negative offset on vector selector",
request: &PrometheusRequest{Query: "metric offset -10ms", End: 125000},
input: tripperware.Response(&PrometheusResponse{}),
expected: false,
},
// offset on matrix selectors.
{
name: "positive offset on matrix selector",
request: &PrometheusRequest{Query: "rate(metric[5m] offset 10ms)", End: 125000},
input: tripperware.Response(&PrometheusResponse{}),
expected: true,
},
{
name: "negative offset on matrix selector",
request: &PrometheusRequest{Query: "rate(metric[5m] offset -10ms)", End: 125000},
input: tripperware.Response(&PrometheusResponse{}),
expected: false,
},
// offset on subqueries.
{
name: "positive offset on subqueries",
request: &PrometheusRequest{Query: "sum_over_time(rate(metric[1m])[10m:1m] offset 10ms)", End: 125000},
input: tripperware.Response(&PrometheusResponse{}),
expected: true,
},
{
name: "negative offset on subqueries",
request: &PrometheusRequest{Query: "sum_over_time(rate(metric[1m])[10m:1m] offset -10ms)", End: 125000},
input: tripperware.Response(&PrometheusResponse{}),
expected: false,
},
} {
{
t.Run(tc.name, func(t *testing.T) {
Expand Down

0 comments on commit e310a35

Please sign in to comment.