-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Conversation
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
…aderMap& 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]>
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
There was a problem hiding this 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.
Almost ready to put up the Base class, I'm just getting stuck on this stupid CODEOWNERS error when I try to lint myself.
I tried adding |
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. |
@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. |
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
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]>
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]>
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]>
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
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! |
There was a problem hiding this 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.
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
There was a problem hiding this 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.
There was a problem hiding this 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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); | ||
} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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]>
Review comments addressed. The shared code isn't meaty but rather sensitive, the "Accesslog::Filter evaluation" mentioned in the PR. |
Signed-off-by: Auni Ahsan <[email protected]>
Signed-off-by: Auni Ahsan <[email protected]>
@@ -61,3 +34,30 @@ envoy_cc_library( | |||
"@envoy_api//envoy/config/filter/accesslog/v2:accesslog_cc", | |||
], | |||
) | |||
|
|||
envoy_cc_library( |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 :)
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]