Skip to content
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

[API] Reduce exception handling in TextMapPropagator#extract #1153

Merged
merged 2 commits into from
Mar 21, 2022

Conversation

hosamaly
Copy link
Contributor

Previous code used to throw an error from TraceParent.from_string when given a nil, which happens when the carrier is empty.

This pull request changes the implementation to return early instead. It follows the same pattern that was introduced in Baggage::TextMapPropagator in PR #835.

@robertlaurin
Copy link
Contributor

robertlaurin commented Mar 18, 2022

Hey @hosamaly just would like to understand the issue this is meant to correct a little better.

Previous code used to throw an error from TraceParent.from_string when given a nil, which happens when the carrier is empty.

I believe we are handling nil cases in that method

it 'returns an empty Tracestate for nil' do
tracestate = OpenTelemetry::Trace::Tracestate.from_string(nil)
_(tracestate).must_be :empty?
end

Could provide an example that would trigger the error?

Edit: I commented on this a bit too quickly, it appears this is specific to the TraceParent.from_string, not TraceState.from_string.

Comment on lines 48 to 53
trace_parent_value = getter.get(carrier, TRACEPARENT_KEY)
trace_state_value = getter.get(carrier, TRACESTATE_KEY)
return context if trace_parent_value.nil? || trace_state_value.nil?

tp = TraceParent.from_string(trace_parent_value)
tracestate = Tracestate.from_string(trace_state_value)
Copy link
Contributor

@robertlaurin robertlaurin Mar 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I understand the intention of this PR now.

This change is intends to stop relying on exceptions for control flow in the (potentially common) case where the TRACEPARENT key is not present in the carrier, so instead we return the context early if we failed to extract any value from that key.

So this is not resolving any bug but instead meant to improve performance, is that correct @hosamaly?

If we do take this approach, we should not return early if the trace_state_value is nil, as the Tracestate.from_string can handle that case.

Suggested change
trace_parent_value = getter.get(carrier, TRACEPARENT_KEY)
trace_state_value = getter.get(carrier, TRACESTATE_KEY)
return context if trace_parent_value.nil? || trace_state_value.nil?
tp = TraceParent.from_string(trace_parent_value)
tracestate = Tracestate.from_string(trace_state_value)
return context unless trace_parent_value = getter.get(carrier, TRACEPARENT_KEY)
tp = TraceParent.from_string(trace_parent_value)
tracestate = Tracestate.from_string(getter.get(carrier, TRACESTATE_KEY))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, we can't parse tracestate before parsing traceparent:

If the vendor failed to parse traceparent, it MUST NOT attempt to parse tracestate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, you're absolutely right. I've committed your suggestion and reworded the commit to indicate that it's a performance improvement rather than a fix.

Comment on lines 48 to 50
trace_parent_value = getter.get(carrier, TRACEPARENT_KEY)
trace_state_value = getter.get(carrier, TRACESTATE_KEY)
return context if trace_parent_value.nil? || trace_state_value.nil?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The W3C Trace Context states that:

If the vendor failed to parse traceparent, it MUST NOT attempt to parse tracestate. Note that the opposite is not true: failure to parse tracestate MUST NOT affect the parsing of traceparent.

so we must not return early if trace_state is nil.

Suggested change
trace_parent_value = getter.get(carrier, TRACEPARENT_KEY)
trace_state_value = getter.get(carrier, TRACESTATE_KEY)
return context if trace_parent_value.nil? || trace_state_value.nil?
trace_parent_value = getter.get(carrier, TRACEPARENT_KEY)
trace_state_value = getter.get(carrier, TRACESTATE_KEY)
return context if trace_parent_value.nil?

@fbogsany
Copy link
Contributor

This is both a perf optimization and an attempt to reduce the use of exceptions for "normal" flow control. In general, I think it would be worth investing the effort to remove the use of exceptions in TraceParent parsing as well, but this is valid regardless.

Copy link
Contributor

@robertlaurin robertlaurin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just waiting on CI, will merge when complete.

Thanks for the PR!

@arielvalentin
Copy link
Contributor

Linter error https://github.com/open-telemetry/opentelemetry-ruby/runs/5628071090?check_suite_focus=true#step:5:64

lib/opentelemetry/trace/propagation/trace_context/text_map_propagator.rb:48:54: W: Lint/AssignmentInCondition: Use == if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition.
[65](https://github.com/open-telemetry/opentelemetry-ruby/runs/5628071090?check_suite_focus=true#step:5:65)
            return context unless trace_parent_value = getter.get(carrier, TRACEPARENT_KEY)

Fixes the following warning:
```
DEPRECATED: Use assert_nil if expecting nil from opentelemetry-ruby/api/test/opentelemetry/baggage/propagation/text_map_propagator_test.rb:187. This will fail in Minitest 6.
```
Previous code used to throw an error from `TraceParent.from_string` when
given a `nil`, which happens when the `carrier` is empty.

This commit causes the method to return early instead. It follows the
same pattern that was introduced in `Baggage::TextMapPropagator` in
commit 76ef411.
@hosamaly
Copy link
Contributor Author

Linter error

Fixed

@robertlaurin robertlaurin merged commit 9e6d877 into open-telemetry:main Mar 21, 2022
@hosamaly hosamaly deleted the reduce-exception-handling branch March 21, 2022 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants