Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e280a8a

Browse files
authored
Make sure trace flags are parsed properly when extracting traceparent and expand tests (open-telemetry#2577)
1 parent b2e9387 commit e280a8a

File tree

4 files changed

+174
-1
lines changed

4 files changed

+174
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.10.0-0.29b0...HEAD)
99

10+
- Fix parsing of trace flags when extracting traceparent
11+
([#2577](https://github.com/open-telemetry/opentelemetry-python/pull/2577))
1012
- Add default aggregation
1113
([#2543](https://github.com/open-telemetry/opentelemetry-python/pull/2543))
1214
- Fix incorrect installation of some exporter “convenience” packages into

opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def extract(
7979
trace_id=int(trace_id, 16),
8080
span_id=int(span_id, 16),
8181
is_remote=True,
82-
trace_flags=trace.TraceFlags(trace_flags),
82+
trace_flags=trace.TraceFlags(int(trace_flags, 16)),
8383
trace_state=tracestate,
8484
)
8585
return trace.set_span_in_context(

opentelemetry-api/tests/propagators/test_propagators.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
from unittest import TestCase
2121
from unittest.mock import Mock, patch
2222

23+
from opentelemetry import trace
2324
from opentelemetry.baggage.propagation import W3CBaggagePropagator
25+
from opentelemetry.context.context import Context
2426
from opentelemetry.environment_variables import OTEL_PROPAGATORS
2527
from opentelemetry.trace.propagation.tracecontext import (
2628
TraceContextTextMapPropagator,
@@ -44,6 +46,7 @@ def test_propagators(propagators):
4446
**{"side_effect": test_propagators}
4547
)
4648

49+
# pylint: disable=import-outside-toplevel
4750
import opentelemetry.propagate
4851

4952
reload(opentelemetry.propagate)
@@ -79,6 +82,7 @@ def test_propagators(propagators):
7982
**{"side_effect": test_propagators}
8083
)
8184

85+
# pylint: disable=import-outside-toplevel
8286
import opentelemetry.propagate
8387

8488
reload(opentelemetry.propagate)
@@ -88,6 +92,7 @@ def test_propagators(propagators):
8892
)
8993
def test_composite_propagators_error(self):
9094

95+
# pylint: disable=import-outside-toplevel
9196
import opentelemetry.propagate
9297

9398
with self.assertRaises(Exception):
@@ -97,3 +102,145 @@ def test_composite_propagators_error(self):
97102
"Failed to load configured propagator `unknown`",
98103
err.output[0],
99104
)
105+
106+
107+
class TestTraceContextTextMapPropagator(TestCase):
108+
def setUp(self):
109+
self.propagator = TraceContextTextMapPropagator()
110+
111+
def traceparent_helper(
112+
self,
113+
carrier,
114+
):
115+
# We purposefully start with an empty context so we can test later if anything is added to it.
116+
initial_context = Context()
117+
118+
context = self.propagator.extract(carrier, context=initial_context)
119+
self.assertIsNotNone(context)
120+
self.assertIsInstance(context, Context)
121+
122+
return context
123+
124+
def traceparent_helper_generator(
125+
self,
126+
version=0x00,
127+
trace_id=0x00000000000000000000000000000001,
128+
span_id=0x0000000000000001,
129+
trace_flags=0x00,
130+
suffix="",
131+
):
132+
traceparent = f"{version:02x}-{trace_id:032x}-{span_id:016x}-{trace_flags:02x}{suffix}"
133+
carrier = {"traceparent": traceparent}
134+
return self.traceparent_helper(carrier)
135+
136+
def valid_traceparent_helper(
137+
self,
138+
version=0x00,
139+
trace_id=0x00000000000000000000000000000001,
140+
span_id=0x0000000000000001,
141+
trace_flags=0x00,
142+
suffix="",
143+
assert_context_msg="A valid traceparent was provided, so the context should be non-empty.",
144+
):
145+
context = self.traceparent_helper_generator(
146+
version=version,
147+
trace_id=trace_id,
148+
span_id=span_id,
149+
trace_flags=trace_flags,
150+
suffix=suffix,
151+
)
152+
153+
self.assertNotEqual(
154+
context,
155+
Context(),
156+
assert_context_msg,
157+
)
158+
159+
span = trace.get_current_span(context)
160+
self.assertIsNotNone(span)
161+
self.assertIsInstance(span, trace.span.Span)
162+
163+
span_context = span.get_span_context()
164+
self.assertIsNotNone(span_context)
165+
self.assertIsInstance(span_context, trace.span.SpanContext)
166+
167+
# Note: No version in SpanContext, it is only used locally in TraceContextTextMapPropagator
168+
self.assertEqual(span_context.trace_id, trace_id)
169+
self.assertEqual(span_context.span_id, span_id)
170+
self.assertEqual(span_context.trace_flags, trace_flags)
171+
172+
self.assertIsInstance(span_context.trace_state, trace.TraceState)
173+
self.assertCountEqual(span_context.trace_state, [])
174+
self.assertEqual(span_context.is_remote, True)
175+
176+
return context, span, span_context
177+
178+
def invalid_traceparent_helper(
179+
self,
180+
version=0x00,
181+
trace_id=0x00000000000000000000000000000001,
182+
span_id=0x0000000000000001,
183+
trace_flags=0x00,
184+
suffix="",
185+
assert_context_msg="An invalid traceparent was provided, so the context should still be empty.",
186+
):
187+
context = self.traceparent_helper_generator(
188+
version=version,
189+
trace_id=trace_id,
190+
span_id=span_id,
191+
trace_flags=trace_flags,
192+
suffix=suffix,
193+
)
194+
195+
self.assertEqual(
196+
context,
197+
Context(),
198+
assert_context_msg,
199+
)
200+
201+
return context
202+
203+
def test_extract_nothing(self):
204+
context = self.traceparent_helper(carrier={})
205+
self.assertEqual(
206+
context,
207+
{},
208+
"We didn't provide a valid traceparent, so we should still have an empty Context.",
209+
)
210+
211+
def test_extract_simple_traceparent(self):
212+
self.valid_traceparent_helper()
213+
214+
# https://www.w3.org/TR/trace-context/#version
215+
def test_extract_version_forbidden_ff(self):
216+
self.invalid_traceparent_helper(
217+
version=0xFF,
218+
assert_context_msg="We provided ann invalid traceparent with a forbidden version=0xff, so the context should still be empty.",
219+
)
220+
221+
# https://www.w3.org/TR/trace-context/#version-format
222+
def test_extract_version_00_with_unsupported_suffix(self):
223+
self.invalid_traceparent_helper(
224+
suffix="-f00",
225+
assert_context_msg="We provided an invalid traceparent with version=0x00 and suffix information which is not supported in this version, so the context should still be empty.",
226+
)
227+
228+
# https://www.w3.org/TR/trace-context/#versioning-of-traceparent
229+
# See the parsing of the sampled bit of flags.
230+
def test_extract_future_version_with_future_suffix_data(self):
231+
self.valid_traceparent_helper(
232+
version=0x99,
233+
suffix="-f00",
234+
assert_context_msg="We provided a traceparent that is possibly valid in the future with version=0x99 and suffix information, so the context be non-empty.",
235+
)
236+
237+
# https://www.w3.org/TR/trace-context/#trace-id
238+
def test_extract_trace_id_invalid_all_zeros(self):
239+
self.invalid_traceparent_helper(trace_id=0)
240+
241+
# https://www.w3.org/TR/trace-context/#parent-id
242+
def test_extract_span_id_invalid_all_zeros(self):
243+
self.invalid_traceparent_helper(span_id=0)
244+
245+
def test_extract_non_decimal_trace_flags(self):
246+
self.valid_traceparent_helper(trace_flags=0xA0)

opentelemetry-sdk/tests/trace/test_trace.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,3 +1745,27 @@ def _test_span_no_limits(self, tracer):
17451745
self.assertEqual(len(root.attributes), num_attributes)
17461746
for attr_val in root.attributes.values():
17471747
self.assertEqual(attr_val, self.long_val)
1748+
1749+
1750+
class TestTraceFlags(unittest.TestCase):
1751+
def test_constant_default(self):
1752+
self.assertEqual(trace_api.TraceFlags.DEFAULT, 0)
1753+
1754+
def test_constant_sampled(self):
1755+
self.assertEqual(trace_api.TraceFlags.SAMPLED, 1)
1756+
1757+
def test_get_default(self):
1758+
self.assertEqual(
1759+
trace_api.TraceFlags.get_default(), trace_api.TraceFlags.DEFAULT
1760+
)
1761+
1762+
def test_sampled_true(self):
1763+
self.assertTrue(trace_api.TraceFlags(0xF1).sampled)
1764+
1765+
def test_sampled_false(self):
1766+
self.assertFalse(trace_api.TraceFlags(0xF0).sampled)
1767+
1768+
def test_constant_default_trace_options(self):
1769+
self.assertEqual(
1770+
trace_api.DEFAULT_TRACE_OPTIONS, trace_api.TraceFlags.DEFAULT
1771+
)

0 commit comments

Comments
 (0)