-
Notifications
You must be signed in to change notification settings - Fork 273
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
Add traceparent header parsing for w3c tracecontext #2179
Conversation
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Update:Added a unit test, refactored logic to make everything look a bit neater. Tested again (attached screenshot at the bottom of the post). Should be ready for review. Testing:Need:
Emojivoto needs to be built using
Emojivoto manifestsNote: pods and namespace have different names because I wanted to run it in parallel with emojivoto to see diff in spans generated. apiVersion: v1
kind: Namespace
metadata:
name: votoemoji
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: emoji
namespace: votoemoji
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: voting
namespace: votoemoji
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: web
namespace: votoemoji
---
apiVersion: v1
kind: Service
metadata:
name: emoji-svc
namespace: votoemoji
spec:
ports:
- name: grpc
port: 8080
targetPort: 8080
- name: prom
port: 8801
targetPort: 8801
selector:
app: emoji-svc
---
apiVersion: v1
kind: Service
metadata:
name: voting-svc
namespace: votoemoji
spec:
ports:
- name: grpc
port: 8080
targetPort: 8080
- name: prom
port: 8801
targetPort: 8801
selector:
app: voting-svc
---
apiVersion: v1
kind: Service
metadata:
name: web-svc
namespace: votoemoji
spec:
ports:
- name: http
port: 80
targetPort: 8080
selector:
app: web-svc
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: emoji
app.kubernetes.io/part-of: votoemoji
app.kubernetes.io/version: v12
name: emoji
namespace: votoemoji
spec:
replicas: 1
selector:
matchLabels:
app: emoji-svc
version: v12
template:
metadata:
labels:
app: emoji-svc
version: v12
spec:
containers:
- env:
- name: GRPC_PORT
value: "8080"
- name: PROM_PORT
value: "8801"
imagePullPolicy: IfNotPresent
image: docker.io/buoyantio/emojivoto-emoji-svc:v12
name: emoji-svc
ports:
- containerPort: 8080
name: grpc
- containerPort: 8801
name: prom
resources:
requests:
cpu: 100m
serviceAccountName: emoji
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: vote-bot
app.kubernetes.io/part-of: votoemoji
app.kubernetes.io/version: v12
name: vote-bot
namespace: votoemoji
spec:
replicas: 1
selector:
matchLabels:
app: vote-bot
version: v12
template:
metadata:
labels:
app: vote-bot
version: v12
spec:
containers:
- command:
- emojivoto-vote-bot
env:
- name: WEB_HOST
value: web-svc.votoemoji:80
image: docker.io/buoyantio/emojivoto-web:v12
imagePullPolicy: IfNotPresent
name: vote-bot
resources:
requests:
cpu: 10m
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: voting
app.kubernetes.io/part-of: votoemoji
app.kubernetes.io/version: v12
name: voting
namespace: votoemoji
spec:
replicas: 1
selector:
matchLabels:
app: voting-svc
version: v12
template:
metadata:
labels:
app: voting-svc
version: v12
spec:
containers:
- env:
- name: GRPC_PORT
value: "8080"
- name: PROM_PORT
value: "8801"
image: docker.io/buoyantio/emojivoto-voting-svc:v12
imagePullPolicy: IfNotPresent
name: voting-svc
ports:
- containerPort: 8080
name: grpc
- containerPort: 8801
name: prom
resources:
requests:
cpu: 100m
serviceAccountName: voting
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: web
app.kubernetes.io/part-of: votoemoji
app.kubernetes.io/version: v12
name: web
namespace: votoemoji
spec:
replicas: 1
selector:
matchLabels:
app: web-svc
version: v12
template:
metadata:
labels:
app: web-svc
version: v12
spec:
containers:
- env:
- name: WEB_PORT
value: "8080"
- name: EMOJISVC_HOST
value: emoji-svc.votoemoji:8080
- name: VOTINGSVC_HOST
value: voting-svc.votoemoji:8080
- name: INDEX_BUNDLE
value: dist/index_bundle.js
image: docker.io/buoyantio/emojivoto-web:v12
imagePullPolicy: IfNotPresent
name: web-svc
ports:
- containerPort: 8080
name: http
resources:
requests:
cpu: 100m
serviceAccountName: web Once proxy branch is built, namespace can be annotated with RFC DiffSome handling of the traceparent version is not present in this PR. I can make the changes, I thought we should limit mutations as much as possible -- also, if an invalid version is parsed, according to the spec we'd have to reset the header values, which means the proxy would function as a root span. If something is not formatted correctly I opted to instead not include the traceparent header at all. e.g
This is not a case we're currently handling. Full RFC processing suggestion can be found here: https://www.w3.org/TR/trace-context-1/#a-traceparent-is-received |
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 great! Couple of tiny suggestions.
Signed-off-by: Matei David <[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.
Should we start splitting this module into submodules? It seems like a w3c
module would be appropriate, for instance.
…crement Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Split everything into submodules. I declared the modules in Also, changed one big assumption. Whenever flags cannot be parsed we invalidate the whole trace. According to the spec, flags are optional (meaning a 0 is sent instead?). If a traceparent cannot be parsed (i.e bad version, or bad id) we invalidate it. Flags shouldn't be any different, we shouldn't hint at what the flags should be (by setting it to 0 if it can't be hex decoded or if it's missing). So we simply fail. |
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 looks good to me! i commented on some small style suggestions, but no blockers in my book!
use super::{decode_id_with_padding, get_header_str, Propagation, TraceContext}; | ||
use crate::{Flags, Id}; | ||
|
||
pub const HTTP_TRACEPARENT: &str = "traceparent"; |
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, take it or leave it: it might be a little bit nicer to use HeaderName::from_static
here, because this would perform the validation that the string only contains valid header characters a single time, rather than repeating it every time we convert the &str
into a HeaderName
(which currently occurs every time it's used to access a HeaderMap
):
pub const HTTP_TRACEPARENT: &str = "traceparent"; | |
pub const HTTP_TRACEPARENT: http::HeaderName = http::HeaderName::from_static("traceparent"); |
we may want to do this for the b3 headers as well, but I didn't leave a comment on that because that code was already here.
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.
Bit besides the point but is the http
crate used only for the types, basically? I thought hyper would have its own internal types to deal with requests and headers. I guess they're all just re-exports tho?
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 http
crate contains core types like requests, headers, etc. Similarly, the Body
trait is in the http_body
crate Hyper uses those types (and reexports them for convenience). This allows these crates to have narrower public APIs so they can reach stability quicker/independently from the rest of Hyper. It also means we can depend on core types in libraries without exposing hyper as part of a public interface (which would influence stability/semver).
if let Result::Ok(hv) = HeaderValue::from_str(&new_header) { | ||
request.headers_mut().insert(HTTP_TRACEPARENT, hv); | ||
} else { | ||
warn!("invalid value {} for tracecontext header", new_header); | ||
} |
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.
also, i wonder if the warning ought to include the error returned by HeaderValue::from_str
?
if let Result::Ok(hv) = HeaderValue::from_str(&new_header) { | |
request.headers_mut().insert(HTTP_TRACEPARENT, hv); | |
} else { | |
warn!("invalid value {} for tracecontext header", new_header); | |
} | |
match HeaderValue::from_str(&new_header) | |
Ok(hv) => request.headers_mut().insert(HTTP_TRACEPARENT, hv), | |
Err(error) => warn!("invalid value {new_header} for tracecontext header: {error}"), | |
} |
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.
Compiler will complain because we're not return an Option from the second branch. I wonder if that's why we used the if let
syntax instead of a match? Do you know if we can somehow ignore the return types in the match arms?
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.
Also, had to change everything to be static
and we're passing references now. Compiler yells otherwise for moving out of static item (which I guess makes lots of sense).
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[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'm cutting my review short for time, but I think we need to take a thoughtful pass at the logs here:
- Are they consistent?
- Are INFO+ logs informative/actionable to users?
- My hunch is that most of the warns should be debugs...
if let Result::Ok(hv) = HeaderValue::from_str(&bytes_b64) { | ||
request.headers_mut().insert(&GRPC_TRACE_HEADER, hv); | ||
} else { | ||
warn!("invalid header: {:?}", &bytes_b64); |
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 should be consistent about log formatting. Specifically, i think all of our log messages should be capitalized (this file seems to have a mix of cases).
warn!("invalid header: {:?}", &bytes_b64); | |
warn!("Invalid header: {:?}", &bytes_b64); |
Furthermore, what would a user do if they saw this warning? Is it going to be informative enough for them to act on?
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.
(FWIW, I believe this code was already here and this PR just moved it into a new module)
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 not sure if it's informative enough to act on without context around what is happening. It's not immediately clear that the header value is invalid because it's not a visible ASCII character, or that this is a value we are trying to set (as opposed to erroring out when reading the header from the inbound request).
I think this one in particular is a bit tricky. The conversion from &str
to HeaderValue
may fail only if the string does not contain visible ASCII codes (32 - 127). Since we encode the value using base64 (and that operation is infallible), we kind of have a guarantee that the value will be valid (b64 uses a subset of 32-127 afaik). I'm pretty sure this operation is infallible so we wouldn't actually see this warn message (in which case it'd be better to just delete and add a comment?). The same logic should apply to any header value that is hex encoded. If hex encoding is successful, we will only use a-f
and 0-9
(potentially -
too), all of which are visible ASCII characters.
For now, I'll update the message and level. Something like debug!(%header_value, %header, "Header value contains invalid ASCII characters")
. I think printing the header (as well as the value) will give more contextual information on where the error is cropping up. We can only fail with invisible ascii characters. Alternatively, we could use map_err
to log the error itself.
Since imo the operation is infallible, I'd just simplify everything to:
HeaderValue::from_str(&bytes_b64).ok().and_then(|hv| request.headers_mut.insert(GRPC_TRACE_HEADER, hv))
I don't want to modify too much of the existing codebase so it seemed more sensible to discuss this with both of you first.
if let Ok(hv) = HeaderValue::from_str(&span_str) { | ||
request.headers_mut().insert(&HTTP_SPAN_ID_HEADER, hv); | ||
} else { | ||
warn!("invalid {HTTP_SPAN_ID_HEADER} header: {span_str:?}"); |
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.
similarly
pub fn increment_http_span_id<B>(request: &mut http::Request<B>) -> Id { | ||
let span_id = Id::new_span_id(&mut thread_rng()); | ||
|
||
trace!("incremented span id: {span_id}"); |
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.
trace!("incremented span id: {span_id}"); | |
trace!("Incremented span id: {span_id}"); |
get_header_str(request, &GRPC_TRACE_HEADER) | ||
.and_then(|header_str| { | ||
base64::decode(header_str) | ||
.map_err(|e| warn!("trace header {GRPC_TRACE_HEADER} is not base64 encoded: {e}")) |
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.
.map_err(|e| warn!("trace header {GRPC_TRACE_HEADER} is not base64 encoded: {e}")) | |
.map_err(|e| warn!("{GRPC_TRACE_HEADER} is not base64 encoded: {e}")) |
Looking at https://docs.rs/base64/latest/src/base64/decode.rs.html#10-28, I'm skeptical that the error messages we have here are useful to users.
if let Result::Ok(hv) = HeaderValue::from_str(&bytes_b64) { | ||
request.headers_mut().insert(&GRPC_TRACE_HEADER, hv); | ||
} else { | ||
warn!("invalid header: {:?}", &bytes_b64); |
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.
(FWIW, I believe this code was already here and this PR just moved it into a new module)
Signed-off-by: Matei David <[email protected]>
… b3 libs Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Signed-off-by: Matei David <[email protected]>
Thanks for the suggestions! I went through the new and existing code and tried my best to make the log messages a bit more descriptive and useful to our users. I mainly thought of what I would find useful if I were to debug a trace propagation issue.
Let me know if this looks better and I'm on the right path 🙏🏻 |
This release includes many internal changes to prepare for the new client policy API. Stack metric label values have changed to reflect the new shape of the outbound proxy. --- * build(deps): bump try-lock from 0.2.3 to 0.2.4 (linkerd/linkerd2-proxy#2139) * build(deps): bump regex from 1.7.0 to 1.7.1 (linkerd/linkerd2-proxy#2145) * build(deps): bump tokio from 1.24.0 to 1.24.1 (linkerd/linkerd2-proxy#2144) * Parameterize the load balancer stack (linkerd/linkerd2-proxy#2142) * build(deps): bump prost-types from 0.11.5 to 0.11.6 (linkerd/linkerd2-proxy#2147) * build(deps): bump prost from 0.11.5 to 0.11.6 (linkerd/linkerd2-proxy#2148) * build(deps): bump prost-build from 0.11.5 to 0.11.6 (linkerd/linkerd2-proxy#2149) * stack: add `AnnotateError` middleware (linkerd/linkerd2-proxy#2158) * Fix proxy-core dependencies (linkerd/linkerd2-proxy#2163) * build(deps): bump tj-actions/changed-files from 35.3.1 to 35.4.1 (linkerd/linkerd2-proxy#2153) * orig_proto: don't set `connection: close` on errors (linkerd/linkerd2-proxy#2171) * build(deps): bump bumpalo from 3.11.1 to 3.12.0 (linkerd/linkerd2-proxy#2166) * build(deps): bump proc-macro2 from 1.0.49 to 1.0.50 (linkerd/linkerd2-proxy#2165) * build(deps): bump tj-actions/changed-files from 35.4.1 to 35.4.4 (linkerd/linkerd2-proxy#2172) * build(deps): bump windows_x86_64_msvc from 0.42.0 to 0.42.1 (linkerd/linkerd2-proxy#2164) * configure buffers from target `Param`s (linkerd/linkerd2-proxy#2173) * Simplify profile discovery (linkerd/linkerd2-proxy#2170) * stack: Unify AnnotateError and MapErr (linkerd/linkerd2-proxy#2180) * build(deps): bump windows_aarch64_msvc from 0.42.0 to 0.42.1 (linkerd/linkerd2-proxy#2176) * build(deps): bump async-trait from 0.1.61 to 0.1.63 (linkerd/linkerd2-proxy#2177) * build(deps): bump tokio from 1.24.1 to 1.24.2 (linkerd/linkerd2-proxy#2178) * Add the `meshtls-boring-fips` feature flag (linkerd/linkerd2-proxy#2168) * Update HTTP error responder to log version info (linkerd/linkerd2-proxy#2182) * build(deps): bump which from 4.3.0 to 4.4.0 (linkerd/linkerd2-proxy#2185) * build(deps): bump derive_arbitrary from 1.2.2 to 1.2.3 (linkerd/linkerd2-proxy#2184) * build(deps): bump unicode-bidi from 0.3.8 to 0.3.10 (linkerd/linkerd2-proxy#2183) * build(deps): bump linkerd/dev from 38 to 39 (linkerd/linkerd2-proxy#2175) * add target metadata to error contexts (linkerd/linkerd2-proxy#2162) * build(deps): bump rustls from 0.20.7 to 0.20.8 (linkerd/linkerd2-proxy#2187) * build(deps): bump ahash from 0.8.2 to 0.8.3 (linkerd/linkerd2-proxy#2188) * build(deps): bump matches from 0.1.9 to 0.1.10 (linkerd/linkerd2-proxy#2189) * Rename MakeThunk to NewThunk (linkerd/linkerd2-proxy#2197) * Add `NewQueueWithoutTimeout` (linkerd/linkerd2-proxy#2196) * Cache discovery results independently of proxy stacks (linkerd/linkerd2-proxy#2195) * core: Rename Stack utilities for clarity (linkerd/linkerd2-proxy#2199) * gateway: Unify discovery for HTTP & opaque stacks (linkerd/linkerd2-proxy#2198) * build(deps): bump libfuzzer-sys from 0.4.5 to 0.4.6 (linkerd/linkerd2-proxy#2193) * build(deps): bump arbitrary from 1.2.2 to 1.2.3 (linkerd/linkerd2-proxy#2191) * http: Remove `Clone` requirement in servers (linkerd/linkerd2-proxy#2200) * build(deps): bump either from 1.8.0 to 1.8.1 (linkerd/linkerd2-proxy#2192) * build(deps): bump bytes from 1.3.0 to 1.4.0 (linkerd/linkerd2-proxy#2202) * build(deps): bump cc from 1.0.78 to 1.0.79 (linkerd/linkerd2-proxy#2203) * build(deps): bump tj-actions/changed-files from 35.4.4 to 35.5.1 (linkerd/linkerd2-proxy#2211) * build(deps): bump tokio from 1.24.2 to 1.25.0 (linkerd/linkerd2-proxy#2206) * build(deps): bump miniz_oxide from 0.6.2 to 0.6.4 (linkerd/linkerd2-proxy#2207) * build(deps): bump async-trait from 0.1.63 to 0.1.64 (linkerd/linkerd2-proxy#2205) * Split outbound test modules into files (linkerd/linkerd2-proxy#2213) * Disable broken tests (linkerd/linkerd2-proxy#2214) * Add traceparent header parsing for w3c tracecontext (linkerd/linkerd2-proxy#2179) * Simplify the `Resolve` trait alias (linkerd/linkerd2-proxy#2218) * downgrade `miniz_oxide` from yanked 0.6.4 to 0.6.2 (linkerd/linkerd2-proxy#2219) * build(deps): bump heck from 0.4.0 to 0.4.1 (linkerd/linkerd2-proxy#2215) * ci: Fix check-each workflow (linkerd/linkerd2-proxy#2222) * Use a cascading stack with protocol detection (linkerd/linkerd2-proxy#2221) * ci: Fix quotation in list-crates (linkerd/linkerd2-proxy#2225) * outbound: Split out separate 'opaq' modules (linkerd/linkerd2-proxy#2224) * Update `linkerd2-proxy-api` to v0.8.0 (linkerd/linkerd2-proxy#2223) * outbound: Lint stack target types (linkerd/linkerd2-proxy#2226) * outbound: Split sidecar and ingress stack modules (linkerd/linkerd2-proxy#2227) * gateway: Split 'http' and 'opaq' modules (linkerd/linkerd2-proxy#2230) * test: Disable tap::rejects_incorrect_identity_when_identity_is_expected (linkerd/linkerd2-proxy#2231) * outbound: Improve discovery cache test (linkerd/linkerd2-proxy#2233) * integration: add destination update builders (linkerd/linkerd2-proxy#2232) * Rename linkerd-server-policy to linkerd-proxy-server-policy (linkerd/linkerd2-proxy#2235) * integration: add test for direct HTTP connections (linkerd/linkerd2-proxy#2234) * outbound: Refactor stack target types (linkerd/linkerd2-proxy#2210) * Add client-policy types (linkerd/linkerd2-proxy#2236) Signed-off-by: Oliver Gould <[email protected]>
This release includes many internal changes to prepare for the new client policy API. Stack metric label values have changed to reflect the new shape of the outbound proxy. This change also includes some test improvements that helped debug an issue while merging this. --- * build(deps): bump try-lock from 0.2.3 to 0.2.4 (linkerd/linkerd2-proxy#2139) * build(deps): bump regex from 1.7.0 to 1.7.1 (linkerd/linkerd2-proxy#2145) * build(deps): bump tokio from 1.24.0 to 1.24.1 (linkerd/linkerd2-proxy#2144) * Parameterize the load balancer stack (linkerd/linkerd2-proxy#2142) * build(deps): bump prost-types from 0.11.5 to 0.11.6 (linkerd/linkerd2-proxy#2147) * build(deps): bump prost from 0.11.5 to 0.11.6 (linkerd/linkerd2-proxy#2148) * build(deps): bump prost-build from 0.11.5 to 0.11.6 (linkerd/linkerd2-proxy#2149) * stack: add `AnnotateError` middleware (linkerd/linkerd2-proxy#2158) * Fix proxy-core dependencies (linkerd/linkerd2-proxy#2163) * build(deps): bump tj-actions/changed-files from 35.3.1 to 35.4.1 (linkerd/linkerd2-proxy#2153) * orig_proto: don't set `connection: close` on errors (linkerd/linkerd2-proxy#2171) * build(deps): bump bumpalo from 3.11.1 to 3.12.0 (linkerd/linkerd2-proxy#2166) * build(deps): bump proc-macro2 from 1.0.49 to 1.0.50 (linkerd/linkerd2-proxy#2165) * build(deps): bump tj-actions/changed-files from 35.4.1 to 35.4.4 (linkerd/linkerd2-proxy#2172) * build(deps): bump windows_x86_64_msvc from 0.42.0 to 0.42.1 (linkerd/linkerd2-proxy#2164) * configure buffers from target `Param`s (linkerd/linkerd2-proxy#2173) * Simplify profile discovery (linkerd/linkerd2-proxy#2170) * stack: Unify AnnotateError and MapErr (linkerd/linkerd2-proxy#2180) * build(deps): bump windows_aarch64_msvc from 0.42.0 to 0.42.1 (linkerd/linkerd2-proxy#2176) * build(deps): bump async-trait from 0.1.61 to 0.1.63 (linkerd/linkerd2-proxy#2177) * build(deps): bump tokio from 1.24.1 to 1.24.2 (linkerd/linkerd2-proxy#2178) * Add the `meshtls-boring-fips` feature flag (linkerd/linkerd2-proxy#2168) * Update HTTP error responder to log version info (linkerd/linkerd2-proxy#2182) * build(deps): bump which from 4.3.0 to 4.4.0 (linkerd/linkerd2-proxy#2185) * build(deps): bump derive_arbitrary from 1.2.2 to 1.2.3 (linkerd/linkerd2-proxy#2184) * build(deps): bump unicode-bidi from 0.3.8 to 0.3.10 (linkerd/linkerd2-proxy#2183) * build(deps): bump linkerd/dev from 38 to 39 (linkerd/linkerd2-proxy#2175) * add target metadata to error contexts (linkerd/linkerd2-proxy#2162) * build(deps): bump rustls from 0.20.7 to 0.20.8 (linkerd/linkerd2-proxy#2187) * build(deps): bump ahash from 0.8.2 to 0.8.3 (linkerd/linkerd2-proxy#2188) * build(deps): bump matches from 0.1.9 to 0.1.10 (linkerd/linkerd2-proxy#2189) * Rename MakeThunk to NewThunk (linkerd/linkerd2-proxy#2197) * Add `NewQueueWithoutTimeout` (linkerd/linkerd2-proxy#2196) * Cache discovery results independently of proxy stacks (linkerd/linkerd2-proxy#2195) * core: Rename Stack utilities for clarity (linkerd/linkerd2-proxy#2199) * gateway: Unify discovery for HTTP & opaque stacks (linkerd/linkerd2-proxy#2198) * build(deps): bump libfuzzer-sys from 0.4.5 to 0.4.6 (linkerd/linkerd2-proxy#2193) * build(deps): bump arbitrary from 1.2.2 to 1.2.3 (linkerd/linkerd2-proxy#2191) * http: Remove `Clone` requirement in servers (linkerd/linkerd2-proxy#2200) * build(deps): bump either from 1.8.0 to 1.8.1 (linkerd/linkerd2-proxy#2192) * build(deps): bump bytes from 1.3.0 to 1.4.0 (linkerd/linkerd2-proxy#2202) * build(deps): bump cc from 1.0.78 to 1.0.79 (linkerd/linkerd2-proxy#2203) * build(deps): bump tj-actions/changed-files from 35.4.4 to 35.5.1 (linkerd/linkerd2-proxy#2211) * build(deps): bump tokio from 1.24.2 to 1.25.0 (linkerd/linkerd2-proxy#2206) * build(deps): bump miniz_oxide from 0.6.2 to 0.6.4 (linkerd/linkerd2-proxy#2207) * build(deps): bump async-trait from 0.1.63 to 0.1.64 (linkerd/linkerd2-proxy#2205) * Split outbound test modules into files (linkerd/linkerd2-proxy#2213) * Disable broken tests (linkerd/linkerd2-proxy#2214) * Add traceparent header parsing for w3c tracecontext (linkerd/linkerd2-proxy#2179) * Simplify the `Resolve` trait alias (linkerd/linkerd2-proxy#2218) * downgrade `miniz_oxide` from yanked 0.6.4 to 0.6.2 (linkerd/linkerd2-proxy#2219) * build(deps): bump heck from 0.4.0 to 0.4.1 (linkerd/linkerd2-proxy#2215) * ci: Fix check-each workflow (linkerd/linkerd2-proxy#2222) * Use a cascading stack with protocol detection (linkerd/linkerd2-proxy#2221) * ci: Fix quotation in list-crates (linkerd/linkerd2-proxy#2225) * outbound: Split out separate 'opaq' modules (linkerd/linkerd2-proxy#2224) * Update `linkerd2-proxy-api` to v0.8.0 (linkerd/linkerd2-proxy#2223) * outbound: Lint stack target types (linkerd/linkerd2-proxy#2226) * outbound: Split sidecar and ingress stack modules (linkerd/linkerd2-proxy#2227) * gateway: Split 'http' and 'opaq' modules (linkerd/linkerd2-proxy#2230) * test: Disable tap::rejects_incorrect_identity_when_identity_is_expected (linkerd/linkerd2-proxy#2231) * outbound: Improve discovery cache test (linkerd/linkerd2-proxy#2233) * integration: add destination update builders (linkerd/linkerd2-proxy#2232) * Rename linkerd-server-policy to linkerd-proxy-server-policy (linkerd/linkerd2-proxy#2235) * integration: add test for direct HTTP connections (linkerd/linkerd2-proxy#2234) * outbound: Refactor stack target types (linkerd/linkerd2-proxy#2210) * Add client-policy types (linkerd/linkerd2-proxy#2236)
This is a proof of concept PR to show what changes would be necessary to support
tracecontext
, the OpenTelemetry "standardised" way of propagating distributed tracing context (akaw3c
format).A copy of the RFC can be found here. The RFC/specification has a processing model for how the header(s) should be parsed. This proof of concept contains most cases, some which are a bit more trivial to implement have been left out and will be done when (or if) this moves forward. The parsing logic is also a bit rushed and I will want to revisit it if conceptually this all looks sound.
Also, most notably,
tracestate
is not being handled at all, since it's optional:Likewise, the proxy will likely not want to implement some parts of the specification, the one that stands out to me is the absence of a traceparent header. On absence, the spec says we should start a trace, we will want to instead parse
b3
headers (we shouldn't create our own trace if it's not present on the request).To test, I used an emojivoto fork configured with otel instead of opencensus library. If we go ahead with this, I plan on pushing my branch to the emojivoto repo along with manifests so that reviewers can test in their environments. For now, I've included pictures from a trace (
vote-bot
-->voting
, note thatbot-vote
naming is to distinguish my fork from the original code, bit confusing maybe, sorry).Note: in the first picture notice how the last service (voting) didn't really have a proxy span. On refresh, the span appeared. Think this is just Jaeger being flakey.
Pictures of Jaeger query
Signed-off-by: Matei David [email protected]