-
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
golang: allow accessing {request,response}/{headers,trailer} in the OnLog phase #34810
Conversation
CC @doujiang24 |
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.
There is a related issute #33873 to get headers at any stage, but I'm not against to get header in log phase for now.
is_golang_processing_log_ = true; | ||
dynamic_lib_->envoyGoFilterOnHttpLog(req_, int(log_context.accessLogType())); | ||
is_golang_processing_log_ = false; | ||
decoding_state_.setFilterState(FilterState::ProcessingLog); |
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.
we'd better not overwrite the state?
Processing Log and Process DecodeXXX/EncodeXXX may run concurrently in Golang side.
use another flag, is_golang_processing_log_
, could be much clear, thoughts?
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.
@doujiang24
What about adding a pair of new methods:
- setProcessingLog
- isProcessingLog
So we can check if we are processing Go in the instance of ProcessorState.
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.
Do you mean still write the logging state into decoding/encoding_state
?
I don't think it is a good idea, logging state does not belongs to decoding/encoding
, it would be some kind of hacky and make the code a bit complicated.
A new flag could be much clear.
}, | ||
} | ||
|
||
var reqTrailer *requestTrailerMapImpl |
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.
var reqTrailer *requestTrailerMapImpl | |
var reqTrailer RequestTrailerMap |
it will be nil as default value, so that we do not need those lines start at line 354?
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.
@doujiang24
Thanks, updated.
@@ -276,16 +284,97 @@ func envoyGoFilterOnHttpLog(r *C.httpRequest, logType uint64) { | |||
|
|||
v := api.AccessLogType(logType) | |||
|
|||
// Request headers must exist because the HTTP filter won't be run if the headers are | |||
// not sent yet. | |||
reqHeader := &requestHeaderMapImpl{ |
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.
better add a TODO commet: it's better to make it readonly?
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.
Updated.
/wait |
Getting headers at any stage is well but it requires an extra event loop to fetch the headers from the Envoy, which will add ~100 microseconds. So using it in the per-request hot path is not a good choice. |
Getting request info in the log phase is a common requirement in API Gateway, for example, nearly 15% plugins of APISIX use this feature. So it would be better to avoid ~200 microseconds of extra latency (from both req and resp headers). |
Forget this, it's my mistake. Getting headers in the log phase doesn't require an extra event loop because the OnLog can't be run nonblockingly. |
case api.AccessLogDownstreamEnd: | ||
f.OnLog() | ||
f.OnLog(reqHeader, reqTrailer, respHeader, respTrailer) |
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.
How about use the Envoy C++ API style:
OnLog(logContext)
OnLogDownstreamPeriodic(logContext)
OnLogDownstreamStart(logContext)
type logContext interface {
requestHeaders() RequestHeaderMap
...
}
benifits:
- we do not need to pre create four interface values even people won't use it. (we do only need one instead)
- API fexible, we can add more APIs into logContext in the feature.
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.
@doujiang24
I wonder how to connect this with the goal in #33873.
If we add the methods in the logContext, then we will have two different implementations to get request headers:
one can only use in OnLog phase and the other is used in the Encode phase.
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 is just API style suggestion, no relation to #33873.
The implementations could keep the same as now, just user face API tweaks.
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.
@doujiang24
It's not just user face API tweaks. It also affects how we implement it internally. If we bind the requestHeaders to the logContext, then we need to get the header from the logContext, which is unavailable in Encode phases. However, if we decide to support RequestHeaders in StreamInfo, and now we have two FilterCallbacks, we will probably fetch the headers from the XXFilterCallback directly.
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 is my thought:
- save the all of the parameters into
logContext
, i.e.decodingState
,encodingState
... - create a
RequestHeaderMap
inlogContext.requestHeaders
, and etc.
we do not need any C/cgo related changes, just Go code tweaks, thoughts?
This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
@doujiang24 We could not copy the States simply, as we may run both the encode header or something similar and the log phase, it could be not very clear to share the same state as they may affect each other. For example, they should use different phases to indicate which one is called. |
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.
otherwise, lgtm
return | ||
} | ||
|
||
reqHeader.Set("a", "b") |
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.
we'd better not write header in test? we comment they will be readonly: https://github.com/envoyproxy/envoy/pull/34810/files#r1648874832
uint64_t resp_trailer_num = 0; | ||
uint64_t resp_trailer_bytes = 0; | ||
|
||
auto decoding_s = dynamic_cast<processState*>(&decoding_state_); |
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.
style: decoding_state could be better.
@@ -266,7 +266,13 @@ func envoyGoFilterOnHttpData(s *C.processState, endStream, buffer, length uint64 | |||
} | |||
|
|||
//export envoyGoFilterOnHttpLog | |||
func envoyGoFilterOnHttpLog(r *C.httpRequest, logType uint64) { | |||
func envoyGoFilterOnHttpLog(r *C.httpRequest, logType uint64, | |||
decodingS *C.processState, encodingS *C.processState, |
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.
style: decodingState could be better.
/retest |
@spacewander The DCO failure should be fixed, https://github.com/envoyproxy/envoy/pull/34810/checks?check_run_id=28445721402 |
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.
lgtm
…nLog phase Signed-off-by: spacewander <[email protected]>
@doujiang24 |
/retest |
The failed test, |
/retest |
…nLog phase (envoyproxy#34810) Signed-off-by: spacewander <[email protected]> Signed-off-by: asingh-g <[email protected]>
…nLog phase (envoyproxy#34810) Signed-off-by: spacewander <[email protected]>
…nLog phase (envoyproxy#34810) Signed-off-by: spacewander <[email protected]> Signed-off-by: duxin40 <[email protected]>
Commit Message: allow accessing {request,response}/{headers,trailer} in the OnLog phase
Additional Description:
Risk Level: Low
Testing: Integration
Docs Changes:
Release Notes: Done
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]