Skip to content

add zstd and snappy compression for query api #6848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 29, 2025

Conversation

afhassan
Copy link
Contributor

@afhassan afhassan commented Jun 27, 2025

What this PR does:

  • Add Snappy and Zstd compression for querier -> QFE responses.
  • Use a new internal http header X-Uncompressed-Length to enforce QFE response size limit before decompressing response

Which issue(s) this PR fixes:
Fixes #

Checklist

  • Tests updated
  • Documentation added
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]

@afhassan afhassan marked this pull request as ready for review July 9, 2025 23:20
Copy link
Contributor

@erlan-z erlan-z left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added small nit, but overall looks good to me.
Thanks.

@afhassan
Copy link
Contributor Author

@yeya24 @SungJin1212 could someone take a look when you have some time? Thanks!

@SungJin1212
Copy link
Member

SungJin1212 commented Jul 25, 2025

@afhassan
Thanks for the contribution. The code looks nice. Can you add an e2e test?
I think it would be good to add tests to TestQuerierResponseCompression.

@afhassan
Copy link
Contributor Author

afhassan commented Jul 26, 2025

@SungJin1212 Thanks for the review, I added unit tests and an integration test for compression. The change done to QFE response size limit is already covered by this test https://github.com/afhassan/cortex/blob/master/integration/query_frontend_test.go#L977

@@ -102,8 +110,23 @@ func (c instantQueryCodec) DecodeResponse(ctx context.Context, r *http.Response,
return nil, err
}

responseSize := 0
responseSizeHeader := r.Header.Get("X-Uncompressed-Length")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change means that we need a two phase deployment for querier to return this header for Query Frontend to properly apply the response size limit. Otherwise, the value is 0.

I think we should find a way (maybe a flag) to properly maintain the previous behavior during rollout.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't quite get it, do you mean during deployment if Query Frontend is updated first then the limit wouldn't apply because the header is not being returned from Querier?

The old behaviour only works for gzip which is why I changed it. I can reverse it to use the old behaviour when gzip is used and the new one for other compression types.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. If we use gzip then this limiter won't work until Querier is updated, which is a breaking behavior.

We just need a way to fallback to the old behavior if it is gzip. Other types are fine since they are new

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If header is missing we now fallback to applying limit using size of the response after decoding it. I think this is a cleaner way to still apply the limit and avoid a breaking change if the header is not there.

Applying the limit before decoding response was an optimization in the old behaviour, but I don't think it is considered breaking if we are still applying the limit.

Copy link
Contributor

@yeya24 yeya24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's fix changelog conflict and then we can merge

afhassan and others added 2 commits July 28, 2025 20:08
Signed-off-by: Ahmed Hassan <[email protected]>
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Jul 29, 2025
@yeya24 yeya24 merged commit 49099a3 into cortexproject:master Jul 29, 2025
17 checks passed
rubywtl pushed a commit to rubywtl/cortex that referenced this pull request Jul 30, 2025
* add zstd and snappy compression for query api

Signed-off-by: Ahmed Hassan <[email protected]>

* parse X-Uncompressed-Length only if header exists

Signed-off-by: Ahmed Hassan <[email protected]>

* fix formatting

Signed-off-by: Ahmed Hassan <[email protected]>

* refactor query decompression

Signed-off-by: Ahmed Hassan <[email protected]>

* ensure zstd reader is closed after decompression

Signed-off-by: Ahmed Hassan <[email protected]>

* add tests for zstd and snappy compression

Signed-off-by: Ahmed Hassan <[email protected]>

* update changelog

Signed-off-by: Ahmed Hassan <[email protected]>

* update docs

Signed-off-by: Ahmed Hassan <[email protected]>

* apply query response size limit after decompression if header is missing

Signed-off-by: Ahmed Hassan <[email protected]>

* fix formatting

Signed-off-by: Ahmed Hassan <[email protected]>

---------

Signed-off-by: Ahmed Hassan <[email protected]>
Signed-off-by: Ahmed Hassan <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/querier lgtm This PR has been approved by a maintainer size/L
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants