Improve Envoy QUICHE logging#15549
Conversation
This PR makes a few small modifications to the Envoy platform implementation of the QUICHE logging code. Performance: conditions are no longer computed in QUICHE_LOG_IF unless the logging level is enabled. Debugging: logs now contain the file, line and function of the caller. Also, it is now possible to control the QUICHE verbosity threshold via an environment variable. Also, QUICHE_CHECH_GT and related macros will print out the value of the compared variables. Signed-off-by: David Schinazi <dschinazi@google.com>
|
Welcome to the Envoy project, and the joys of Envoy CI! While you passed the first hurdle of DCO, non-dictionary-words are as discouraged as enthusiastic spaces, so you'll want to check spelling and push an update. As an aside, there's some way to make Envoy presubmits email you when they succeed or fail which I strongly encourage setting up and adding to our onboarding docs. |
Signed-off-by: David Schinazi <dschinazi@google.com>
danzh2010
left a comment
There was a problem hiding this comment.
Thanks for working on logging improvement!
| explicit QuicLogEmitter(QuicLogLevel level); | ||
| // |file_name| and |function_name| MUST be valid for the lifetime of the QuicLogEmitter. This is | ||
| // guaranteed when passing __FILE__ and __func__. | ||
| explicit QuicLogEmitter(QuicLogLevel level, const char* file_name, int line, |
There was a problem hiding this comment.
No need of explicit in this case.
Can we hard code __FILE__ and __func__ in ~QuicLogEmitter() instead? Then no need to worry about life time.
There was a problem hiding this comment.
explicit is not required when there are multiple arguments, but it's still good practice because it prevents initializer-list construction. The Google style guide explicitly says it's OK either way in this case, and the Envoy one doesn't mention it. Is that OK with you?
__FILE__ and __func__ are expanded by the preprocessor from the caller of the macro that lead to them. We can't hard-code __FILE__ and __func__ in the .cc file because that'll give you that file name and function, as opposed to this macro usage which gives us the actual caller.
There was a problem hiding this comment.
I see. Thanks for explanation!
|
|
||
| using QuicLogLevel = spdlog::level::level_enum; | ||
|
|
||
| static const QuicLogLevel TRACE = spdlog::level::trace; |
There was a problem hiding this comment.
Do we have "QUIC_LOG(TRACE/DEBUG)"?
There was a problem hiding this comment.
We don't, but our code calls GetLogger().set_level() with these values (see QuicPlatformTest for example) so we should cover all possible values.
| QUICHE_IS_LOG_LEVEL_ENABLED_IMPL(WARNING) | ||
| QUICHE_IS_LOG_LEVEL_ENABLED_IMPL(ERROR) | ||
| QUICHE_IS_LOG_LEVEL_ENABLED_IMPL(DFATAL) | ||
| inline bool constexpr IsLogLevelEnabledFATAL() { return true; } |
There was a problem hiding this comment.
It's not obvious why IsLogLevelEnabledFATAL() can't be defined using the macro above?
There was a problem hiding this comment.
Because that wouldn't be constexpr, there's a comment above to that effect - do you have a suggestion for how I could improve the comment?
|
A side request, mind add document about ENVOY_QUICHE_VERBOSITY in source/docs/quiche_integration.md? Maybe add a debug section? |
Signed-off-by: David Schinazi <dschinazi@google.com>
alyssawilk
left a comment
There was a problem hiding this comment.
Hurrah for logging improvements! Code LGTM, mind adding a unit test?
I'd hope TestEnvironment::setEnvVar would work for std::getenv but I'll admit I'm not 100% sure
|
Unfortunately the std::getenv happens when the verbosity levels are first checked, and that happens before test instantiation. I could add a helper for tests but at that point it wouldn't exercise the code path we'd want to exercise. Thoughts? |
alyssawilk
left a comment
There was a problem hiding this comment.
As discussed offline (and proven in your local client) doing a separate test file isn't going to work for this and given this is for debug logging and mainly for us, I'm fine with it as is. Throwing it over to @mattklein123 for non-google pass and in case he has other clever test ideas ;-)
mattklein123
left a comment
There was a problem hiding this comment.
Throwing it over to @mattklein123 for non-google pass and in case he has other clever test ideas ;-)
I can think of two ideas:
- Use bazel to explicitly run a test setting the env var. I don't know off hand whether this would force recompilation or if you can just run the test binary with a new action_env var that wouldn't effect compilation.
- If we think we will never use this in the release build, the other option would be to do what nghttp2 does and just compile all of this out on release, and then on debug you could do something like read the env var for every log line. https://nghttp2.org/documentation/nghttp2_set_debug_vprintf_callback.html
No strong preference but throwing that out there in case either of them appeal to you.
| * In Google QUIC, encodeHeaders()/encodeTrailers() check the buffer size increase on header stream before and after writing headers/trailers. In QuicSession::OnCanWrite(), may drain header stream send buffer, so there we also check send buffer size decrease on header stream. | ||
| * In IETF QUIC, encodeHeaders()/encodeTrailers() check the buffer size increase on the corresponding data stream which is similar to encodeData(). The buffered headers/trailers are only drained via QuicStream::OnCanWrite() so there is no need to check QuicSession::OnCanWrite. | ||
|
|
||
| ### Debugging |
There was a problem hiding this comment.
While you are in here do you mind also documenting the nghttp2 env var? https://github.com/envoyproxy/envoy/blob/main/source/common/http/http2/nghttp2.cc (edit never mind this isn't where you would document nghttp2, but see cross linking comment below)
Would it be worth it to standardize the names a bit also? I don't feel strongly but might be nice.
And finally, if you search fro ENVOY_NGHTTP2_TRACE you will see it's documented a few different places. Might be nice to consolidate and/or cross reference.
There was a problem hiding this comment.
I intentionally picked a slightly different name because ENVOY_NGHTTP2_TRACE is a bool whereas ENVOY_QUICHE_VERBOSITY is an int. What do you think?
I just modified the documentation that referenced ENVOY_NGHTTP2_TRACE to also reference ENVOY_QUICHE_VERBOSITY.
040a437
|
Thanks @mattklein123 ! I think there's value in enabling I'm happy to do what you mentioned:
but I'm not knowledgeable enough in bazel to know how to do this. Do you have another example I can use as inspiration? Alternatively we can say that this debugging feature doesn't need a test given the overhead? |
I'm fine with whatever you and @danzh2010 @alyssawilk decide, but if you want to try with bazel you would use |
mattklein123
left a comment
There was a problem hiding this comment.
Let's merge this and if you want to circle back with a test feel free.
Commit Message:
This PR makes a few small modifications to the Envoy platform
implementation of the QUICHE logging code.
Performance: conditions are no longer computed in QUICHE_LOG_IF
unless the logging level is enabled.
Debugging: logs now contain the file, line and function of the caller.
Also, it is now possible to control the QUICHE verbosity threshold
via an environment variable. Also, QUICHE_CHECH_GT and related macros
will print out the value of the compared variables.
Signed-off-by: David Schinazi dschinazi@google.com
Additional Description: None
Risk Level: Low
Testing: Manual
Docs Changes: None
Release Notes: None
Platform Specific Features: None
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Deprecated:]
[Optional API Considerations:]