Skip to content
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

gzip: add stats to filter and fix accept-encoding identity bug #3647

Merged
merged 11 commits into from Jun 20, 2018

Conversation

lita
Copy link

@lita lita commented Jun 17, 2018

gzip filter: add stats to filter and fix accept-encoding identity bug

Description: This PR adds stats to the gzip filter. In the process of adding stats, I noticed a bug where the filter compresses when the Accept-Encoding is set to identity. I believe that goes against the RFC, as no transformation or encoding should happen to the data when "identity" is set. https://tools.ietf.org/html/rfc7231#section-5.3.4

Risk Level: Low

Testing: unit and integration

Docs Changes: Updated the gzip filter docs to clarify the behavior with identity and added more details with q=0.

Release Notes: Added a change to the release notes as this is user impacting.

Lita Cho added 3 commits June 17, 2018 01:13
Signed-off-by: Lita Cho <lcho@lyft.com>
Signed-off-by: Lita Cho <lcho@lyft.com>
Signed-off-by: Lita Cho <lcho@lyft.com>
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thank you! Generally looks great. Some comments to get started then will take another pass.

that the "gzip" will have a higher weight then "\*". For example, if *accept-encoding*
is "gzip;q=0,\*;q=1", the filter will not compress. But if the header is set to
"\*;q=0,gzip;q=1", the filter will compress.
- A request includes *accept-encoding* header includes "identity".
Copy link
Member

Choose a reason for hiding this comment

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

s/includes/whose value is ?

@@ -39,9 +39,14 @@ response and request allow.
By *default* compression will be *skipped* when:
Copy link
Member

Choose a reason for hiding this comment

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

Please add documentation for all the stats that you added. See other doc examples for how we do this.

Copy link
Author

Choose a reason for hiding this comment

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

done.

@@ -36,6 +35,7 @@ Version history
* debug: added symbolized stack traces (where supported)
* grpc: support added for the full set of :ref:`Google gRPC call credentials
<envoy_api_msg_core.GrpcService.GoogleGrpc.CallCredentials>`.
* gzip filter: sending accept-encoding header as identity no longer compresses the payload.
Copy link
Member

Choose a reason for hiding this comment

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

nit: italicize both accept-encoding and identity. Also mention new stats.

bool disable_on_etag_header_;
bool remove_accept_encoding_header_;
const std::string stats_prefix_;
Stats::Scope& scope_;
Copy link
Member

Choose a reason for hiding this comment

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

Instead of storing the scope here, you actually want to create the stats object in the config instead of the filter, and the return that on request. See other similar examples in other filters.

Copy link
Author

Choose a reason for hiding this comment

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

oh got it. didn't see this until now.

@@ -123,16 +128,20 @@ Http::FilterHeadersStatus GzipFilter::encodeHeaders(Http::HeaderMap& headers, bo
headers.insertContentEncoding().value(Http::Headers::get().ContentEncodingValues.Gzip);
compressor_.init(config_->compressionLevel(), config_->compressionStrategy(),
config_->windowBits(), config_->memoryLevel());
} else {

Copy link
Member

Choose a reason for hiding this comment

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

nit: del newline

compressor_.compress(data, end_stream ? Compressor::State::Finish : Compressor::State::Flush);
stats_.total_compressed_bytes_.add(data.length());
stats_.compressed_.inc();
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 the compressed stat would be more useful if it were per-request, not per data frame similar to not_compressed?

Copy link
Author

Choose a reason for hiding this comment

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

Yea, Jose and I thought that the delta per data frame would be good enough, but happy to change it to per request. if you have a good example of how to do that, that would be awesome.

Copy link
Member

Choose a reason for hiding this comment

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

I would probably just invert the logic such that when you know that you are not "not compressing" you would increment the compressing stat. Not sure of the best way of doing that since I haven't looked at the filter code in detail, but I'm sure you can sort something out.

Copy link
Author

Choose a reason for hiding this comment

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

sounds good.

Copy link
Author

@lita lita Jun 18, 2018

Choose a reason for hiding this comment

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

ah nvm, i see what you mean. Yup. will fix to move this into the encodeHeaders

@@ -191,15 +217,23 @@ bool GzipFilter::isContentTypeAllowed(Http::HeaderMap& headers) const {
}

bool GzipFilter::isEtagAllowed(Http::HeaderMap& headers) const {
return !(config_->disableOnEtagHeader() && headers.Etag());
bool isEtagAllowed = !(config_->disableOnEtagHeader() && headers.Etag());
Copy link
Member

Choose a reason for hiding this comment

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

nit: all variables snake_case. There are other examples in the PR, please audit. Also, this var can be const bool. Also other similar examples for this, please audit.

Copy link
Author

Choose a reason for hiding this comment

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

Ah yeah. Copy paste fail. Will fix.

Lita Cho added 3 commits June 18, 2018 13:40
Signed-off-by: Lita Cho <lcho@lyft.com>
Signed-off-by: Lita Cho <lcho@lyft.com>
Signed-off-by: Lita Cho <lcho@lyft.com>
@mattklein123 mattklein123 self-assigned this Jun 19, 2018
Lita Cho added 3 commits June 18, 2018 22:05
Signed-off-by: Lita Cho <lcho@lyft.com>
Signed-off-by: Lita Cho <lcho@lyft.com>
Signed-off-by: Lita Cho <lcho@lyft.com>
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thanks, some more nits.

@@ -163,19 +170,36 @@ bool GzipFilter::isAcceptEncodingAllowed(Http::HeaderMap& headers) const {
const auto q_value = StringUtil::trim(StringUtil::cropLeft(token, ";"));
// If value is the gzip coding, check the qvalue and return.
if (value == Http::Headers::get().AcceptEncodingValues.Gzip) {
return !StringUtil::caseCompare(q_value, ZeroQvalueString);
bool is_gzip = !StringUtil::caseCompare(q_value, ZeroQvalueString);
Copy link
Member

Choose a reason for hiding this comment

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

nit: const

@@ -191,15 +215,23 @@ bool GzipFilter::isContentTypeAllowed(Http::HeaderMap& headers) const {
}

bool GzipFilter::isEtagAllowed(Http::HeaderMap& headers) const {
return !(config_->disableOnEtagHeader() && headers.Etag());
bool is_etag_allowed = !(config_->disableOnEtagHeader() && headers.Etag());
Copy link
Member

Choose a reason for hiding this comment

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

nit: const

}

bool GzipFilter::isMinimumContentLength(Http::HeaderMap& headers) const {
const Http::HeaderEntry* content_length = headers.ContentLength();
if (content_length) {
uint64_t length;
return StringUtil::atoul(content_length->value().c_str(), length) &&
length >= config_->minimumLength();
bool is_minimum_content_length = StringUtil::atoul(content_length->value().c_str(), length) &&
Copy link
Member

Choose a reason for hiding this comment

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

nit: const

@@ -18,14 +19,43 @@ namespace Extensions {
namespace HttpFilters {
namespace Gzip {

/**
* All gzip filter stats. @see stats_macros.h
* Note that the total_bytes is only if the response
Copy link
Member

Choose a reason for hiding this comment

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

This comment is hard to understand. Rephrase?

@@ -35,6 +65,8 @@ class GzipFilterConfig {
}

Runtime::Loader& runtime() { return runtime_; }
GzipStats& stats() { return stats_; }
const std::string stats_prefix() { return stats_prefix_; }
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is needed anymore

compressed, Counter, Number of requests compressed.
not_compressed, Counter, Number of requests not compressed.
no_accept_header, Counter, Number of requests with no accept header sent.
header_identity, Counter, Number of requests sent with the "identity" set as the *accept-encoding*.
Copy link
Member

Choose a reason for hiding this comment

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

"with the" -> "with", same elsewhere where applicable

Lita Cho added 2 commits June 19, 2018 16:47
Signed-off-by: Lita Cho <lcho@lyft.com>
Signed-off-by: Lita Cho <lcho@lyft.com>
@lita
Copy link
Author

lita commented Jun 20, 2018

@mattklein123 this is ready for another look.

Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

nice, well done

@mattklein123 mattklein123 merged commit 08ba248 into envoyproxy:master Jun 20, 2018
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.

None yet

2 participants