-
Notifications
You must be signed in to change notification settings - Fork 122
Add B3 single propagation format support #281
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
Conversation
Codecov Report
@@ Coverage Diff @@
## main #281 +/- ##
==========================================
+ Coverage 36.59% 37.51% +0.92%
==========================================
Files 45 47 +2
Lines 3178 3228 +50
==========================================
+ Hits 1163 1211 +48
- Misses 2015 2017 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
a9de390
to
a143b39
Compare
@@ -91,58 +90,132 @@ inject(Ctx, Carrier, CarrierSet, _Options) -> | |||
Carrier | |||
end. | |||
|
|||
% Extract trace context from the supplied carrier. The b3 single header takes | |||
% precedence over the multi-header format. |
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.
Hm, this is interesting. Does the otel spec also say this or only the b3 spec? I'm confused about how in otel a user could specify b3 or b3multi but its supposed to use both either way?
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.
That's in the otel spec: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#b3-requirements . First point in the Extract section. That's also how it's done in the ruby implementation: https://github.com/open-telemetry/opentelemetry-ruby/blob/main/propagator/b3/lib/opentelemetry/propagator/b3/text_map_extractor.rb#L48
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, the use of being able to specify one or the other is for injection, makes sense.
%% Since `trace_context' and `baggage' are the two default propagators the | ||
%% global TextMap Propagators must be configured if B3 is to be used for | ||
%% propagation: | ||
%% | ||
%% ``` | ||
%% {text_map_propagators, [b3, baggage]}, | ||
%% ''' | ||
%% | ||
%% ``` | ||
%% CompositePropagator = otel_propagator_text_map_composite:create([b3, baggage]), | ||
%% opentelemetry:set_text_map_propagator(CompositePropagator). | ||
%% ''' | ||
%% | ||
%% It is also possible to set a separate list of injectors or extractors. | ||
%% For example, if the service should extract B3 encoded context but you | ||
%% only want to inject context encoded with the W3C TraceContext format | ||
%% (maybe you have some services only supporting B3 that are making requests | ||
%% to your server but you have no reason to continue propagating in both | ||
%% formats when communicating to other services further down the stack). | ||
%% In that case you would instead set configuration like: | ||
%% | ||
%% | ||
%% ``` | ||
%% {text_map_extractors, [b3, trace_context, baggage]}, | ||
%% {text_map_injectors, [trace_context, baggage]}, | ||
%% ''' | ||
%% | ||
%% Or using calls to {@link opentelemetry} at runtime: | ||
%% | ||
%% ``` | ||
%% B3CompositePropagator = otel_propagator_text_map_composite:create([b3, trace_context, baggage]), | ||
%% CompositePropagator = otel_propagator_text_map_composite:create([trace_context, baggage]), | ||
%% opentelemetry:set_text_map_extractor(B3CompositePropagator), | ||
%% opentelemetry:set_text_map_injector(CompositePropagator). | ||
%% ''' | ||
%% @end |
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 super helpful doc, A+
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.
99% copied from the existing b3multi module though
#span_ctx{trace_id=TraceId, | ||
span_id=SpanId, | ||
trace_flags=TraceOptions} when TraceId =/= 0 andalso SpanId =/= 0 -> | ||
Options = case TraceOptions band 1 of 1 -> <<"1">>; _ -> <<"0">> end, |
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.
Options = case TraceOptions band 1 of 1 -> <<"1">>; _ -> <<"0">> end, | |
Options = <<(TraceOptions band 1 + $0)>>, |
Is this too much code golf? Should technically be faster since band 1
is always gonna be 0 or 1 anyway.
I see lower that there's a <<"d">>
debug option that should come in, which I guess makes this suggestion irrelevant?
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.
Debug flag currently isn't propagated so here we deal only with 1
and 0
. Tbh I like the explicit version a bit more (I'm quite new to erlang so the code golf currently is a bit hard to grasp though I think I understand what is happening). I would keep it as is unless you feel strongly about changing it.
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.
Yea, the case
version is good.
A bit of a nitpick but I think this will be clearer if the module Injection can be based on a option to the propagator. So the configuration will then turn Does that make sense? |
a391e12
to
c6bd101
Compare
@tsloughter Yes, updated. |
[B3 single format][1] looks like this: `b3={TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}`, where the last two fields are optional. [OpenTelemetry B3 requirements][2]: B3 has both single and multi-header encodings. It also has semantics that do not map directly to OpenTelemetry such as a debug trace flag, and allowing spans from both sides of request to share the same id. To maximize compatibility between OpenTelemetry and Zipkin implementations, the following guidelines have been established for B3 context propagation. When extracting B3, propagators: * MUST attempt to extract B3 encoded using single and multi-header formats. The single-header variant takes precedence over the multi-header version. * MUST preserve a debug trace flag, if received, and propagate it with subsequent requests. Additionally, an OpenTelemetry implementation MUST set the sampled trace flag when the debug flag is set. * MUST NOT reuse X-B3-SpanId as the id for the server-side span. When injecting B3, propagators: * MUST default to injecting B3 using the single-header format * MUST provide configuration to change the default injection format to B3 multi-header * MUST NOT propagate X-B3-ParentSpanId as OpenTelemetry does not support reusing the same id for both sides of a request. [1]: https://github.com/openzipkin/b3-propagation#single-header [2]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#b3-requirements
B3 single format looks like this:
b3={TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}
,where the last two fields are optional.
OpenTelemetry B3 requirements:
B3 has both single and multi-header encodings. It also has semantics
that do not map directly to OpenTelemetry such as a debug trace flag,
and allowing spans from both sides of request to share the same id. To
maximize compatibility between OpenTelemetry and Zipkin implementations,
the following guidelines have been established for B3 context
propagation.
When extracting B3, propagators:
When injecting B3, propagators: