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

access log: Add AccessLoggers::Common::ImplBase base class to handle AccessLog::Filter evaluation #7359

Merged
merged 29 commits into from
Jul 16, 2019

Conversation

auni53
Copy link
Contributor

@auni53 auni53 commented Jun 21, 2019

Introduce AccessLoggers::Common::ImplBase in the access_loggers extension to handle converting request/response/trailer HeaderMap pointer-to-reference conversion and evaluation of access log filters. Refactors existing loggers to inherit from the common base class.

Risk Level: Low. No behavior change intended.
Testing: Added unit tests for base class, existing tests suffice for other loggers.
Docs Changes: n/a
Release Notes: n/a
Fixes: #7325

Signed-off-by: Auni Ahsan [email protected]

auni53 added 2 commits June 22, 2019 14:39
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
auni53 added 7 commits June 25, 2019 09:28
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
@auni53 auni53 changed the title (access log) Add AccessLog::maybeLog to handle AccessLog::Filter evaluation (access log) Add AccessLog::InstanceImpl base class to handle AccessLog::Filter evaluation Jun 25, 2019
Copy link
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

I think this is getting pretty close.

include/envoy/access_log/access_log.h Outdated Show resolved Hide resolved
include/envoy/access_log/access_log.h Outdated Show resolved Hide resolved
source/common/access_log/access_log_impl.h Outdated Show resolved Hide resolved
source/common/access_log/access_log_impl.h Outdated Show resolved Hide resolved
@auni53
Copy link
Contributor Author

auni53 commented Jun 28, 2019

Almost ready to put up the Base class, I'm just getting stuck on this stupid CODEOWNERS error when I try to lint myself.

> (cd ~/envoy && ./ci/run_envoy_docker.sh './ci/do_ci.sh fix_format')
No remote cache bucket is set, skipping setup remote cache.
ENVOY_SRCDIR=/source
find: File system loop detected; '/source/.cache/bazel/_bazel_envoybuild/b570b5ccd0454dc9af9f65ab1833764d/external/envoy' is part of the same file system loop as '/source'.
building using 12 CPUs
fix_format...
ERROR: New directory extensions/access_loggers/common appears to not have owners in CODEOWNERS
ERROR: check format failed. run 'tools/check_format.py fix'

I tried adding /*/extensions/access_loggers/common @auni, but no dice.

@zuercher
Copy link
Member

Was looking at this earlier but got sidetracked. I think it’s a bug in the script. If you want to take a look at fixing it, it’d be much appreciated. Otherwise I’ll try to fix it up on Monday.

@zuercher
Copy link
Member

zuercher commented Jul 1, 2019

@auni53 I see the problem. It's not really a bug so much as failure to emit the correct error. Each directory requires two owners. So go ahead and add me as the second one, I guess.

@auni53
Copy link
Contributor Author

auni53 commented Jul 2, 2019

Sorry I was having computer problems, just running the test suite and I'll have an update on this soon.

Signed-off-by: Auni Ahsan <[email protected]>
@auni53
Copy link
Contributor Author

auni53 commented Jul 3, 2019

Ready for more review! I left the log() interface alone but changed emitLog to references. Think I should change the log() function too? (I'd probably do that in a separate PR.) If not, let me know if I should add a .cc as well.

Since I'm not currently changing any base interfaces, do I need release notes?

Signed-off-by: Auni Ahsan <[email protected]>
auni53 added 3 commits July 8, 2019 21:45
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
@auni53
Copy link
Contributor Author

auni53 commented Jul 8, 2019

Sorry for the churn, was trying and failing to clean up the dependency tree. (Envoy unfortunately does not enforce "include what you use".) This is ready for another review round now!

Copy link
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

No worries. Thanks for cleaning up the dependencies.

include/envoy/access_log/access_log.h Outdated Show resolved Hide resolved
source/extensions/filters/http/tap/tap_filter.h Outdated Show resolved Hide resolved
auni53 added 3 commits July 10, 2019 13:45
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
zuercher
zuercher previously approved these changes Jul 10, 2019
Copy link
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

Looks good! Thanks for sticking with this.

I went ahead and updated the PR description (which we'll use as the commit message on merge) to match the PR in this state. Feel free to make edits.

@zuercher zuercher changed the title (access log) Add AccessLog::InstanceImpl base class to handle AccessLog::Filter evaluation access log: Add AccessLoggers::Common::ImplBase base class to handle AccessLog::Filter evaluation Jul 10, 2019
@jmarantz jmarantz self-assigned this Jul 10, 2019
Copy link
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

It seems like this PR is intended to enable sharing of some meaty code that's not shared now. What code is that? Maybe just add that to the PR description?

* @param config the custom configuration for this access log type.
* @param filter filter to determine whether a particular request should be logged. If no filter
* @param config is the custom configuration for this access log type.
* @param filter can determine whether a particular request should be logged. If no filter
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the previous state is more doxygen style at least as used in Envoy; it's not a sentence; it's the arg name followed by a description of the arg. For me, you can resolve this by simply reverting this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, I was trying to be consistent with the rest of the codebase. I had just done a search for @param and found, e.g. in header_map.h, @param key specifies the name of the header to set; it WILL NOT be copied. and @param value specifies the value of the header to set; it WILL be copied.

Not strongly opinionated on this and happy to revert, but the inconsistency is not good.

virtual void log(const Http::HeaderMap* request_headers, const Http::HeaderMap* response_headers,
const Http::HeaderMap* response_trailers,
const StreamInfo::StreamInfo& stream_info) override {
static Http::HeaderMapImpl empty_headers;
Copy link
Contributor

Choose a reason for hiding this comment

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

static non-pod. Can you use a lazy-init?

https://isocpp.org/wiki/faq/ctors#static-init-order

also make it const, which I think will work with evaluate's signature. But I wouldn't want to pass it to something that might modify it if it gets changed in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hah, glad I'm grouping this code in one place. This "static Http::HeaderMapImpl" was in a couple places. Done.

return;
}
return emitLog(*request_headers, *response_headers, *response_trailers, stream_info);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

this seems like too large a function to inline into a .h as a virtual function. Put it into a .cc?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

/**
* Log a completed request if the underlying AccessLog `filter_` allows it.
*/
virtual void log(const Http::HeaderMap* request_headers, const Http::HeaderMap* response_headers,
Copy link
Contributor

Choose a reason for hiding this comment

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

s/virtual//

No need to specify 'virtual' if we have override.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah I'd wanted to give overriders the option to override the log() functionality, but I guess that defeats the point of the whole base class. Done.

Signed-off-by: Auni Ahsan <[email protected]>
@auni53
Copy link
Contributor Author

auni53 commented Jul 11, 2019

Review comments addressed. The shared code isn't meaty but rather sensitive, the "Accesslog::Filter evaluation" mentioned in the PR.

@@ -61,3 +34,30 @@ envoy_cc_library(
"@envoy_api//envoy/config/filter/accesslog/v2:accesslog_cc",
],
)

envoy_cc_library(
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like these 2 stanzas were moved for no reason. Revert? Or at least move them back above access_log_lib so the diffs are easier to see.

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 moved intentionally; access_log_lib is the main dependency people will be consuming so it makes more sense for it to be at the top IMO.

void ImplBase::log(const Http::HeaderMap* request_headers, const Http::HeaderMap* response_headers,
const Http::HeaderMap* response_trailers,
const StreamInfo::StreamInfo& stream_info) {
const Http::HeaderMapImpl empty_headers;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm OK with this but it might be worth it to use a lazy singleton; you just need it to be a const pointer, rather than a non-const value. The reason is that (I believe) HeaderMapImpl is not a trivial ctor and it is better not to have to construct it on every log request.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wrapped this in a ConstSingleton instead.

// Common::ImplBase
void emitLog(const Http::HeaderMap& request_headers, const Http::HeaderMap& response_headers,
const Http::HeaderMap& response_trailers,
const StreamInfo::StreamInfo& stream_info) override;
Copy link
Contributor

Choose a reason for hiding this comment

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

why private? usually override methods should be public or protected.

Copy link
Contributor Author

@auni53 auni53 Jul 15, 2019

Choose a reason for hiding this comment

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

The public interface is in AccessLog::Instance::log(), which calls this overridden emitLog() function. This way logs won't be emitted without a filter evaluation.

Signed-off-by: Auni Ahsan <[email protected]>
@@ -10,15 +11,15 @@ namespace Common {
void ImplBase::log(const Http::HeaderMap* request_headers, const Http::HeaderMap* response_headers,
const Http::HeaderMap* response_trailers,
const StreamInfo::StreamInfo& stream_info) {
const Http::HeaderMapImpl empty_headers;
ConstSingleton<Http::HeaderMapImpl> empty_headers;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's potentially slightly slower to write this using the ConstSingleton abstraction rather than writing it directly because you are potentially calling get() multiple times in the function body., each of which has to do some kind atomic lookup. If you just write the code directly it will only do the atomic update once. But I'm OK with this.

And I guess this method is faster if all three forms of headers is specified, since then the atomic update will not happen at all :)

But my guess is that in most cases there will be response and request headers but no trailers so ithe lookup will happen once, and it'll be a wash :)

@zuercher zuercher merged commit c53b12d into envoyproxy:master Jul 16, 2019
@auni53 auni53 deleted the filter branch July 17, 2019 14:29
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.

Evaluate accesslog filters in Envoy rather than accesslog implementations
3 participants