From ef00f36265c7ff1235306f0ea130f13655192505 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Thu, 1 Oct 2020 17:23:51 +0200 Subject: [PATCH 1/2] Move SpanContext into Span. --- .../src/opentelemetry/trace/__init__.py | 18 ++-- .../trace/propagation/tracecontext.py | 17 ++-- .../src/opentelemetry/trace/span.py | 94 +++++++------------ .../propagators/test_global_httptextformat.py | 7 +- .../tests/test_implementation.py | 8 +- .../test_tracecontexthttptextformat.py | 35 ++++--- .../tests/trace/test_defaultspan.py | 18 +++- opentelemetry-api/tests/trace/test_globals.py | 2 +- opentelemetry-api/tests/trace/test_tracer.py | 2 +- .../src/opentelemetry/sdk/trace/__init__.py | 86 +++++++++-------- .../sdk/trace/export/__init__.py | 4 +- .../sdk/trace/propagation/b3_format.py | 23 ++--- .../src/opentelemetry/sdk/trace/sampling.py | 18 ++-- .../tests/context/test_asyncio.py | 2 +- .../tests/trace/export/test_export.py | 14 ++- .../export/test_in_memory_span_exporter.py | 2 +- .../tests/trace/propagation/test_b3_format.py | 65 ++++++------- .../tests/trace/test_implementation.py | 15 ++- .../tests/trace/test_sampling.py | 20 ++-- .../tests/trace/test_span_processor.py | 3 +- opentelemetry-sdk/tests/trace/test_trace.py | 71 +++++++------- 21 files changed, 245 insertions(+), 279 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 1795192254f..555dfc90093 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -85,12 +85,10 @@ DEFAULT_TRACE_OPTIONS, DEFAULT_TRACE_STATE, INVALID_SPAN, - INVALID_SPAN_CONTEXT, INVALID_SPAN_ID, INVALID_TRACE_ID, DefaultSpan, Span, - SpanContext, TraceFlags, TraceState, format_span_id, @@ -102,16 +100,16 @@ logger = getLogger(__name__) # TODO: quarantine -ParentSpan = typing.Optional[typing.Union["Span", "SpanContext"]] +ParentSpan = typing.Optional["Span"] class LinkBase(abc.ABC): - def __init__(self, context: "SpanContext") -> None: - self._context = context + def __init__(self, span: "Span") -> None: + self._span = span @property - def context(self) -> "SpanContext": - return self._context + def span(self) -> "Span": + return self._span @property @abc.abstractmethod @@ -128,9 +126,9 @@ class Link(LinkBase): """ def __init__( - self, context: "SpanContext", attributes: types.Attributes = None, + self, span: "Span", attributes: types.Attributes = None, ) -> None: - super().__init__(context) + super().__init__(span) self._attributes = attributes @property @@ -221,7 +219,7 @@ class Tracer(abc.ABC): # Constant used to represent the current span being used as a parent. # This is the default behavior when creating spans. - CURRENT_SPAN = DefaultSpan(INVALID_SPAN_CONTEXT) + CURRENT_SPAN = INVALID_SPAN @abc.abstractmethod def start_span( diff --git a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py index 8627b9a65cb..8f55c8aafc7 100644 --- a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py +++ b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py @@ -96,7 +96,7 @@ def extract( ) tracestate = _parse_tracestate(tracestate_headers) - span_context = trace.SpanContext( + extracted_span = trace.DefaultSpan( trace_id=int(trace_id, 16), span_id=int(span_id, 16), is_remote=True, @@ -104,7 +104,7 @@ def extract( trace_state=tracestate, ) return trace.set_span_in_context( - trace.DefaultSpan(span_context), context + extracted_span, context ) def inject( @@ -118,19 +118,18 @@ def inject( See `opentelemetry.trace.propagation.textmap.TextMapPropagator.inject` """ span = trace.get_current_span(context) - span_context = span.get_context() - if span_context == trace.INVALID_SPAN_CONTEXT: + if span == trace.INVALID_SPAN: return traceparent_string = "00-{:032x}-{:016x}-{:02x}".format( - span_context.trace_id, - span_context.span_id, - span_context.trace_flags, + span.trace_id, + span.span_id, + span.trace_flags, ) set_in_carrier( carrier, self._TRACEPARENT_HEADER_NAME, traceparent_string ) - if span_context.trace_state: - tracestate_string = _format_tracestate(span_context.trace_state) + if span.trace_state: + tracestate_string = _format_tracestate(span.trace_state) set_in_carrier( carrier, self._TRACESTATE_HEADER_NAME, tracestate_string ) diff --git a/opentelemetry-api/src/opentelemetry/trace/span.py b/opentelemetry-api/src/opentelemetry/trace/span.py index 27bbc223368..7e9b6d71253 100644 --- a/opentelemetry-api/src/opentelemetry/trace/span.py +++ b/opentelemetry-api/src/opentelemetry/trace/span.py @@ -9,6 +9,28 @@ class Span(abc.ABC): """A span represents a single operation within a trace.""" + def __init__( + self, + trace_id: int, + span_id: int, + is_remote: bool, + trace_flags: "TraceFlags", + trace_state: "TraceState" + ) -> None: + if trace_flags is None: + trace_flags = DEFAULT_TRACE_OPTIONS + if trace_state is None: + trace_state = DEFAULT_TRACE_STATE + self.trace_id = trace_id + self.span_id = span_id + self.trace_flags = trace_flags + self.trace_state = trace_state + self.is_remote = is_remote + self.is_valid = ( + self.trace_id != INVALID_TRACE_ID + and self.span_id != INVALID_SPAN_ID + ) + @abc.abstractmethod def end(self, end_time: typing.Optional[int] = None) -> None: """Sets the current time as the span's end time. @@ -19,17 +41,6 @@ def end(self, end_time: typing.Optional[int] = None) -> None: implementations are free to ignore or raise on further calls. """ - @abc.abstractmethod - def get_context(self) -> "SpanContext": - """Gets the span's SpanContext. - - Get an immutable, serializable identifier for this span that can be - used to create new child spans. - - Returns: - A :class:`opentelemetry.trace.SpanContext` with a copy of this span's immutable state. - """ - @abc.abstractmethod def set_attribute(self, key: str, value: types.AttributeValue) -> None: """Sets an Attribute. @@ -143,20 +154,11 @@ def get_default(cls) -> "TraceState": DEFAULT_TRACE_STATE = TraceState.get_default() -class SpanContext: - """The state of a Span to propagate between processes. - - This class includes the immutable attributes of a :class:`.Span` that must - be propagated to a span's children and across process boundaries. +class DefaultSpan(Span): + """The default Span that is used when no Span implementation is available. - Args: - trace_id: The ID of the trace that this span belongs to. - span_id: This span's ID. - trace_flags: Trace options to propagate. - trace_state: Tracing-system-specific info to propagate. - is_remote: True if propagated from a remote parent. + All operations are no-op except context propagation. """ - def __init__( self, trace_id: int, @@ -165,44 +167,14 @@ def __init__( trace_flags: "TraceFlags" = DEFAULT_TRACE_OPTIONS, trace_state: "TraceState" = DEFAULT_TRACE_STATE, ) -> None: - if trace_flags is None: - trace_flags = DEFAULT_TRACE_OPTIONS - if trace_state is None: - trace_state = DEFAULT_TRACE_STATE - self.trace_id = trace_id - self.span_id = span_id - self.trace_flags = trace_flags - self.trace_state = trace_state - self.is_remote = is_remote - self.is_valid = ( - self.trace_id != INVALID_TRACE_ID - and self.span_id != INVALID_SPAN_ID - ) - - def __repr__(self) -> str: - return ( - "{}(trace_id={}, span_id={}, trace_state={!r}, is_remote={})" - ).format( - type(self).__name__, - format_trace_id(self.trace_id), - format_span_id(self.span_id), - self.trace_state, - self.is_remote, + super().__init__( + trace_id, + span_id, + is_remote, + trace_flags, + trace_state ) - -class DefaultSpan(Span): - """The default Span that is used when no Span implementation is available. - - All operations are no-op except context propagation. - """ - - def __init__(self, context: "SpanContext") -> None: - self._context = context - - def get_context(self) -> "SpanContext": - return self._context - def is_recording(self) -> bool: return False @@ -232,15 +204,13 @@ def record_exception(self, exception: Exception) -> None: INVALID_SPAN_ID = 0x0000000000000000 INVALID_TRACE_ID = 0x00000000000000000000000000000000 -INVALID_SPAN_CONTEXT = SpanContext( +INVALID_SPAN = DefaultSpan( trace_id=INVALID_TRACE_ID, span_id=INVALID_SPAN_ID, is_remote=False, trace_flags=DEFAULT_TRACE_OPTIONS, trace_state=DEFAULT_TRACE_STATE, ) -INVALID_SPAN = DefaultSpan(INVALID_SPAN_CONTEXT) - def format_trace_id(trace_id: int) -> str: return "0x{:032x}".format(trace_id) diff --git a/opentelemetry-api/tests/propagators/test_global_httptextformat.py b/opentelemetry-api/tests/propagators/test_global_httptextformat.py index a1c58a4c3ad..0bf6f5cd7a2 100644 --- a/opentelemetry-api/tests/propagators/test_global_httptextformat.py +++ b/opentelemetry-api/tests/propagators/test_global_httptextformat.py @@ -49,12 +49,11 @@ def test_propagation(self): baggage_entries = baggage.get_all(context=ctx) expected = {"key1": "val1", "key2": "val2"} self.assertEqual(baggage_entries, expected) - span_context = get_current_span(context=ctx).get_context() + span = get_current_span(context=ctx) - self.assertEqual(span_context.trace_id, self.TRACE_ID) - self.assertEqual(span_context.span_id, self.SPAN_ID) + self.assertEqual(span.trace_id, self.TRACE_ID) + self.assertEqual(span.span_id, self.SPAN_ID) - span = trace.DefaultSpan(span_context) ctx = baggage.set_baggage("key3", "val3") ctx = baggage.set_baggage("key4", "val4", context=ctx) ctx = set_span_in_context(span, context=ctx) diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index 0d5b22b18f5..67115e0cdd7 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -37,13 +37,9 @@ def test_default_tracer(self): tracer_provider = trace.DefaultTracerProvider() tracer = tracer_provider.get_tracer(__name__) with tracer.start_span("test") as span: - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) self.assertEqual(span, trace.INVALID_SPAN) self.assertIs(span.is_recording(), False) with tracer.start_span("test2") as span2: - self.assertEqual( - span2.get_context(), trace.INVALID_SPAN_CONTEXT - ) self.assertEqual(span2, trace.INVALID_SPAN) self.assertIs(span2.is_recording(), False) @@ -53,8 +49,8 @@ def test_span(self): trace.Span() # type:ignore def test_default_span(self): - span = trace.DefaultSpan(trace.INVALID_SPAN_CONTEXT) - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) + span = trace.INVALID_SPAN + self.assertEqual(False, span.is_valid) self.assertIs(span.is_recording(), False) # METER diff --git a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py index 8abe4193873..9486c0eb28e 100644 --- a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py +++ b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py @@ -43,7 +43,7 @@ def test_no_traceparent_header(self): """ output = {} # type:typing.Dict[str, typing.List[str]] span = trace.get_current_span(FORMAT.extract(get_as_list, output)) - self.assertIsInstance(span.get_context(), trace.SpanContext) + self.assertIsInstance(span, trace.Span) def test_headers_with_tracestate(self): """When there is a traceparent and tracestate header, data from @@ -54,7 +54,7 @@ def test_headers_with_tracestate(self): span_id=format(self.SPAN_ID, "016x"), ) tracestate_value = "foo=1,bar=2,baz=3" - span_context = trace.get_current_span( + span = trace.get_current_span( FORMAT.extract( get_as_list, { @@ -62,15 +62,14 @@ def test_headers_with_tracestate(self): "tracestate": [tracestate_value], }, ) - ).get_context() - self.assertEqual(span_context.trace_id, self.TRACE_ID) - self.assertEqual(span_context.span_id, self.SPAN_ID) + ) + self.assertEqual(span.trace_id, self.TRACE_ID) + self.assertEqual(span.span_id, self.SPAN_ID) self.assertEqual( - span_context.trace_state, {"foo": "1", "bar": "2", "baz": "3"} + span.trace_state, {"foo": "1", "bar": "2", "baz": "3"} ) - self.assertTrue(span_context.is_remote) + self.assertTrue(span.is_remote) output = {} # type:typing.Dict[str, str] - span = trace.DefaultSpan(span_context) ctx = trace.set_span_in_context(span) FORMAT.inject(dict.__setitem__, output, ctx) @@ -109,7 +108,7 @@ def test_invalid_trace_id(self): }, ) ) - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) + self.assertEqual(span, trace.INVALID_SPAN) def test_invalid_parent_id(self): """If the parent id is invalid, we must ignore the full traceparent @@ -140,7 +139,7 @@ def test_invalid_parent_id(self): }, ) ) - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) + self.assertEqual(span, trace.INVALID_SPAN) def test_no_send_empty_tracestate(self): """If the tracestate is empty, do not set the header. @@ -152,7 +151,7 @@ def test_no_send_empty_tracestate(self): """ output = {} # type:typing.Dict[str, str] span = trace.DefaultSpan( - trace.SpanContext(self.TRACE_ID, self.SPAN_ID, is_remote=False) + self.TRACE_ID, self.SPAN_ID, is_remote=False ) ctx = trace.set_span_in_context(span) FORMAT.inject(dict.__setitem__, output, ctx) @@ -179,7 +178,7 @@ def test_format_not_supported(self): }, ) ) - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) + self.assertEqual(span, trace.INVALID_SPAN) def test_propagate_invalid_context(self): """Do not propagate invalid trace context.""" @@ -202,7 +201,7 @@ def test_tracestate_empty_header(self): }, ) ) - self.assertEqual(span.get_context().trace_state["foo"], "1") + self.assertEqual(span.trace_state["foo"], "1") def test_tracestate_header_with_trailing_comma(self): """Do not propagate invalid trace context. @@ -218,7 +217,7 @@ def test_tracestate_header_with_trailing_comma(self): }, ) ) - self.assertEqual(span.get_context().trace_state["foo"], "1") + self.assertEqual(span.trace_state["foo"], "1") def test_tracestate_keys(self): """Test for valid key patterns in the tracestate @@ -242,9 +241,9 @@ def test_tracestate_keys(self): }, ) ) - self.assertEqual(span.get_context().trace_state["1a-2f@foo"], "bar1") + self.assertEqual(span.trace_state["1a-2f@foo"], "bar1") self.assertEqual( - span.get_context().trace_state["1a-_*/2b@foo"], "bar2" + span.trace_state["1a-_*/2b@foo"], "bar2" ) - self.assertEqual(span.get_context().trace_state["foo"], "bar3") - self.assertEqual(span.get_context().trace_state["foo-_*/bar"], "bar4") + self.assertEqual(span.trace_state["foo"], "bar3") + self.assertEqual(span.trace_state["foo-_*/bar"], "bar4") diff --git a/opentelemetry-api/tests/trace/test_defaultspan.py b/opentelemetry-api/tests/trace/test_defaultspan.py index 67c2fc33521..5c5c1fcccd7 100644 --- a/opentelemetry-api/tests/trace/test_defaultspan.py +++ b/opentelemetry-api/tests/trace/test_defaultspan.py @@ -19,17 +19,25 @@ class TestDefaultSpan(unittest.TestCase): def test_ctor(self): - context = trace.SpanContext( + span = trace.DefaultSpan( 1, 1, is_remote=False, trace_flags=trace.DEFAULT_TRACE_OPTIONS, trace_state=trace.DEFAULT_TRACE_STATE, ) - span = trace.DefaultSpan(context) - self.assertEqual(context, span.get_context()) + self.assertEqual(1, span.trace_id) + self.assertEqual(1, span.trace_id) + self.assertEqual(False, span.is_remote) + self.assertEqual(trace.DEFAULT_TRACE_OPTIONS, span.trace_flags) + self.assertEqual(trace.DEFAULT_TRACE_STATE, span.trace_state) def test_invalid_span(self): + # TODO: Test the actual expected values of an invalid Span. self.assertIsNotNone(trace.INVALID_SPAN) - self.assertIsNotNone(trace.INVALID_SPAN.get_context()) - self.assertFalse(trace.INVALID_SPAN.get_context().is_valid) + self.assertIsNotNone(trace.INVALID_SPAN.trace_id) + self.assertIsNotNone(trace.INVALID_SPAN.span_id) + self.assertIsNotNone(trace.INVALID_SPAN.is_remote) + self.assertIsNotNone(trace.INVALID_SPAN.trace_flags) + self.assertIsNotNone(trace.INVALID_SPAN.trace_state) + self.assertFalse(trace.INVALID_SPAN.is_valid) diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index dc7c02e5139..e1b98a4be68 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -49,7 +49,7 @@ def test_get_current_span(self): be retrievable via get_current_span """ self.assertEqual(trace.get_current_span(), trace.INVALID_SPAN) - span = trace.DefaultSpan(trace.INVALID_SPAN_CONTEXT) + span = trace.INVALID_SPAN ctx = trace.set_span_in_context(span) token = context.attach(ctx) try: diff --git a/opentelemetry-api/tests/trace/test_tracer.py b/opentelemetry-api/tests/trace/test_tracer.py index 73909fd8ddb..07110e8d10f 100644 --- a/opentelemetry-api/tests/trace/test_tracer.py +++ b/opentelemetry-api/tests/trace/test_tracer.py @@ -30,7 +30,7 @@ def test_start_as_current_span(self): self.assertIsInstance(span, trace.Span) def test_use_span(self): - span = trace.DefaultSpan(trace.INVALID_SPAN_CONTEXT) + span = trace.INVALID_SPAN with self.tracer.use_span(span): pass diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 13819ed35b0..109b7df077b 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -43,7 +43,7 @@ from opentelemetry.sdk.trace import sampling from opentelemetry.sdk.util import BoundedDict, BoundedList from opentelemetry.sdk.util.instrumentation import InstrumentationInfo -from opentelemetry.trace import SpanContext +from opentelemetry.trace import Span, DEFAULT_TRACE_OPTIONS, DEFAULT_TRACE_STATE from opentelemetry.trace.propagation import SPAN_KEY from opentelemetry.trace.status import Status, StatusCanonicalCode from opentelemetry.util import time_ns, types @@ -345,7 +345,7 @@ class Span(trace_api.Span): Args: name: The name of the operation this span represents context: The immutable span context - parent: This span's parent's `opentelemetry.trace.SpanContext`, or + parent: This span's parent's `opentelemetry.trace.Span`, or null if this is a root span sampler: The sampler used to create this span trace_config: TODO @@ -360,8 +360,12 @@ class Span(trace_api.Span): def __init__( self, name: str, - context: trace_api.SpanContext, - parent: Optional[trace_api.SpanContext] = None, + trace_id: int, + span_id: int, + is_remote: bool, + trace_flags: "TraceFlags" = DEFAULT_TRACE_OPTIONS, + trace_state: "TraceState" = DEFAULT_TRACE_STATE, + parent: Optional[trace_api.Span] = None, sampler: Optional[sampling.Sampler] = None, trace_config: None = None, # TODO resource: Resource = Resource.create({}), @@ -374,8 +378,14 @@ def __init__( set_status_on_exception: bool = True, ) -> None: + super().__init__( + trace_id, + span_id, + is_remote, + trace_flags, + trace_state + ) self.name = name - self.context = context self.parent = parent self.sampler = sampler self.trace_config = trace_config @@ -419,8 +429,9 @@ def end_time(self): return self._end_time def __repr__(self): + # TODO - Print also the span context information. return '{}(name="{}", context={})'.format( - type(self).__name__, self.name, self.context + type(self).__name__, self.name ) @staticmethod @@ -436,11 +447,11 @@ def _new_links(): return BoundedList(MAX_NUM_LINKS) @staticmethod - def _format_context(context): + def _format_context(span): x_ctx = OrderedDict() - x_ctx["trace_id"] = trace_api.format_trace_id(context.trace_id) - x_ctx["span_id"] = trace_api.format_span_id(context.span_id) - x_ctx["trace_state"] = repr(context.trace_state) + x_ctx["trace_id"] = trace_api.format_trace_id(span.trace_id) + x_ctx["span_id"] = trace_api.format_span_id(span.span_id) + x_ctx["trace_state"] = repr(span.trace_state) return x_ctx @staticmethod @@ -465,7 +476,7 @@ def _format_links(links): f_links = [] for link in links: f_link = OrderedDict() - f_link["context"] = Span._format_context(link.context) + f_link["context"] = Span._format_context(link.span) f_link["attributes"] = Span._format_attributes(link.attributes) f_links.append(f_link) return f_links @@ -474,9 +485,6 @@ def to_json(self, indent=4): parent_id = None if self.parent is not None: if isinstance(self.parent, Span): - ctx = self.parent.context - parent_id = trace_api.format_span_id(ctx.span_id) - elif isinstance(self.parent, SpanContext): parent_id = trace_api.format_span_id(self.parent.span_id) start_time = None @@ -496,7 +504,7 @@ def to_json(self, indent=4): f_span = OrderedDict() f_span["name"] = self.name - f_span["context"] = self._format_context(self.context) + f_span["context"] = self._format_context(self) f_span["kind"] = str(self.kind) f_span["parent_id"] = parent_id f_span["start_time"] = start_time @@ -510,9 +518,6 @@ def to_json(self, indent=4): return json.dumps(f_span, indent=indent) - def get_context(self): - return self.context - def set_attribute(self, key: str, value: types.AttributeValue) -> None: with self._lock: if not self.is_recording(): @@ -722,24 +727,20 @@ def start_span( # pylint: disable=too-many-locals if parent is Tracer.CURRENT_SPAN: parent = trace_api.get_current_span() - parent_context = parent - if isinstance(parent_context, trace_api.Span): - parent_context = parent.get_context() - - if parent_context is not None and not isinstance( - parent_context, trace_api.SpanContext + if parent is not None and not isinstance( + parent, trace_api.Span ): - raise TypeError("parent must be a Span, SpanContext or None.") + raise TypeError("parent must be a Span or None.") - if parent_context is None or not parent_context.is_valid: - parent = parent_context = None + if parent is None or not parent.is_valid: + parent = None trace_id = generate_trace_id() trace_flags = None trace_state = None else: - trace_id = parent_context.trace_id - trace_flags = parent_context.trace_flags - trace_state = parent_context.trace_state + trace_id = parent.trace_id + trace_flags = parent.trace_flags + trace_state = parent.trace_state # The sampler decides whether to create a real or no-op span at the # time of span creation. No-op spans do not record events, and are not @@ -747,7 +748,7 @@ def start_span( # pylint: disable=too-many-locals # The sampler may also add attributes to the newly-created span, e.g. # to include information about the sampling result. sampling_result = self.source.sampler.should_sample( - parent_context, trace_id, name, attributes, links, + parent, trace_id, name, attributes, links, ) trace_flags = ( @@ -755,21 +756,18 @@ def start_span( # pylint: disable=too-many-locals if sampling_result.decision.is_sampled() else trace_api.TraceFlags(trace_api.TraceFlags.DEFAULT) ) - context = trace_api.SpanContext( - trace_id, - generate_span_id(), - is_remote=False, - trace_flags=trace_flags, - trace_state=trace_state, - ) # Only record if is_recording() is true if sampling_result.decision.is_recording(): # pylint:disable=protected-access span = Span( name=name, - context=context, - parent=parent_context, + trace_id=trace_id, + span_id=generate_span_id(), + is_remote=False, + trace_flags=trace_flags, + trace_state=trace_state, + parent=parent, sampler=self.source.sampler, resource=self.source.resource, attributes=sampling_result.attributes.copy(), @@ -781,7 +779,13 @@ def start_span( # pylint: disable=too-many-locals ) span.start(start_time=start_time) else: - span = trace_api.DefaultSpan(context=context) + span = trace_api.DefaultSpan( + trace_id, + generate_span_id(), + is_remote=False, + trace_flags=trace_flags, + trace_state=trace_state + ) return span @contextmanager diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index 59231e60f36..6c8bcd2ab75 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -75,7 +75,7 @@ def on_start(self, span: Span) -> None: pass def on_end(self, span: Span) -> None: - if not span.context.trace_flags.sampled: + if not span.trace_flags.sampled: return token = attach(set_value("suppress_instrumentation", True)) try: @@ -180,7 +180,7 @@ def on_end(self, span: Span) -> None: if self.done: logger.warning("Already shutdown, dropping span.") return - if not span.context.trace_flags.sampled: + if not span.trace_flags.sampled: return if len(self.queue) == self.max_queue_size: if not self._spans_dropped: diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py index c2b12f33f5a..36984276ffb 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py @@ -121,14 +121,12 @@ def extract( return trace.set_span_in_context( trace.DefaultSpan( - trace.SpanContext( - # trace an span ids are encoded in hex, so must be converted - trace_id=trace_id, - span_id=span_id, - is_remote=True, - trace_flags=trace.TraceFlags(options), - trace_state=trace.TraceState(), - ) + # trace an span ids are encoded in hex, so must be converted + trace_id=trace_id, + span_id=span_id, + is_remote=True, + trace_flags=trace.TraceFlags(options), + trace_state=trace.TraceState(), ) ) @@ -140,16 +138,15 @@ def inject( ) -> None: span = trace.get_current_span(context=context) - span_context = span.get_context() - if span_context == trace.INVALID_SPAN_CONTEXT: + if span == trace.INVALID_SPAN: return - sampled = (trace.TraceFlags.SAMPLED & span_context.trace_flags) != 0 + sampled = (trace.TraceFlags.SAMPLED & span.trace_flags) != 0 set_in_carrier( - carrier, self.TRACE_ID_KEY, format_trace_id(span_context.trace_id), + carrier, self.TRACE_ID_KEY, format_trace_id(span.trace_id), ) set_in_carrier( - carrier, self.SPAN_ID_KEY, format_span_id(span_context.span_id) + carrier, self.SPAN_ID_KEY, format_span_id(span.span_id) ) span_parent = getattr(span, "parent", None) if span_parent is not None: diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py index c40d3e691ee..ee22079dc74 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py @@ -66,7 +66,7 @@ from typing import Optional, Sequence # pylint: disable=unused-import -from opentelemetry.trace import Link, SpanContext +from opentelemetry.trace import Link, Span from opentelemetry.util.types import Attributes @@ -113,7 +113,7 @@ class Sampler(abc.ABC): @abc.abstractmethod def should_sample( self, - parent_context: Optional["SpanContext"], + parent: Optional["Span"], trace_id: int, name: str, attributes: Attributes = None, @@ -134,7 +134,7 @@ def __init__(self, decision: "Decision"): def should_sample( self, - parent_context: Optional["SpanContext"], + parent: Optional["Span"], trace_id: int, name: str, attributes: Attributes = None, @@ -188,7 +188,7 @@ def bound(self) -> int: def should_sample( self, - parent_context: Optional["SpanContext"], + parent: Optional["Span"], trace_id: int, name: str, attributes: Attributes = None, # TODO @@ -220,22 +220,22 @@ def __init__(self, delegate: Sampler): def should_sample( self, - parent_context: Optional["SpanContext"], + parent: Optional["Span"], trace_id: int, name: str, attributes: Attributes = None, # TODO links: Sequence["Link"] = (), ) -> "SamplingResult": - if parent_context is not None: + if parent is not None: if ( - not parent_context.is_valid - or not parent_context.trace_flags.sampled + not parent.is_valid + or not parent.trace_flags.sampled ): return SamplingResult(Decision.DROP) return SamplingResult(Decision.RECORD_AND_SAMPLE, attributes) return self._delegate.should_sample( - parent_context=parent_context, + parent=parent, trace_id=trace_id, name=name, attributes=attributes, diff --git a/opentelemetry-sdk/tests/context/test_asyncio.py b/opentelemetry-sdk/tests/context/test_asyncio.py index 4fa653205b0..f213753c59f 100644 --- a/opentelemetry-sdk/tests/context/test_asyncio.py +++ b/opentelemetry-sdk/tests/context/test_asyncio.py @@ -108,4 +108,4 @@ def test_with_asyncio(self): for span in span_list: if span is expected_parent: continue - self.assertEqual(span.parent, expected_parent.get_context()) + self.assertEqual(span.parent, expected_parent) diff --git a/opentelemetry-sdk/tests/trace/export/test_export.py b/opentelemetry-sdk/tests/trace/export/test_export.py index 8c43f731b2c..f895561c952 100644 --- a/opentelemetry-sdk/tests/trace/export/test_export.py +++ b/opentelemetry-sdk/tests/trace/export/test_export.py @@ -123,12 +123,10 @@ def test_simple_span_processor_not_sampled(self): def _create_start_and_end_span(name, span_processor): span = trace.Span( name, - trace_api.SpanContext( - 0xDEADBEEF, - 0xDEADBEEF, - is_remote=False, - trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), - ), + 0xDEADBEEF, + 0xDEADBEEF, + is_remote=False, + trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), span_processor=span_processor, ) span.start() @@ -403,7 +401,7 @@ def test_export(self): # pylint: disable=no-self-use # Mocking stdout interferes with debugging and test reporting, mock on # the exporter instance instead. - span = trace.Span("span name", trace_api.INVALID_SPAN_CONTEXT) + span = trace.Span("span name", 0, 0, False) with mock.patch.object(exporter, "out") as mock_stdout: exporter.export([span]) mock_stdout.write.assert_called_once_with(span.to_json() + os.linesep) @@ -421,5 +419,5 @@ def formatter(span): # pylint: disable=unused-argument exporter = export.ConsoleSpanExporter( out=mock_stdout, formatter=formatter ) - exporter.export([trace.Span("span name", mock.Mock())]) + exporter.export([trace.Span("span name", 1, 2, False)]) mock_stdout.write.assert_called_once_with(mock_span_str) diff --git a/opentelemetry-sdk/tests/trace/export/test_in_memory_span_exporter.py b/opentelemetry-sdk/tests/trace/export/test_in_memory_span_exporter.py index 4925bdb1825..e8cf0b330d8 100644 --- a/opentelemetry-sdk/tests/trace/export/test_in_memory_span_exporter.py +++ b/opentelemetry-sdk/tests/trace/export/test_in_memory_span_exporter.py @@ -61,7 +61,7 @@ def test_shutdown(self): self.assertEqual(len(span_list), 3) def test_return_code(self): - span = trace.Span("name", mock.Mock(spec=trace_api.SpanContext)) + span = trace.Span("name", 1, 2, False) span_list = (span,) memory_exporter = InMemorySpanExporter() diff --git a/opentelemetry-sdk/tests/trace/propagation/test_b3_format.py b/opentelemetry-sdk/tests/trace/propagation/test_b3_format.py index 77834adec97..3c6048f7430 100644 --- a/opentelemetry-sdk/tests/trace/propagation/test_b3_format.py +++ b/opentelemetry-sdk/tests/trace/propagation/test_b3_format.py @@ -31,19 +31,16 @@ def get_as_list(dict_object, key): def get_child_parent_new_carrier(old_carrier): ctx = FORMAT.extract(get_as_list, old_carrier) - parent_context = trace_api.get_current_span(ctx).get_context() + parent = trace_api.get_current_span(ctx) - parent = trace.Span("parent", parent_context) child = trace.Span( "child", - trace_api.SpanContext( - parent_context.trace_id, - trace.generate_span_id(), - is_remote=False, - trace_flags=parent_context.trace_flags, - trace_state=parent_context.trace_state, - ), - parent=parent.get_context(), + parent.trace_id, + trace.generate_span_id(), + is_remote=False, + trace_flags=parent.trace_flags, + trace_state=parent.trace_state, + parent=parent, ) new_carrier = {} @@ -79,17 +76,17 @@ def test_extract_multi_header(self): self.assertEqual( new_carrier[FORMAT.TRACE_ID_KEY], - b3_format.format_trace_id(child.context.trace_id), + b3_format.format_trace_id(child.trace_id), ) self.assertEqual( new_carrier[FORMAT.SPAN_ID_KEY], - b3_format.format_span_id(child.context.span_id), + b3_format.format_span_id(child.span_id), ) self.assertEqual( new_carrier[FORMAT.PARENT_SPAN_ID_KEY], - b3_format.format_span_id(parent.context.span_id), + b3_format.format_span_id(parent.span_id), ) - self.assertTrue(parent.context.is_remote) + self.assertTrue(parent.is_remote) self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1") def test_extract_single_header(self): @@ -104,14 +101,14 @@ def test_extract_single_header(self): self.assertEqual( new_carrier[FORMAT.TRACE_ID_KEY], - b3_format.format_trace_id(child.context.trace_id), + b3_format.format_trace_id(child.trace_id), ) self.assertEqual( new_carrier[FORMAT.SPAN_ID_KEY], - b3_format.format_span_id(child.context.span_id), + b3_format.format_span_id(child.span_id), ) self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1") - self.assertTrue(parent.context.is_remote) + self.assertTrue(parent.is_remote) child, parent, new_carrier = get_child_parent_new_carrier( { @@ -125,17 +122,17 @@ def test_extract_single_header(self): self.assertEqual( new_carrier[FORMAT.TRACE_ID_KEY], - b3_format.format_trace_id(child.context.trace_id), + b3_format.format_trace_id(child.trace_id), ) self.assertEqual( new_carrier[FORMAT.SPAN_ID_KEY], - b3_format.format_span_id(child.context.span_id), + b3_format.format_span_id(child.span_id), ) self.assertEqual( new_carrier[FORMAT.PARENT_SPAN_ID_KEY], - b3_format.format_span_id(parent.context.span_id), + b3_format.format_span_id(parent.span_id), ) - self.assertTrue(parent.context.is_remote) + self.assertTrue(parent.is_remote) self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1") def test_extract_header_precedence(self): @@ -231,9 +228,9 @@ def test_invalid_single_header(self): """ carrier = {FORMAT.SINGLE_HEADER_KEY: "0-1-2-3-4-5-6-7"} ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() - self.assertEqual(span_context.trace_id, trace_api.INVALID_TRACE_ID) - self.assertEqual(span_context.span_id, trace_api.INVALID_SPAN_ID) + span = trace_api.get_current_span(ctx) + self.assertEqual(span.trace_id, trace_api.INVALID_TRACE_ID) + self.assertEqual(span.span_id, trace_api.INVALID_SPAN_ID) def test_missing_trace_id(self): """If a trace id is missing, populate an invalid trace id.""" @@ -243,8 +240,8 @@ def test_missing_trace_id(self): } ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() - self.assertEqual(span_context.trace_id, trace_api.INVALID_TRACE_ID) + span = trace_api.get_current_span(ctx) + self.assertEqual(span.trace_id, trace_api.INVALID_TRACE_ID) @patch("opentelemetry.sdk.trace.propagation.b3_format.generate_trace_id") @patch("opentelemetry.sdk.trace.propagation.b3_format.generate_span_id") @@ -263,10 +260,10 @@ def test_invalid_trace_id( } ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() + span = trace_api.get_current_span(ctx) - self.assertEqual(span_context.trace_id, 1) - self.assertEqual(span_context.span_id, 2) + self.assertEqual(span.trace_id, 1) + self.assertEqual(span.span_id, 2) @patch("opentelemetry.sdk.trace.propagation.b3_format.generate_trace_id") @patch("opentelemetry.sdk.trace.propagation.b3_format.generate_span_id") @@ -285,10 +282,10 @@ def test_invalid_span_id( } ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() + span = trace_api.get_current_span(ctx) - self.assertEqual(span_context.trace_id, 1) - self.assertEqual(span_context.span_id, 2) + self.assertEqual(span.trace_id, 1) + self.assertEqual(span.span_id, 2) def test_missing_span_id(self): """If a trace id is missing, populate an invalid trace id.""" @@ -298,8 +295,8 @@ def test_missing_span_id(self): } ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() - self.assertEqual(span_context.span_id, trace_api.INVALID_SPAN_ID) + span = trace_api.get_current_span(ctx) + self.assertEqual(span.span_id, trace_api.INVALID_SPAN_ID) @staticmethod def test_inject_empty_context(): diff --git a/opentelemetry-sdk/tests/trace/test_implementation.py b/opentelemetry-sdk/tests/trace/test_implementation.py index 4582b069578..782e7ed3b2f 100644 --- a/opentelemetry-sdk/tests/trace/test_implementation.py +++ b/opentelemetry-sdk/tests/trace/test_implementation.py @@ -15,7 +15,7 @@ import unittest from opentelemetry.sdk import trace -from opentelemetry.trace import INVALID_SPAN, INVALID_SPAN_CONTEXT +from opentelemetry.trace import INVALID_SPAN, INVALID_TRACE_ID, INVALID_SPAN_ID class TestTracerImplementation(unittest.TestCase): @@ -29,11 +29,10 @@ class TestTracerImplementation(unittest.TestCase): def test_tracer(self): tracer = trace.TracerProvider().get_tracer(__name__) with tracer.start_span("test") as span: - self.assertNotEqual(span.get_context(), INVALID_SPAN_CONTEXT) + self.assertNotEqual(span, INVALID_SPAN) self.assertNotEqual(span, INVALID_SPAN) self.assertIs(span.is_recording(), True) with tracer.start_span("test2") as span2: - self.assertNotEqual(span2.get_context(), INVALID_SPAN_CONTEXT) self.assertNotEqual(span2, INVALID_SPAN) self.assertIs(span2.is_recording(), True) @@ -42,6 +41,12 @@ def test_span(self): # pylint: disable=no-value-for-parameter span = trace.Span() - span = trace.Span("name", INVALID_SPAN_CONTEXT) - self.assertEqual(span.get_context(), INVALID_SPAN_CONTEXT) + span = trace.Span( + "name", + INVALID_TRACE_ID, + INVALID_SPAN_ID, + is_remote=False, + ) + self.assertEqual(span.trace_id, INVALID_TRACE_ID) + self.assertEqual(span.span_id, INVALID_SPAN_ID) self.assertIs(span.is_recording(), True) diff --git a/opentelemetry-sdk/tests/trace/test_sampling.py b/opentelemetry-sdk/tests/trace/test_sampling.py index 9160ec4a351..ea5f12e5488 100644 --- a/opentelemetry-sdk/tests/trace/test_sampling.py +++ b/opentelemetry-sdk/tests/trace/test_sampling.py @@ -60,7 +60,7 @@ def test_ctr(self): class TestSampler(unittest.TestCase): def test_always_on(self): no_record_always_on = sampling.ALWAYS_ON.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT ), 0xDEADBEF1, @@ -73,7 +73,7 @@ def test_always_on(self): ) sampled_always_on = sampling.ALWAYS_ON.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED ), 0xDEADBEF1, @@ -87,7 +87,7 @@ def test_always_on(self): def test_always_off(self): no_record_always_off = sampling.ALWAYS_OFF.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT ), 0xDEADBEF1, @@ -98,7 +98,7 @@ def test_always_off(self): self.assertEqual(no_record_always_off.attributes, {}) sampled_always_on = sampling.ALWAYS_OFF.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED ), 0xDEADBEF1, @@ -110,7 +110,7 @@ def test_always_off(self): def test_default_on(self): no_record_default_on = sampling.DEFAULT_ON.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT ), 0xDEADBEF1, @@ -121,7 +121,7 @@ def test_default_on(self): self.assertEqual(no_record_default_on.attributes, {}) sampled_default_on = sampling.DEFAULT_ON.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED ), 0xDEADBEF1, @@ -143,7 +143,7 @@ def test_default_on(self): def test_default_off(self): no_record_default_off = sampling.DEFAULT_OFF.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT ), 0xDEADBEF1, @@ -154,7 +154,7 @@ def test_default_off(self): self.assertEqual(no_record_default_off.attributes, {}) sampled_default_off = sampling.DEFAULT_OFF.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED ), 0xDEADBEF1, @@ -278,7 +278,7 @@ def test_parent_based(self): # Check that the sampling decision matches the parent context if given self.assertFalse( sampler.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEF0, 0xDEADBEF1, is_remote=False, @@ -293,7 +293,7 @@ def test_parent_based(self): sampler2 = sampling.ParentBased(sampling.ALWAYS_OFF) self.assertTrue( sampler2.should_sample( - trace.SpanContext( + trace.DefaultSpan( 0xDEADBEF0, 0xDEADBEF1, is_remote=False, diff --git a/opentelemetry-sdk/tests/trace/test_span_processor.py b/opentelemetry-sdk/tests/trace/test_span_processor.py index 90b4003ca6d..29a0a59c629 100644 --- a/opentelemetry-sdk/tests/trace/test_span_processor.py +++ b/opentelemetry-sdk/tests/trace/test_span_processor.py @@ -149,8 +149,7 @@ def create_multi_span_processor( @staticmethod def create_default_span() -> trace_api.Span: - span_context = trace_api.SpanContext(37, 73, is_remote=False) - return trace_api.DefaultSpan(span_context) + return trace_api.DefaultSpan(37, 73, is_remote=False) def test_on_start(self): multi_processor = self.create_multi_span_processor() diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index fdf85ef19b5..b7d991b3e0f 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -111,7 +111,7 @@ def test_use_span_exception(self): class TestUseSpanException(Exception): pass - default_span = trace_api.DefaultSpan(trace_api.INVALID_SPAN_CONTEXT) + default_span = trace_api.DefaultSpan(0, 0, False) tracer = new_tracer() with self.assertRaises(TestUseSpanException): with tracer.use_span(default_span): @@ -139,12 +139,12 @@ def test_default_sampler(self): self.assertIsInstance(root_span, trace.Span) child_span = tracer.start_span(name="child span", parent=root_span) self.assertIsInstance(child_span, trace.Span) - self.assertTrue(root_span.context.trace_flags.sampled) + self.assertTrue(root_span.trace_flags.sampled) self.assertEqual( - root_span.get_context().trace_flags, trace_api.TraceFlags.SAMPLED + root_span.trace_flags, trace_api.TraceFlags.SAMPLED ) self.assertEqual( - child_span.get_context().trace_flags, trace_api.TraceFlags.SAMPLED + child_span.trace_flags, trace_api.TraceFlags.SAMPLED ) def test_sampler_no_sampling(self): @@ -158,10 +158,10 @@ def test_sampler_no_sampling(self): child_span = tracer.start_span(name="child span", parent=root_span) self.assertIsInstance(child_span, trace_api.DefaultSpan) self.assertEqual( - root_span.get_context().trace_flags, trace_api.TraceFlags.DEFAULT + root_span.trace_flags, trace_api.TraceFlags.DEFAULT ) self.assertEqual( - child_span.get_context().trace_flags, trace_api.TraceFlags.DEFAULT + child_span.trace_flags, trace_api.TraceFlags.DEFAULT ) @@ -175,9 +175,9 @@ def test_start_span_invalid_spancontext(self): """ tracer = new_tracer() new_span = tracer.start_span( - "root", parent=trace_api.INVALID_SPAN_CONTEXT + "root", parent=trace_api.INVALID_SPAN ) - self.assertTrue(new_span.context.is_valid) + self.assertTrue(new_span.is_valid) self.assertIsNone(new_span.parent) def test_instrumentation_info(self): @@ -250,7 +250,7 @@ def test_start_span_implicit(self): with tracer.start_span( "child", kind=trace_api.SpanKind.CLIENT ) as child: - self.assertIs(child.parent, root.get_context()) + self.assertIs(child.parent, root) self.assertEqual(child.kind, trace_api.SpanKind.CLIENT) self.assertIsNotNone(child.start_time) @@ -258,17 +258,15 @@ def test_start_span_implicit(self): # The new child span should inherit the parent's context but # get a new span ID. - root_context = root.get_context() - child_context = child.get_context() - self.assertEqual(root_context.trace_id, child_context.trace_id) + self.assertEqual(root.trace_id, child.trace_id) self.assertNotEqual( - root_context.span_id, child_context.span_id + root.span_id, child.span_id ) self.assertEqual( - root_context.trace_state, child_context.trace_state + root.trace_state, child.trace_state ) self.assertEqual( - root_context.trace_flags, child_context.trace_flags + root.trace_flags, child.trace_flags ) # Verify start_span() did not set the current span. @@ -282,7 +280,7 @@ def test_start_span_implicit(self): def test_start_span_explicit(self): tracer = new_tracer() - other_parent = trace_api.SpanContext( + other_parent = trace_api.DefaultSpan( trace_id=0x000000000000000000000000DEADBEEF, span_id=0x00000000DEADBEF0, is_remote=False, @@ -310,16 +308,15 @@ def test_start_span_explicit(self): # The child should inherit its context from the explicit # parent, not the current span. - child_context = child.get_context() - self.assertEqual(other_parent.trace_id, child_context.trace_id) + self.assertEqual(other_parent.trace_id, child.trace_id) self.assertNotEqual( - other_parent.span_id, child_context.span_id + other_parent.span_id, child.span_id ) self.assertEqual( - other_parent.trace_state, child_context.trace_state + other_parent.trace_state, child.trace_state ) self.assertEqual( - other_parent.trace_flags, child_context.trace_flags + other_parent.trace_flags, child.trace_flags ) # Verify start_span() did not set the current span. @@ -339,7 +336,7 @@ def test_start_as_current_span_implicit(self): with tracer.start_as_current_span("child") as child: self.assertIs(trace_api.get_current_span(), child) - self.assertIs(child.parent, root.get_context()) + self.assertIs(child.parent, root) # After exiting the child's scope the parent should become the # current span again. @@ -352,7 +349,7 @@ def test_start_as_current_span_implicit(self): def test_start_as_current_span_explicit(self): tracer = new_tracer() - other_parent = trace_api.SpanContext( + other_parent = trace_api.DefaultSpan( trace_id=0x000000000000000000000000DEADBEEF, span_id=0x00000000DEADBEF0, is_remote=False, @@ -402,7 +399,7 @@ def test_span_context_remote_flag(self): tracer = new_tracer() span = tracer.start_span("foo") - self.assertFalse(span.context.is_remote) + self.assertFalse(span.is_remote) class TestSpan(unittest.TestCase): @@ -410,7 +407,7 @@ def setUp(self): self.tracer = new_tracer() def test_basic_span(self): - span = trace.Span("name", mock.Mock(spec=trace_api.SpanContext)) + span = trace.Span("name", 1, 2, False) self.assertEqual(span.name, "name") def test_attributes(self): @@ -550,7 +547,7 @@ def test_sampling_attributes(self): self.assertEqual(root.attributes["sampler-attr"], "sample-val") self.assertEqual(root.attributes["attr-in-both"], "decision-attr") self.assertEqual( - root.get_context().trace_flags, trace_api.TraceFlags.SAMPLED + root.trace_flags, trace_api.TraceFlags.SAMPLED ) def test_events(self): @@ -615,12 +612,12 @@ def test_invalid_event_attributes(self): self.assertEqual(root.events[3].attributes, {"attr2": (1, 2)}) def test_links(self): - other_context1 = trace_api.SpanContext( + other_context1 = trace_api.DefaultSpan( trace_id=trace.generate_trace_id(), span_id=trace.generate_span_id(), is_remote=False, ) - other_context2 = trace_api.SpanContext( + other_context2 = trace_api.DefaultSpan( trace_id=trace.generate_trace_id(), span_id=trace.generate_span_id(), is_remote=False, @@ -634,17 +631,17 @@ def test_links(self): self.assertEqual(len(root.links), 2) self.assertEqual( - root.links[0].context.trace_id, other_context1.trace_id + root.links[0].span.trace_id, other_context1.trace_id ) self.assertEqual( - root.links[0].context.span_id, other_context1.span_id + root.links[0].span.span_id, other_context1.span_id ) self.assertEqual(root.links[0].attributes, None) self.assertEqual( - root.links[1].context.trace_id, other_context2.trace_id + root.links[1].span.trace_id, other_context2.trace_id ) self.assertEqual( - root.links[1].context.span_id, other_context2.span_id + root.links[1].span.span_id, other_context2.span_id ) self.assertEqual(root.links[1].attributes, {"name": "neighbor"}) @@ -656,7 +653,7 @@ def test_update_name(self): def test_start_span(self): """Start twice, end a not started""" - span = trace.Span("name", mock.Mock(spec=trace_api.SpanContext)) + span = trace.Span("name", 1, 2, False) # end not started span self.assertRaises(RuntimeError, span.end) @@ -682,7 +679,7 @@ def test_start_span(self): def test_span_override_start_and_end_time(self): """Span sending custom start_time and end_time values""" - span = trace.Span("name", mock.Mock(spec=trace_api.SpanContext)) + span = trace.Span("name", 1, 2, False) start_time = 123 span.start(start_time) self.assertEqual(start_time, span.start_time) @@ -781,7 +778,7 @@ def error_status_test(context): ) def test_record_exception(self): - span = trace.Span("name", mock.Mock(spec=trace_api.SpanContext)) + span = trace.Span("name", 1, 2, False) try: raise ValueError("invalid") except ValueError as err: @@ -915,13 +912,13 @@ def test_add_span_processor_after_span_creation(self): self.assertListEqual(spans_calls_list, expected_list) def test_to_json(self): - context = trace_api.SpanContext( + span = trace.Span( + "span-name", trace_id=0x000000000000000000000000DEADBEEF, span_id=0x00000000DEADBEF0, is_remote=False, trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), ) - span = trace.Span("span-name", context) span.resource = Resource({}) self.assertEqual( From 66daae1a0095385016e9bf0ceced06ab52ca8183 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Thu, 1 Oct 2020 18:49:51 +0200 Subject: [PATCH 2/2] Port the Jaeger exporter as well. --- .../examples/jaeger_exporter_example.py | 2 +- .../opentelemetry/exporter/jaeger/__init__.py | 11 +++---- .../tests/test_jaeger_exporter.py | 33 +++++++++++-------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py b/exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py index 68453fd9fac..3ff79679b08 100644 --- a/exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py +++ b/exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py @@ -34,7 +34,7 @@ foo.set_attribute("my_atribbute", True) foo.add_event("event in foo", {"name": "foo1"}) with tracer.start_as_current_span( - "bar", links=[trace.Link(foo.get_context())] + "bar", links=[trace.Link(foo)] ) as bar: time.sleep(0.2) bar.set_attribute("speed", 100.0) diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py index 354fe8b85c1..4447e9dd2d1 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py +++ b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py @@ -192,9 +192,8 @@ def _translate_to_jaeger(spans: Span): jaeger_spans = [] for span in spans: - ctx = span.get_context() - trace_id = ctx.trace_id - span_id = ctx.span_id + trace_id = span.trace_id + span_id = span.span_id start_time_us = _nsec_to_usec_round(span.start_time) duration_us = _nsec_to_usec_round(span.end_time - span.start_time) @@ -235,7 +234,7 @@ def _translate_to_jaeger(spans: Span): refs = _extract_refs_from_span(span) logs = _extract_logs_from_span(span) - flags = int(ctx.trace_flags) + flags = int(span.trace_flags) jaeger_span = jaeger.Span( traceIdHigh=_get_trace_id_high(trace_id), @@ -263,8 +262,8 @@ def _extract_refs_from_span(span): refs = [] for link in span.links: - trace_id = link.context.trace_id - span_id = link.context.span_id + trace_id = link.span.trace_id + span_id = link.span.span_id refs.append( jaeger.SpanRef( refType=jaeger.SpanRefType.FOLLOWS_FROM, diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter.py index c7870814226..26edddf3e4e 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter.py +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter.py @@ -30,13 +30,12 @@ class TestJaegerSpanExporter(unittest.TestCase): def setUp(self): # create and save span to be used in tests - context = trace_api.SpanContext( + self._test_span = trace.Span( + "test_span", trace_id=0x000000000000000000000000DEADBEEF, span_id=0x00000000DEADBEF0, is_remote=False, ) - - self._test_span = trace.Span("test_span", context=context) self._test_span.start() self._test_span.end() @@ -141,13 +140,10 @@ def test_translate_to_jaeger(self): start_times[2] + durations[2], ) - span_context = trace_api.SpanContext( - trace_id, span_id, is_remote=False - ) - parent_context = trace_api.SpanContext( + parent_span = trace_api.DefaultSpan( trace_id, parent_id, is_remote=False ) - other_context = trace_api.SpanContext( + other_span = trace_api.DefaultSpan( trace_id, other_id, is_remote=False ) @@ -167,7 +163,7 @@ def test_translate_to_jaeger(self): link_attributes = {"key_bool": True} link = trace_api.Link( - context=other_context, attributes=link_attributes + span=other_span, attributes=link_attributes ) default_tags = [ @@ -189,16 +185,27 @@ def test_translate_to_jaeger(self): otel_spans = [ trace.Span( name=span_names[0], - context=span_context, - parent=parent_context, + trace_id=trace_id, + span_id=span_id, + is_remote=False, + parent=parent_span, events=(event,), links=(link,), kind=trace_api.SpanKind.CLIENT, ), trace.Span( - name=span_names[1], context=parent_context, parent=None + name=span_names[1], + trace_id=parent_span.trace_id, + span_id=parent_span.span_id, + is_remote=parent_span.is_remote, + parent=None ), - trace.Span(name=span_names[2], context=other_context, parent=None), + trace.Span( + name=span_names[2], + trace_id=other_span.trace_id, + span_id=other_span.span_id, + is_remote=other_span.is_remote, + parent=None), ] otel_spans[0].start(start_time=start_times[0])