Skip to content

Fix snappy/framed-snappy encoding/decoding #12911

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

ArthurSens
Copy link
Member

Description

This is an alternative PR to #12825.

I'm taking all the commits from that PR and adding the feature gate on the client side, as requested by reviews. The server behavior of peeking into the initial bytes to identify the encoding is kept :)

If you've reviewed the previous PR, you can just review the latest commit!

Link to tracking issue

Fixes #10584

@ArthurSens ArthurSens requested a review from a team as a code owner April 22, 2025 21:30
@ArthurSens ArthurSens requested a review from codeboten April 22, 2025 21:30
@ArthurSens
Copy link
Member Author

Hey @skandragon, I took the liberty of continuing your PR just because we're blocked in developing the prometheusremotewritereceiver. I hope that's okay!

cc @bogdandrutu @jade-guiton-dd @perebaj

Copy link

codecov bot commented Apr 22, 2025

Codecov Report

Attention: Patch coverage is 80.37383% with 21 lines in your changes missing coverage. Please review.

Project coverage is 91.61%. Comparing base (07f1863) to head (b7caec7).

Files with missing lines Patch % Lines
config/confighttp/compressor.go 61.29% 9 Missing and 3 partials ⚠️
config/confighttp/compression.go 86.95% 6 Missing and 3 partials ⚠️

❌ Your patch check has failed because the patch coverage (80.37%) is below the target coverage (95.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12911      +/-   ##
==========================================
- Coverage   91.65%   91.61%   -0.05%     
==========================================
  Files         499      499              
  Lines       27426    27492      +66     
==========================================
+ Hits        25138    25186      +48     
- Misses       1809     1822      +13     
- Partials      479      484       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Arthur Silva Sens <[email protected]>
change_type: bug_fix

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: confighttp
Copy link

Choose a reason for hiding this comment

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

Should we say that we are changing both?

Suggested change
component: confighttp
component: confighttp and configcompression

Comment on lines +18 to +29
subtext: |
The collector used the Snappy compression type of "framed" to handle the HTTP
content-encoding "snappy". However, this encoding is typically used to indicate
the "block" compression variant of "snappy". This change allows the collector to:
- When receiving a request with encoding 'snappy', the server endpoints will peek
at the first bytes of the payload to determine if it is "framed" or "block" snappy,
and will decompress accordingly. This is a backwards-compatible change.

If the feature-gate "confighttp.framedSnappy" is enabled, you'll see new behavior for both client and server:
- Client compression type "snappy" will now compress to the "block" variant of snappy
instead of "framed". Client compression type "x-snappy-framed" will now compress to the "framed" variant of snappy.
- Servers will accept both "snappy" and "x-snappy-framed" as valid content-encodings.
Copy link

Choose a reason for hiding this comment

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

Maybe would be nice to add these details here, or just add the new compression type: x-snappy-framed

Comment on lines +47 to +52
// snappyHandler returns an io.ReadCloser that auto-detects the snappy format.
// This is necessary because the collector previously used "content-encoding: snappy"
// but decompressed and compressed the payloads using the snappy framing format.
// However, "content-encoding: snappy" is uses the block format, and "x-snappy-framed"
// is the framing format. This handler is a (hopefully temporary) hack to
// make this work in a backwards-compatible way.
Copy link

Choose a reason for hiding this comment

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

On the original issue, the contributors shared those references:

https://github.com/google/snappy/blob/main/framing_format.txt
https://pkg.go.dev/github.com/golang/snappy#pkg-overview

Maybe add them here on the function comment?

Comment on lines +26 to +29
If the feature-gate "confighttp.framedSnappy" is enabled, you'll see new behavior for both client and server:
- Client compression type "snappy" will now compress to the "block" variant of snappy
instead of "framed". Client compression type "x-snappy-framed" will now compress to the "framed" variant of snappy.
- Servers will accept both "snappy" and "x-snappy-framed" as valid content-encodings.
Copy link
Member

Choose a reason for hiding this comment

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

I think this is not clear about when gate is disabled (default).

Copy link
Member

@bogdandrutu bogdandrutu left a comment

Choose a reason for hiding this comment

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

This LGTM, would like @jade-guiton-dd to review as well.

Copy link
Contributor

@jade-guiton-dd jade-guiton-dd left a comment

Choose a reason for hiding this comment

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

LGTM, just a few nitpicks and questions.

After reviewing the docs for both formats, the protocol-detection and compression logic looks sound to me.

Comment on lines +125 to +134
if enableFramedSnappy.IsEnabled() {
//nolint:unparam // Ignoring the linter request to remove error return since it needs to match the method signature
availableDecoders["x-snappy-framed"] = func(body io.ReadCloser) (io.ReadCloser, error) {
// Lazy Reading content to improve memory efficiency
return &compressReadCloser{
Reader: snappy.NewReader(body),
orig: body,
}, nil
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think it would cause problems either way, but is there a need to put support for the x-snappy-framed format behind the gate?

@@ -141,6 +200,7 @@ func httpContentDecompressor(h http.Handler, maxRequestBodySize int64, eh func(w
errHandler = eh
}

availableDecoders := availableDecoders()
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of rebuilding the map every time we setup a server, I think we could probably put the code of availableDecoders() into an init() function. I don't expect server creation to be a performance bottleneck for anyone though, so I don't think it's a big concern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[confighttp] snappy compress, Encode and NewReader inconsistent behavior
5 participants