-
Notifications
You must be signed in to change notification settings - Fork 103
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
[1/3 header changes][metrics + grpc] Emit metrics for new headers handling behaviour. Hide actual changes under feature flag. #2268
base: dev
Are you sure you want to change the base?
Conversation
2da1be9
to
61a74eb
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev #2268 +/- ##
==========================================
+ Coverage 85.23% 85.29% +0.06%
==========================================
Files 270 272 +2
Lines 15555 15630 +75
==========================================
+ Hits 13258 13332 +74
+ Misses 1876 1875 -1
- Partials 421 423 +2 ☔ View full report in Codecov by Sentry. |
docs/headers-handling.md
Outdated
@@ -0,0 +1,86 @@ | |||
# Headers handling | |||
|
|||
Yarpc has unified API for getting and setting headers. Although implementations may wary |
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.
fixing some typo and grammar: YARPC has a single unified API for getting and setting headers across 3 L7 protocols, although implementations may vary by a lot.
Also it is worth calling out HTTP and gRPC (a HTTP2 protocol) allows multiple key for the same key, which is why [go http|https://pkg.go.dev/net/http#Header] defines the type as map[string][]string
. This is very different from TChannel.
One more thing you can call out is, HTTP/gRPC header is case insensitive, but TChannel header is case sensitive. This is why we have an OriginalHeaders
on the yarpc.CallFromContext(ctx).OriginalHeaders
method.
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.
HTTP and gRPC support multiple values, but yarpc introduces undefined behaviour and uses only one value (https://github.com/yarpc/yarpc-go/blob/dev/transport/grpc/headers.go#L156, https://github.com/yarpc/yarpc-go/blob/dev/transport/http/header.go#L66).
Added these notes to doc.
docs/headers-handling.md
Outdated
|
||
### Inbound - Request (Parsing) | ||
|
||
Predefined list of headers (one header, actually) is read and stripped from the inbound 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.
If it is just one, just phrase as: A single header (list the key) is read and stripped from the inbound 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.
Done
docs/headers-handling.md
Outdated
|
||
Predefined list of headers (one header, actually) is read and stripped from the inbound request. | ||
|
||
All other headers are forwarded as is to an application code. |
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.
All other headers are forwarded as is to the application handler.
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.
Fixed.
docs/headers-handling.md
Outdated
|
||
### Inbound - Response (Writing) | ||
|
||
Attempting to add a header with a name listed as reserved leads to an error "cannot use reserved header key". |
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.
ambiguity: reserved by tchannel or yarpc? Can you call out and add a link if possible
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.
Added clarification and link
docs/headers-handling.md
Outdated
|
||
### Outbound - Response (Parsing) | ||
|
||
Headers with the names listed as reserved are deleted. All other headers are forwarded to an application code as is. |
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.
All other headers are forwarded to the outbound as is.
// IncStripped increments the stripped metric. | ||
func (m *ReservedHeaderMetrics) IncStripped(source, dest string) { | ||
incHeaderMetric(m.strippedVec, source, dest) | ||
} | ||
|
||
// IncError increments the error metric. | ||
func (m *ReservedHeaderMetrics) IncError(source, dest string) { | ||
incHeaderMetric(m.errorVec, source, dest) | ||
} |
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 we need those? If it is only used in IncStripped
, you can just inline there?
func (r *ReservedHeaderReporter) IncStripped() {
incHeaderMetric(r.m.strippedVec, source, dest)
}
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 checked, these calls are inlined by compiler, so we're fine in this regard. And as we're good from performance perspective, I would say, it's nice to have some ownership separation - edge doesn't know about internal structure of ReservedHeaderMetrics. Plus it may be useful one day anyway.
return v | ||
} | ||
|
||
func incHeaderMetric(vector *metrics.CounterVector, source, dest string) { |
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.
incHeaderVecMetric
?
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.
Fixed
@@ -153,9 +168,21 @@ func metadataToTransportRequest(md metadata.MD) (*transport.Request, error) { | |||
request.Encoding = transport.Encoding(getContentSubtype(value)) | |||
} | |||
default: | |||
if isReservedHeaderPrefixV2(header) { | |||
reportStrippedHeader = true |
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.
instead of a true/false value, do you want to use a counter here? Right now, no matter how many violations we have, we already inc by 1.
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 won't change anything, +1 or +10 - it's basically gives no new information.
} | ||
|
||
func assertTuples(t *testing.T, snapshots []metrics.Snapshot, expected []tuple) { | ||
var actual []tuple |
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.
nit: actual := make([]tuple, len(snapshots)*2)
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.
Fixed
m := NewReserveHeaderMetrics(nil, "test") | ||
|
||
m.IncStripped("", "") | ||
m.IncError("", "") |
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.
should you assert something here? If you are testing no panic, you should do assert.NoPanic
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.
Added
61a74eb
to
93a82ba
Compare
93a82ba
to
f7b3c8e
Compare
Currently underlying implementation of headers handling wary significantly from one transport to another (docs/docs/headers-handling.md in this PR). Eventually, in one of the following releases, we want to make behaviour consistent and protective: filter inbound 'rpc-' headers, return error for attempting of 'rpc-' header setting.
Proposed changes are backward incompatible, so to identify the edges that are affected by the future changes, at first stage let's emit metrics.
Metrics: reserved_headers_stripped and reserved_headers_error metrics with "component": "yarpc-header-migration" constant tag and with source and dest variable tags
Part of #2265