diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py index 2b36299989f..36335c23588 100644 --- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py +++ b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py @@ -189,12 +189,12 @@ def _translate_to_datadog(self, spans): def _get_trace_ids(span): """Extract tracer ids from span""" - ctx = span.get_context() + ctx = span.get_span_context() trace_id = ctx.trace_id span_id = ctx.span_id if isinstance(span.parent, trace_api.Span): - parent_id = span.parent.get_context().span_id + parent_id = span.parent.get_span_context().span_id elif isinstance(span.parent, trace_api.SpanContext): parent_id = span.parent.span_id else: @@ -255,13 +255,13 @@ def _get_exc_info(span): def _get_origin(span): - ctx = span.get_context() + ctx = span.get_span_context() origin = ctx.trace_state.get(DD_ORIGIN) return origin def _get_sampling_rate(span): - ctx = span.get_context() + ctx = span.get_span_context() return ( span.sampler.rate if ctx.trace_flags.sampled diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/propagator.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/propagator.py index d2e60476e68..3ad9fa1ae21 100644 --- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/propagator.py +++ b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/propagator.py @@ -86,7 +86,7 @@ def inject( context: typing.Optional[Context] = None, ) -> None: span = get_current_span(context) - span_context = span.get_context() + span_context = span.get_span_context() if span_context == trace.INVALID_SPAN_CONTEXT: return sampled = (trace.TraceFlags.SAMPLED & span.context.trace_flags) != 0 diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py index 600778c88c2..603ea5024ec 100644 --- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py +++ b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py @@ -82,7 +82,7 @@ def __init__( self.worker_thread.start() def on_start(self, span: Span) -> None: - ctx = span.get_context() + ctx = span.get_span_context() trace_id = ctx.trace_id with self.traces_lock: @@ -102,7 +102,7 @@ def on_end(self, span: Span) -> None: logger.warning("Already shutdown, dropping span.") return - ctx = span.get_context() + ctx = span.get_span_context() trace_id = ctx.trace_id with self.traces_lock: diff --git a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py index 27b4d0fa03f..98e894f94d4 100644 --- a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py +++ b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py @@ -178,7 +178,7 @@ def test_translate_to_datadog(self): span_context = trace_api.SpanContext( trace_id, span_id, is_remote=False ) - parent_context = trace_api.SpanContext( + parent_span_context = trace_api.SpanContext( trace_id, parent_id, is_remote=False ) other_context = trace_api.SpanContext( @@ -191,14 +191,14 @@ def test_translate_to_datadog(self): trace._Span( name=span_names[0], context=span_context, - parent=parent_context, + parent=parent_span_context, kind=trace_api.SpanKind.CLIENT, instrumentation_info=instrumentation_info, resource=Resource({}), ), trace._Span( name=span_names[1], - context=parent_context, + context=parent_span_context, parent=None, instrumentation_info=instrumentation_info, resource=resource_without_service, diff --git a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py index 3c045539fd2..8480374471b 100644 --- a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py +++ b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py @@ -51,7 +51,7 @@ def test_malformed_headers(self): malformed_parent_id_key: self.serialized_parent_id, }, ) - ).get_context() + ).get_span_context() self.assertNotEqual(context.trace_id, int(self.serialized_trace_id)) self.assertNotEqual(context.span_id, int(self.serialized_parent_id)) @@ -64,7 +64,7 @@ def test_missing_trace_id(self): } ctx = FORMAT.extract(get_as_list, carrier) - span_context = get_current_span(ctx).get_context() + span_context = get_current_span(ctx).get_span_context() self.assertEqual(span_context.trace_id, trace_api.INVALID_TRACE_ID) def test_missing_parent_id(self): @@ -74,12 +74,12 @@ def test_missing_parent_id(self): } ctx = FORMAT.extract(get_as_list, carrier) - span_context = get_current_span(ctx).get_context() + span_context = get_current_span(ctx).get_span_context() self.assertEqual(span_context.span_id, trace_api.INVALID_SPAN_ID) def test_context_propagation(self): """Test the propagation of Datadog headers.""" - parent_context = get_current_span( + parent_span_context = get_current_span( FORMAT.extract( get_as_list, { @@ -89,31 +89,31 @@ def test_context_propagation(self): FORMAT.ORIGIN_KEY: self.serialized_origin, }, ) - ).get_context() + ).get_span_context() self.assertEqual( - parent_context.trace_id, int(self.serialized_trace_id) + parent_span_context.trace_id, int(self.serialized_trace_id) ) self.assertEqual( - parent_context.span_id, int(self.serialized_parent_id) + parent_span_context.span_id, int(self.serialized_parent_id) ) - self.assertEqual(parent_context.trace_flags, constants.AUTO_KEEP) + self.assertEqual(parent_span_context.trace_flags, constants.AUTO_KEEP) self.assertEqual( - parent_context.trace_state.get(constants.DD_ORIGIN), + parent_span_context.trace_state.get(constants.DD_ORIGIN), self.serialized_origin, ) - self.assertTrue(parent_context.is_remote) + self.assertTrue(parent_span_context.is_remote) child = trace._Span( "child", trace_api.SpanContext( - parent_context.trace_id, + parent_span_context.trace_id, trace_api.RandomIdsGenerator().generate_span_id(), is_remote=False, - trace_flags=parent_context.trace_flags, - trace_state=parent_context.trace_state, + trace_flags=parent_span_context.trace_flags, + trace_state=parent_span_context.trace_state, ), - parent=parent_context, + parent=parent_span_context, ) child_carrier = {} @@ -136,7 +136,7 @@ def test_context_propagation(self): def test_sampling_priority_auto_reject(self): """Test sampling priority rejected.""" - parent_context = get_current_span( + parent_span_context = get_current_span( FORMAT.extract( get_as_list, { @@ -145,20 +145,22 @@ def test_sampling_priority_auto_reject(self): FORMAT.SAMPLING_PRIORITY_KEY: str(constants.AUTO_REJECT), }, ) - ).get_context() + ).get_span_context() - self.assertEqual(parent_context.trace_flags, constants.AUTO_REJECT) + self.assertEqual( + parent_span_context.trace_flags, constants.AUTO_REJECT + ) child = trace._Span( "child", trace_api.SpanContext( - parent_context.trace_id, + parent_span_context.trace_id, trace_api.RandomIdsGenerator().generate_span_id(), is_remote=False, - trace_flags=parent_context.trace_flags, - trace_state=parent_context.trace_state, + trace_flags=parent_span_context.trace_flags, + trace_state=parent_span_context.trace_state, ), - parent=parent_context, + parent=parent_span_context, ) child_carrier = {} diff --git a/exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py b/exporter/opentelemetry-exporter-jaeger/examples/jaeger_exporter_example.py index 68453fd9fac..0552f75183b 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.get_span_context())] ) 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..3cfd3fca431 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py +++ b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/__init__.py @@ -192,7 +192,7 @@ def _translate_to_jaeger(spans: Span): jaeger_spans = [] for span in spans: - ctx = span.get_context() + ctx = span.get_span_context() trace_id = ctx.trace_id span_id = ctx.span_id diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter.py index bb4920f7b3d..0a01bcb2347 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter.py +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter.py @@ -144,7 +144,7 @@ def test_translate_to_jaeger(self): span_context = trace_api.SpanContext( trace_id, span_id, is_remote=False ) - parent_context = trace_api.SpanContext( + parent_span_context = trace_api.SpanContext( trace_id, parent_id, is_remote=False ) other_context = trace_api.SpanContext( @@ -190,13 +190,13 @@ def test_translate_to_jaeger(self): trace._Span( name=span_names[0], context=span_context, - parent=parent_context, + parent=parent_span_context, events=(event,), links=(link,), kind=trace_api.SpanKind.CLIENT, ), trace._Span( - name=span_names[1], context=parent_context, parent=None + name=span_names[1], context=parent_span_context, parent=None ), trace._Span( name=span_names[2], context=other_context, parent=None diff --git a/exporter/opentelemetry-exporter-opencensus/tests/test_otcollector_trace_exporter.py b/exporter/opentelemetry-exporter-opencensus/tests/test_otcollector_trace_exporter.py index 3721139efc9..c49310b30a6 100644 --- a/exporter/opentelemetry-exporter-opencensus/tests/test_otcollector_trace_exporter.py +++ b/exporter/opentelemetry-exporter-opencensus/tests/test_otcollector_trace_exporter.py @@ -96,7 +96,7 @@ def test_translate_to_collector(self): trace_flags=TraceFlags(TraceFlags.SAMPLED), trace_state=trace_api.TraceState({"testKey": "testValue"}), ) - parent_context = trace_api.SpanContext( + parent_span_context = trace_api.SpanContext( trace_id, parent_id, is_remote=False ) other_context = trace_api.SpanContext( @@ -118,19 +118,19 @@ def test_translate_to_collector(self): context=other_context, attributes=link_attributes ) link_2 = trace_api.Link( - context=parent_context, attributes=link_attributes + context=parent_span_context, attributes=link_attributes ) span_1 = trace._Span( name="test1", context=span_context, - parent=parent_context, + parent=parent_span_context, events=(event,), links=(link_1,), kind=trace_api.SpanKind.CLIENT, ) span_2 = trace._Span( name="test2", - context=parent_context, + context=parent_span_context, parent=None, kind=trace_api.SpanKind.SERVER, ) @@ -138,7 +138,7 @@ def test_translate_to_collector(self): name="test3", context=other_context, links=(link_2,), - parent=span_2.get_context(), + parent=span_2.get_span_context(), ) otel_spans = [span_1, span_2, span_3] otel_spans[0].start(start_time=start_times[0]) diff --git a/exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/__init__.py b/exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/__init__.py index bacfcc278d3..c8578c9649c 100644 --- a/exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/__init__.py +++ b/exporter/opentelemetry-exporter-zipkin/src/opentelemetry/exporter/zipkin/__init__.py @@ -159,7 +159,7 @@ def _translate_to_zipkin(self, spans: Sequence[Span]): zipkin_spans = [] for span in spans: - context = span.get_context() + context = span.get_span_context() trace_id = context.trace_id span_id = context.span_id @@ -205,7 +205,7 @@ def _translate_to_zipkin(self, spans: Sequence[Span]): if isinstance(span.parent, Span): zipkin_span["parentId"] = format( - span.parent.get_context().span_id, "016x" + span.parent.get_span_context().span_id, "016x" ) elif isinstance(span.parent, SpanContext): zipkin_span["parentId"] = format(span.parent.span_id, "016x") diff --git a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py index 8d6d8bb8604..c3098da8847 100644 --- a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py +++ b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py @@ -127,7 +127,7 @@ def test_export(self): is_remote=False, trace_flags=TraceFlags(TraceFlags.SAMPLED), ) - parent_context = trace_api.SpanContext( + parent_span_context = trace_api.SpanContext( trace_id, parent_id, is_remote=False ) other_context = trace_api.SpanContext( @@ -157,12 +157,12 @@ def test_export(self): trace._Span( name=span_names[0], context=span_context, - parent=parent_context, + parent=parent_span_context, events=(event,), links=(link,), ), trace._Span( - name=span_names[1], context=parent_context, parent=None + name=span_names[1], context=parent_span_context, parent=None ), trace._Span( name=span_names[2], context=other_context, parent=None @@ -328,12 +328,14 @@ def test_zero_padding(self): is_remote=False, trace_flags=TraceFlags(TraceFlags.SAMPLED), ) - parent_context = trace_api.SpanContext( + parent_span_context = trace_api.SpanContext( trace_id, parent_id, is_remote=False ) otel_span = trace._Span( - name=span_names[0], context=span_context, parent=parent_context, + name=span_names[0], + context=span_context, + parent=parent_span_context, ) otel_span.start(start_time=start_time) diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py index d2cc90902eb..176fc82b40c 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py @@ -63,7 +63,7 @@ class AiopgInstrumentor(BaseInstrumentor): def _instrument(self, **kwargs): """Integrate with PostgreSQL aiopg library. - aiopg: https://github.com/aio-libs/aiopg + aiopg: https://github.com/aio-libs/aiopg """ tracer_provider = kwargs.get("tracer_provider") diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py index b6992120f3c..1455f23e629 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py @@ -37,8 +37,7 @@ async def wrapped_connection( args: typing.Tuple[typing.Any, typing.Any], kwargs: typing.Dict[typing.Any, typing.Any], ): - """Add object proxy to connection object. - """ + """Add object proxy to connection object.""" connection = await connect_method(*args, **kwargs) # pylint: disable=protected-access self.get_connection_attributes(connection._conn) @@ -109,10 +108,14 @@ async def traced_execution( self._populate_span(span, *args) try: result = await query_method(*args, **kwargs) - span.set_status(Status(StatusCanonicalCode.OK)) + if span.is_recording(): + span.set_status(Status(StatusCanonicalCode.OK)) return result except Exception as ex: # pylint: disable=broad-except - span.set_status(Status(StatusCanonicalCode.UNKNOWN, str(ex))) + if span.is_recording(): + span.set_status( + Status(StatusCanonicalCode.UNKNOWN, str(ex)) + ) raise ex diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py index 473c5039c32..8a3b6023bd5 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py @@ -56,16 +56,16 @@ def trace_integration( tracer_provider: typing.Optional[TracerProvider] = None, ): """Integrate with aiopg library. - based on dbapi integration, where replaced sync wrap methods to async - - Args: - database_component: Database driver name or - database name "postgreSQL". - database_type: The Database type. For any SQL database, "sql". - connection_attributes: Attribute names for database, port, host and - user in Connection object. - tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to - use. If ommited the current configured one is used. + based on dbapi integration, where replaced sync wrap methods to async + + Args: + database_component: Database driver name or + database name "postgreSQL". + database_type: The Database type. For any SQL database, "sql". + connection_attributes: Attribute names for database, port, host and + user in Connection object. + tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to + use. If ommited the current configured one is used. """ wrap_connect( @@ -87,18 +87,18 @@ def wrap_connect( tracer_provider: typing.Optional[TracerProvider] = None, ): """Integrate with aiopg library. - https://github.com/aio-libs/aiopg - - Args: - name: Name of opentelemetry extension for aiopg. - database_component: Database driver name - or database name "postgreSQL". - database_type: The Database type. For any SQL database, "sql". - connection_attributes: Attribute names for database, port, host and - user in Connection object. - version: Version of opentelemetry extension for aiopg. - tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to - use. If ommited the current configured one is used. + https://github.com/aio-libs/aiopg + + Args: + name: Name of opentelemetry extension for aiopg. + database_component: Database driver name + or database name "postgreSQL". + database_type: The Database type. For any SQL database, "sql". + connection_attributes: Attribute names for database, port, host and + user in Connection object. + version: Version of opentelemetry extension for aiopg. + tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to + use. If ommited the current configured one is used. """ # pylint: disable=unused-argument @@ -125,8 +125,8 @@ async def wrap_connect_( def unwrap_connect(): - """"Disable integration with aiopg library. - https://github.com/aio-libs/aiopg + """Disable integration with aiopg library. + https://github.com/aio-libs/aiopg """ unwrap(aiopg, "connect") @@ -217,7 +217,7 @@ async def wrap_create_pool_( def unwrap_create_pool(): - """"Disable integration with aiopg library. - https://github.com/aio-libs/aiopg + """Disable integration with aiopg library. + https://github.com/aio-libs/aiopg """ unwrap(aiopg, "create_pool") diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py index f7daf7ccc0f..135f9ee9a78 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py @@ -230,6 +230,40 @@ def test_span_succeeded(self): trace_api.status.StatusCanonicalCode.OK, ) + def test_span_not_recording(self): + connection_props = { + "database": "testdatabase", + "server_host": "testhost", + "server_port": 123, + "user": "testuser", + } + connection_attributes = { + "database": "database", + "port": "server_port", + "host": "server_host", + "user": "user", + } + mock_tracer = mock.Mock() + mock_span = mock.Mock() + mock_span.is_recording.return_value = False + mock_tracer.start_span.return_value = mock_span + mock_tracer.use_span.return_value.__enter__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True + db_integration = AiopgIntegration( + mock_tracer, "testcomponent", "testtype", connection_attributes + ) + mock_connection = async_call( + db_integration.wrapped_connection( + mock_connect, {}, connection_props + ) + ) + cursor = async_call(mock_connection.cursor()) + async_call(cursor.execute("Test query", ("param1Value", False))) + self.assertFalse(mock_span.is_recording()) + self.assertTrue(mock_span.is_recording.called) + self.assertFalse(mock_span.set_attribute.called) + self.assertFalse(mock_span.set_status.called) + def test_span_failed(self): db_integration = AiopgIntegration(self.tracer, "testcomponent") mock_connection = async_call( diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py index 189809809d9..6af816b39df 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py @@ -112,9 +112,6 @@ def _uninstrument(self, **__): unwrap(asyncpg.Connection, method) async def _do_execute(self, func, instance, args, kwargs): - span_attributes = _hydrate_span_from_args( - instance, args[0], args[1:] if self.capture_parameters else None, - ) tracer = getattr(asyncpg, _APPLIED) exception = None @@ -122,9 +119,14 @@ async def _do_execute(self, func, instance, args, kwargs): with tracer.start_as_current_span( "postgresql", kind=SpanKind.CLIENT ) as span: - - for attribute, value in span_attributes.items(): - span.set_attribute(attribute, value) + if span.is_recording(): + span_attributes = _hydrate_span_from_args( + instance, + args[0], + args[1:] if self.capture_parameters else None, + ) + for attribute, value in span_attributes.items(): + span.set_attribute(attribute, value) try: result = await func(*args, **kwargs) @@ -132,11 +134,12 @@ async def _do_execute(self, func, instance, args, kwargs): exception = exc raise finally: - if exception is not None: - span.set_status( - Status(_exception_to_canonical_code(exception)) - ) - else: - span.set_status(Status(StatusCanonicalCode.OK)) + if span.is_recording(): + if exception is not None: + span.set_status( + Status(_exception_to_canonical_code(exception)) + ) + else: + span.set_status(Status(StatusCanonicalCode.OK)) return result diff --git a/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py b/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py index 1a8cc2b387f..cb45514c799 100644 --- a/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-boto/tests/test_boto_instrumentation.py @@ -88,7 +88,7 @@ def test_not_recording(self): mock_span.is_recording.return_value = False mock_tracer.start_span.return_value = mock_span mock_tracer.use_span.return_value.__enter__ = mock_span - mock_tracer.use_span.return_value.__exit__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True with patch("opentelemetry.trace.get_tracer") as tracer: tracer.return_value = mock_tracer ec2 = boto.ec2.connect_to_region("us-west-2") diff --git a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py index 9bf691f6570..fba0182eec4 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py @@ -84,7 +84,7 @@ def test_not_recording(self): mock_span.is_recording.return_value = False mock_tracer.start_span.return_value = mock_span mock_tracer.use_span.return_value.__enter__ = mock_span - mock_tracer.use_span.return_value.__exit__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True with patch("opentelemetry.trace.get_tracer") as tracer: tracer.return_value = mock_tracer ec2 = self.session.create_client("ec2", region_name="us-west-2") diff --git a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py index 4768e93d18e..3bd912c5ed0 100644 --- a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/__init__.py @@ -118,14 +118,13 @@ def _trace_prerun(self, *args, **kwargs): return request = task.request - tracectx = propagators.extract(carrier_extractor, request) or {} - parent = get_current_span(tracectx) + tracectx = propagators.extract(carrier_extractor, request) or None logger.debug("prerun signal start task_id=%s", task_id) operation_name = "{0}/{1}".format(_TASK_RUN, task.name) span = self._tracer.start_span( - operation_name, parent=parent, kind=trace.SpanKind.CONSUMER + operation_name, context=tracectx, kind=trace.SpanKind.CONSUMER ) activation = self._tracer.use_span(span, end_on_exit=True) diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py index 551f71555ad..0dcdd5ba606 100644 --- a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py @@ -311,6 +311,8 @@ def __init__(self, db_api_integration: DatabaseApiIntegration): def _populate_span( self, span: trace_api.Span, *args: typing.Tuple[typing.Any, typing.Any] ): + if not span.is_recording(): + return statement = args[0] if args else "" span.set_attribute( "component", self._db_api_integration.database_component @@ -341,10 +343,14 @@ def traced_execution( self._populate_span(span, *args) try: result = query_method(*args, **kwargs) - span.set_status(Status(StatusCanonicalCode.OK)) + if span.is_recording(): + span.set_status(Status(StatusCanonicalCode.OK)) return result except Exception as ex: # pylint: disable=broad-except - span.set_status(Status(StatusCanonicalCode.UNKNOWN, str(ex))) + if span.is_recording(): + span.set_status( + Status(StatusCanonicalCode.UNKNOWN, str(ex)) + ) raise ex diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py index 29915703339..e342e15aa34 100644 --- a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py +++ b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py @@ -69,6 +69,38 @@ def test_span_succeeded(self): trace_api.status.StatusCanonicalCode.OK, ) + def test_span_not_recording(self): + connection_props = { + "database": "testdatabase", + "server_host": "testhost", + "server_port": 123, + "user": "testuser", + } + connection_attributes = { + "database": "database", + "port": "server_port", + "host": "server_host", + "user": "user", + } + mock_tracer = mock.Mock() + mock_span = mock.Mock() + mock_span.is_recording.return_value = False + mock_tracer.start_span.return_value = mock_span + mock_tracer.use_span.return_value.__enter__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True + db_integration = dbapi.DatabaseApiIntegration( + mock_tracer, "testcomponent", "testtype", connection_attributes + ) + mock_connection = db_integration.wrapped_connection( + mock_connect, {}, connection_props + ) + cursor = mock_connection.cursor() + cursor.execute("Test query", ("param1Value", False)) + self.assertFalse(mock_span.is_recording()) + self.assertTrue(mock_span.is_recording.called) + self.assertFalse(mock_span.set_attribute.called) + self.assertFalse(mock_span.set_status.called) + def test_span_failed(self): db_integration = dbapi.DatabaseApiIntegration( self.tracer, "testcomponent" diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py index 07e3eb710b8..11991413eb8 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -17,6 +17,7 @@ from opentelemetry.configuration import Configuration from opentelemetry.context import attach, detach from opentelemetry.instrumentation.django.version import __version__ +from opentelemetry.instrumentation.utils import extract_attributes_from_object from opentelemetry.instrumentation.wsgi import ( add_response_attributes, collect_request_attributes, @@ -111,10 +112,9 @@ def process_request(self, request): if span.is_recording(): attributes = collect_request_attributes(environ) - for attr in self._traced_request_attrs: - value = getattr(request, attr, None) - if value is not None: - attributes[attr] = str(value) + attributes = extract_attributes_from_object( + request, self._traced_request_attrs, attributes + ) for key, value in attributes.items(): span.set_attribute(key, value) diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py index 7e9ab72b523..4db6c485dec 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py @@ -95,7 +95,7 @@ def test_not_recording(self): mock_span.is_recording.return_value = False mock_tracer.start_span.return_value = mock_span mock_tracer.use_span.return_value.__enter__ = mock_span - mock_tracer.use_span.return_value.__exit__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True with patch("opentelemetry.trace.get_tracer") as tracer: tracer.return_value = mock_tracer Client().get("/traced/") diff --git a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py index 660fc23063c..bfcd45a8b58 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py @@ -53,7 +53,10 @@ def on_get(self, req, resp): from opentelemetry.configuration import Configuration from opentelemetry.instrumentation.falcon.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from opentelemetry.instrumentation.utils import http_status_to_canonical_code +from opentelemetry.instrumentation.utils import ( + extract_attributes_from_object, + http_status_to_canonical_code, +) from opentelemetry.trace.status import Status from opentelemetry.util import ExcludeList, time_ns @@ -162,10 +165,11 @@ def process_request(self, req, resp): if not span: return - for attr in self._traced_request_attrs: - value = getattr(req, attr, None) - if value is not None: - span.set_attribute(attr, str(value)) + attributes = extract_attributes_from_object( + req, self._traced_request_attrs + ) + for key, value in attributes.items(): + span.set_attribute(key, value) def process_resource(self, req, resp, resource, params): span = req.env.get(_ENVIRON_SPAN_KEY) diff --git a/instrumentation/opentelemetry-instrumentation-jinja2/tests/test_jinja2.py b/instrumentation/opentelemetry-instrumentation-jinja2/tests/test_jinja2.py index 7f5b52c936d..717431abbb9 100644 --- a/instrumentation/opentelemetry-instrumentation-jinja2/tests/test_jinja2.py +++ b/instrumentation/opentelemetry-instrumentation-jinja2/tests/test_jinja2.py @@ -49,8 +49,8 @@ def test_render_inline_template_with_root(self): # pylint:disable=unbalanced-tuple-unpacking render, template, root = spans[:3] - self.assertIs(render.parent, root.get_context()) - self.assertIs(template.parent, root.get_context()) + self.assertIs(render.parent, root.get_span_context()) + self.assertIs(template.parent, root.get_span_context()) self.assertIsNone(root.parent) def test_render_inline_template(self): @@ -88,8 +88,8 @@ def test_generate_inline_template_with_root(self): # pylint:disable=unbalanced-tuple-unpacking template, generate, root = spans - self.assertIs(generate.parent, root.get_context()) - self.assertIs(template.parent, root.get_context()) + self.assertIs(generate.parent, root.get_span_context()) + self.assertIs(template.parent, root.get_span_context()) self.assertIsNone(root.parent) def test_generate_inline_template(self): @@ -131,11 +131,11 @@ def test_file_template_with_root(self): # pylint:disable=unbalanced-tuple-unpacking compile2, load2, compile1, load1, render, root = spans - self.assertIs(compile2.parent, load2.get_context()) - self.assertIs(load2.parent, root.get_context()) - self.assertIs(compile1.parent, load1.get_context()) - self.assertIs(load1.parent, render.get_context()) - self.assertIs(render.parent, root.get_context()) + self.assertIs(compile2.parent, load2.get_span_context()) + self.assertIs(load2.parent, root.get_span_context()) + self.assertIs(compile1.parent, load1.get_span_context()) + self.assertIs(load1.parent, render.get_span_context()) + self.assertIs(render.parent, root.get_span_context()) self.assertIsNone(root.parent) def test_file_template(self): diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/__init__.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/__init__.py index 6bb22130d8e..63be13fe489 100644 --- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-opentracing-shim/src/opentelemetry/instrumentation/opentracing_shim/__init__.py @@ -378,7 +378,7 @@ def from_context_manager(cls, manager: "ScopeManagerShim", span_cm): """ otel_span = span_cm.__enter__() - span_context = SpanContextShim(otel_span.get_context()) + span_context = SpanContextShim(otel_span.get_span_context()) span = SpanShim(manager.tracer, span_context, otel_span) return cls(manager, span, span_cm) @@ -474,13 +474,13 @@ def active(self) -> "ScopeShim": """ span = get_current_span() - if span.get_context() == INVALID_SPAN_CONTEXT: + if span.get_span_context() == INVALID_SPAN_CONTEXT: return None try: return get_value("scope_shim") except KeyError: - span_context = SpanContextShim(span.get_context()) + span_context = SpanContextShim(span.get_span_context()) wrapped_span = SpanShim(self._tracer, span_context, span) return ScopeShim(self, span=wrapped_span) @@ -630,6 +630,10 @@ def start_span( # Use the specified parent or the active span if possible. Otherwise, # use a `None` parent, which triggers the creation of a new trace. parent = child_of.unwrap() if child_of else None + if isinstance(parent, OtelSpanContext): + parent = DefaultSpan(parent) + + parent_span_context = set_span_in_context(parent) links = [] if references: @@ -645,13 +649,13 @@ def start_span( span = self._otel_tracer.start_span( operation_name, - parent, + context=parent_span_context, links=links, attributes=tags, start_time=start_time_ns, ) - context = SpanContextShim(span.get_context()) + context = SpanContextShim(span.get_span_context()) return SpanShim(self, context, span) def inject(self, span_context, format: object, carrier: object): @@ -714,7 +718,7 @@ def get_as_list(dict_object, key): ctx = propagator.extract(get_as_list, carrier) span = get_current_span(ctx) if span is not None: - otel_context = span.get_context() + otel_context = span.get_span_context() else: otel_context = INVALID_SPAN_CONTEXT diff --git a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_shim.py b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_shim.py index 672e7b02f96..151ca07ba9e 100644 --- a/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_shim.py +++ b/instrumentation/opentelemetry-instrumentation-opentracing-shim/tests/test_shim.py @@ -284,13 +284,17 @@ def test_parent_child_implicit(self): ) # Verify parent-child relationship. - parent_trace_id = parent.span.unwrap().get_context().trace_id - child_trace_id = child.span.unwrap().get_context().trace_id + parent_trace_id = ( + parent.span.unwrap().get_span_context().trace_id + ) + child_trace_id = ( + child.span.unwrap().get_span_context().trace_id + ) self.assertEqual(parent_trace_id, child_trace_id) self.assertEqual( child.span.unwrap().parent, - parent.span.unwrap().get_context(), + parent.span.unwrap().get_span_context(), ) # Verify parent span becomes the active span again. @@ -314,23 +318,26 @@ def test_parent_child_explicit_span(self): with self.shim.start_active_span( "ChildSpan", child_of=parent ) as child: - parent_trace_id = parent.unwrap().get_context().trace_id - child_trace_id = child.span.unwrap().get_context().trace_id + parent_trace_id = parent.unwrap().get_span_context().trace_id + child_trace_id = ( + child.span.unwrap().get_span_context().trace_id + ) self.assertEqual(child_trace_id, parent_trace_id) self.assertEqual( - child.span.unwrap().parent, parent.unwrap().get_context() + child.span.unwrap().parent, + parent.unwrap().get_span_context(), ) with self.shim.start_span("ParentSpan") as parent: child = self.shim.start_span("ChildSpan", child_of=parent) - parent_trace_id = parent.unwrap().get_context().trace_id - child_trace_id = child.unwrap().get_context().trace_id + parent_trace_id = parent.unwrap().get_span_context().trace_id + child_trace_id = child.unwrap().get_span_context().trace_id self.assertEqual(child_trace_id, parent_trace_id) self.assertEqual( - child.unwrap().parent, parent.unwrap().get_context() + child.unwrap().parent, parent.unwrap().get_span_context() ) child.finish() @@ -344,8 +351,10 @@ def test_parent_child_explicit_span_context(self): with self.shim.start_active_span( "ChildSpan", child_of=parent.context ) as child: - parent_trace_id = parent.unwrap().get_context().trace_id - child_trace_id = child.span.unwrap().get_context().trace_id + parent_trace_id = parent.unwrap().get_span_context().trace_id + child_trace_id = ( + child.span.unwrap().get_span_context().trace_id + ) self.assertEqual(child_trace_id, parent_trace_id) self.assertEqual( @@ -356,8 +365,8 @@ def test_parent_child_explicit_span_context(self): with self.shim.start_span( "SpanWithContextParent", child_of=parent.context ) as child: - parent_trace_id = parent.unwrap().get_context().trace_id - child_trace_id = child.unwrap().get_context().trace_id + parent_trace_id = parent.unwrap().get_span_context().trace_id + child_trace_id = child.unwrap().get_span_context().trace_id self.assertEqual(child_trace_id, parent_trace_id) self.assertEqual( diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py b/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py index 629b2f62b65..cb127c7a5ef 100644 --- a/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py +++ b/instrumentation/opentelemetry-instrumentation-psycopg2/tests/test_psycopg2_integration.py @@ -60,6 +60,29 @@ def test_instrumentor(self, mock_connect): spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 1) + @mock.patch("psycopg2.connect") + # pylint: disable=unused-argument + def test_not_recording(self, mock_connect): + mock_tracer = mock.Mock() + mock_span = mock.Mock() + mock_span.is_recording.return_value = False + mock_tracer.start_span.return_value = mock_span + mock_tracer.use_span.return_value.__enter__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True + Psycopg2Instrumentor().instrument() + with mock.patch("opentelemetry.trace.get_tracer") as tracer: + tracer.return_value = mock_tracer + cnx = psycopg2.connect(database="test") + cursor = cnx.cursor() + query = "SELECT * FROM test" + cursor.execute(query) + self.assertFalse(mock_span.is_recording()) + self.assertTrue(mock_span.is_recording.called) + self.assertFalse(mock_span.set_attribute.called) + self.assertFalse(mock_span.set_status.called) + + Psycopg2Instrumentor().uninstrument() + @mock.patch("psycopg2.connect") # pylint: disable=unused-argument def test_custom_tracer_provider(self, mock_connect): diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py b/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py index 332e92ccdde..46b188a3dfa 100644 --- a/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-pymemcache/src/opentelemetry/instrumentation/pymemcache/__init__.py @@ -90,13 +90,14 @@ def _set_connection_attributes(span, instance): + if not span.is_recording(): + return for key, value in _get_address_attributes(instance).items(): span.set_attribute(key, value) def _with_tracer_wrapper(func): - """Helper for providing tracer for wrapper functions. - """ + """Helper for providing tracer for wrapper functions.""" def _with_tracer(tracer, cmd): def wrapper(wrapped, instance, args, kwargs): diff --git a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py index 794da9972be..b38bedf3fd8 100644 --- a/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py +++ b/instrumentation/opentelemetry-instrumentation-pymemcache/tests/test_pymemcache.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from unittest import mock import pymemcache from pymemcache.exceptions import ( @@ -84,6 +85,23 @@ def test_set_success(self): self.check_spans(spans, 1, ["set key"]) + def test_set_not_recording(self): + mock_tracer = mock.Mock() + mock_span = mock.Mock() + mock_span.is_recording.return_value = False + mock_tracer.start_span.return_value = mock_span + mock_tracer.use_span.return_value.__enter__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True + with mock.patch("opentelemetry.trace.get_tracer") as tracer: + tracer.return_value = mock_tracer + client = self.make_client([b"STORED\r\n"]) + result = client.set(b"key", b"value", noreply=False) + self.assertTrue(result) + self.assertFalse(mock_span.is_recording()) + self.assertTrue(mock_span.is_recording.called) + self.assertFalse(mock_span.set_attribute.called) + self.assertFalse(mock_span.set_status.called) + def test_get_many_none_found(self): client = self.make_client([b"END\r\n"]) result = client.get_many([b"key1", b"key2"]) diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py b/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py index 4cfff745d17..bb20fd5442c 100644 --- a/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-pymongo/src/opentelemetry/instrumentation/pymongo/__init__.py @@ -71,28 +71,32 @@ def started(self, event: monitoring.CommandStartedEvent): try: span = self._tracer.start_span(name, kind=SpanKind.CLIENT) - span.set_attribute("component", DATABASE_TYPE) - span.set_attribute("db.type", DATABASE_TYPE) - span.set_attribute("db.instance", event.database_name) - span.set_attribute("db.statement", statement) - if event.connection_id is not None: - span.set_attribute("net.peer.name", event.connection_id[0]) - span.set_attribute("net.peer.port", event.connection_id[1]) - - # pymongo specific, not specified by spec - span.set_attribute("db.mongo.operation_id", event.operation_id) - span.set_attribute("db.mongo.request_id", event.request_id) - - for attr in COMMAND_ATTRIBUTES: - _attr = event.command.get(attr) - if _attr is not None: - span.set_attribute("db.mongo." + attr, str(_attr)) + if span.is_recording(): + span.set_attribute("component", DATABASE_TYPE) + span.set_attribute("db.type", DATABASE_TYPE) + span.set_attribute("db.instance", event.database_name) + span.set_attribute("db.statement", statement) + if event.connection_id is not None: + span.set_attribute("net.peer.name", event.connection_id[0]) + span.set_attribute("net.peer.port", event.connection_id[1]) + + # pymongo specific, not specified by spec + span.set_attribute("db.mongo.operation_id", event.operation_id) + span.set_attribute("db.mongo.request_id", event.request_id) + + for attr in COMMAND_ATTRIBUTES: + _attr = event.command.get(attr) + if _attr is not None: + span.set_attribute("db.mongo." + attr, str(_attr)) # Add Span to dictionary self._span_dict[_get_span_dict_key(event)] = span except Exception as ex: # noqa pylint: disable=broad-except if span is not None: - span.set_status(Status(StatusCanonicalCode.INTERNAL, str(ex))) + if span.is_recording(): + span.set_status( + Status(StatusCanonicalCode.INTERNAL, str(ex)) + ) span.end() self._pop_span(event) @@ -103,8 +107,11 @@ def succeeded(self, event: monitoring.CommandSucceededEvent): span = self._pop_span(event) if span is None: return - span.set_attribute("db.mongo.duration_micros", event.duration_micros) - span.set_status(Status(StatusCanonicalCode.OK, event.reply)) + if span.is_recording(): + span.set_attribute( + "db.mongo.duration_micros", event.duration_micros + ) + span.set_status(Status(StatusCanonicalCode.OK, event.reply)) span.end() def failed(self, event: monitoring.CommandFailedEvent): @@ -114,8 +121,11 @@ def failed(self, event: monitoring.CommandFailedEvent): span = self._pop_span(event) if span is None: return - span.set_attribute("db.mongo.duration_micros", event.duration_micros) - span.set_status(Status(StatusCanonicalCode.UNKNOWN, event.failure)) + if span.is_recording(): + span.set_attribute( + "db.mongo.duration_micros", event.duration_micros + ) + span.set_status(Status(StatusCanonicalCode.UNKNOWN, event.failure)) span.end() def _pop_span(self, event): diff --git a/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py b/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py index a84841b28b2..d5f67cafe8c 100644 --- a/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py +++ b/instrumentation/opentelemetry-instrumentation-pymongo/tests/test_pymongo.py @@ -91,6 +91,22 @@ def test_succeeded(self): self.assertEqual(span.status.description, "reply") self.assertIsNotNone(span.end_time) + def test_not_recording(self): + mock_tracer = mock.Mock() + mock_span = mock.Mock() + mock_span.is_recording.return_value = False + mock_tracer.start_span.return_value = mock_span + mock_tracer.use_span.return_value.__enter__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True + mock_event = MockEvent({}) + command_tracer = CommandTracer(mock_tracer) + command_tracer.started(event=mock_event) + command_tracer.succeeded(event=mock_event) + self.assertFalse(mock_span.is_recording()) + self.assertTrue(mock_span.is_recording.called) + self.assertFalse(mock_span.set_attribute.called) + self.assertFalse(mock_span.set_status.called) + def test_failed(self): mock_event = MockEvent({}) command_tracer = CommandTracer(self.tracer) diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py index 38ba71cb55d..77427b0db7a 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py @@ -93,7 +93,7 @@ def test_not_recording(self): mock_span.is_recording.return_value = False mock_tracer.start_span.return_value = mock_span mock_tracer.use_span.return_value.__enter__ = mock_span - mock_tracer.use_span.return_value.__exit__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True with patch("opentelemetry.trace.get_tracer"): self.client.get("/hello/123") span_list = self.memory_exporter.get_finished_spans() diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py index e2ab78b5356..e1c5db1e940 100644 --- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py @@ -63,6 +63,8 @@ def _set_connection_attributes(span, conn): + if not span.is_recording(): + return for key, value in _extract_conn_attributes( conn.connection_pool.connection_kwargs ).items(): @@ -75,10 +77,11 @@ def _traced_execute_command(func, instance, args, kwargs): with tracer.start_as_current_span( _CMD, kind=trace.SpanKind.CLIENT ) as span: - span.set_attribute("service", tracer.instrumentation_info.name) - span.set_attribute(_RAWCMD, query) - _set_connection_attributes(span, instance) - span.set_attribute("redis.args_length", len(args)) + if span.is_recording(): + span.set_attribute("service", tracer.instrumentation_info.name) + span.set_attribute(_RAWCMD, query) + _set_connection_attributes(span, instance) + span.set_attribute("redis.args_length", len(args)) return func(*args, **kwargs) @@ -91,12 +94,13 @@ def _traced_execute_pipeline(func, instance, args, kwargs): with tracer.start_as_current_span( _CMD, kind=trace.SpanKind.CLIENT ) as span: - span.set_attribute("service", tracer.instrumentation_info.name) - span.set_attribute(_RAWCMD, resource) - _set_connection_attributes(span, instance) - span.set_attribute( - "redis.pipeline_length", len(instance.command_stack) - ) + if span.is_recording(): + span.set_attribute("service", tracer.instrumentation_info.name) + span.set_attribute(_RAWCMD, resource) + _set_connection_attributes(span, instance) + span.set_attribute( + "redis.pipeline_length", len(instance.command_stack) + ) return func(*args, **kwargs) diff --git a/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py b/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py index c306dca3637..3e07ac725e2 100644 --- a/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py +++ b/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py @@ -34,6 +34,25 @@ def test_span_properties(self): self.assertEqual(span.name, "redis.command") self.assertEqual(span.kind, SpanKind.CLIENT) + def test_not_recording(self): + redis_client = redis.Redis() + RedisInstrumentor().instrument(tracer_provider=self.tracer_provider) + + mock_tracer = mock.Mock() + mock_span = mock.Mock() + mock_span.is_recording.return_value = False + mock_tracer.start_span.return_value = mock_span + mock_tracer.use_span.return_value.__enter__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True + with mock.patch("opentelemetry.trace.get_tracer") as tracer: + with mock.patch.object(redis_client, "connection"): + tracer.return_value = mock_tracer + redis_client.get("key") + self.assertFalse(mock_span.is_recording()) + self.assertTrue(mock_span.is_recording.called) + self.assertFalse(mock_span.set_attribute.called) + self.assertFalse(mock_span.set_status.called) + def test_instrument_uninstrument(self): redis_client = redis.Redis() RedisInstrumentor().instrument(tracer_provider=self.tracer_provider) diff --git a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py index 2d3636284bb..678499e8794 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py +++ b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py @@ -198,12 +198,12 @@ def test_distributed_context(self): headers = dict(httpretty.last_request().headers) self.assertIn(MockTextMapPropagator.TRACE_ID_KEY, headers) self.assertEqual( - str(span.get_context().trace_id), + str(span.get_span_context().trace_id), headers[MockTextMapPropagator.TRACE_ID_KEY], ) self.assertIn(MockTextMapPropagator.SPAN_ID_KEY, headers) self.assertEqual( - str(span.get_context().span_id), + str(span.get_span_context().span_id), headers[MockTextMapPropagator.SPAN_ID_KEY], ) diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py index df80c4841c3..83a5b82b235 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py @@ -79,15 +79,16 @@ def __init__(self, tracer, service, engine): def _before_cur_exec(self, conn, cursor, statement, *args): self.current_span = self.tracer.start_span(self.name) with self.tracer.use_span(self.current_span, end_on_exit=False): - self.current_span.set_attribute("service", self.vendor) - self.current_span.set_attribute(_STMT, statement) + if self.current_span.is_recording(): + self.current_span.set_attribute("service", self.vendor) + self.current_span.set_attribute(_STMT, statement) - if not _set_attributes_from_url( - self.current_span, conn.engine.url - ): - _set_attributes_from_cursor( - self.current_span, self.vendor, cursor - ) + if not _set_attributes_from_url( + self.current_span, conn.engine.url + ): + _set_attributes_from_cursor( + self.current_span, self.vendor, cursor + ) # pylint: disable=unused-argument def _after_cur_exec(self, conn, cursor, statement, *args): @@ -95,7 +96,11 @@ def _after_cur_exec(self, conn, cursor, statement, *args): return try: - if cursor and cursor.rowcount >= 0: + if ( + cursor + and cursor.rowcount >= 0 + and self.current_span.is_recording() + ): self.current_span.set_attribute(_ROWS, cursor.rowcount) finally: self.current_span.end() @@ -105,30 +110,34 @@ def _handle_error(self, context): return try: - self.current_span.set_status( - Status( - StatusCanonicalCode.UNKNOWN, - str(context.original_exception), + if self.current_span.is_recording(): + self.current_span.set_status( + Status( + StatusCanonicalCode.UNKNOWN, + str(context.original_exception), + ) ) - ) finally: self.current_span.end() def _set_attributes_from_url(span: trace.Span, url): """Set connection tags from the url. return true if successful.""" - if url.host: - span.set_attribute(_HOST, url.host) - if url.port: - span.set_attribute(_PORT, url.port) - if url.database: - span.set_attribute(_DB, url.database) + if span.is_recording(): + if url.host: + span.set_attribute(_HOST, url.host) + if url.port: + span.set_attribute(_PORT, url.port) + if url.database: + span.set_attribute(_DB, url.database) return bool(url.host) def _set_attributes_from_cursor(span: trace.Span, vendor, cursor): """Attempt to set db connection attributes by introspecting the cursor.""" + if not span.is_recording(): + return if vendor == "postgres": # pylint: disable=import-outside-toplevel from psycopg2.extensions import parse_dsn diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py index 06593da94fd..3b2e3548a5c 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/tests/test_sqlalchemy.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from unittest import mock from sqlalchemy import create_engine @@ -37,6 +38,28 @@ def test_trace_integration(self): self.assertEqual(len(spans), 1) self.assertEqual(spans[0].name, "sqlite.query") + def test_not_recording(self): + mock_tracer = mock.Mock() + mock_span = mock.Mock() + mock_span.is_recording.return_value = False + mock_tracer.start_span.return_value = mock_span + mock_tracer.use_span.return_value.__enter__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True + with mock.patch("opentelemetry.trace.get_tracer") as tracer: + tracer.return_value = mock_tracer + engine = create_engine("sqlite:///:memory:") + SQLAlchemyInstrumentor().instrument( + engine=engine, + tracer_provider=self.tracer_provider, + service="my-database", + ) + cnx = engine.connect() + cnx.execute("SELECT 1 + 1;").fetchall() + self.assertFalse(mock_span.is_recording()) + self.assertTrue(mock_span.is_recording.called) + self.assertFalse(mock_span.set_attribute.called) + self.assertFalse(mock_span.set_status.called) + def test_create_engine_wrapper(self): SQLAlchemyInstrumentor().instrument() from sqlalchemy import create_engine # pylint: disable-all diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/tests/test_sqlite3.py b/instrumentation/opentelemetry-instrumentation-sqlite3/tests/test_sqlite3.py index a4444e7d937..0e385cf3e76 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlite3/tests/test_sqlite3.py +++ b/instrumentation/opentelemetry-instrumentation-sqlite3/tests/test_sqlite3.py @@ -52,7 +52,7 @@ def validate_spans(self): self.assertEqual(root_span.name, "rootSpan") self.assertEqual(child_span.name, "sqlite3") self.assertIsNotNone(child_span.parent) - self.assertIs(child_span.parent, root_span.get_context()) + self.assertIs(child_span.parent, root_span.get_span_context()) self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT) def test_execute(self): diff --git a/instrumentation/opentelemetry-instrumentation-tornado/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-tornado/CHANGELOG.md index 7cc628718de..e82446d66d7 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/CHANGELOG.md +++ b/instrumentation/opentelemetry-instrumentation-tornado/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Added support for `OTEL_PYTHON_TORNADO_TRACED_REQUEST_ATTRS` ([#1178](https://github.com/open-telemetry/opentelemetry-python/pull/1178)) + ## Version 0.13b0 Released 2020-09-17 diff --git a/instrumentation/opentelemetry-instrumentation-tornado/README.rst b/instrumentation/opentelemetry-instrumentation-tornado/README.rst index d84fbd0412c..088c7f0e85d 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/README.rst +++ b/instrumentation/opentelemetry-instrumentation-tornado/README.rst @@ -31,6 +31,18 @@ A comma separated list of paths that should not be automatically traced. For exa Then any requests made to ``/healthz`` and ``/ping`` will not be automatically traced. +Request attributes +******************** +To extract certain attributes from Tornado's request object and use them as span attributes, set the environment variable ``OTEL_PYTHON_TORNADO_TRACED_REQUEST_ATTRS`` to a comma +delimited list of request attribute names. + +For example, + +:: + + export OTEL_PYTHON_TORNADO_TRACED_REQUEST_ATTRS='uri,query' + +will extract path_info and content_type attributes from every traced request and add them as span attributes. References ---------- diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py index 6379d841a03..5357be6d0fc 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py @@ -50,6 +50,7 @@ def get(self): from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.tornado.version import __version__ from opentelemetry.instrumentation.utils import ( + extract_attributes_from_object, http_status_to_canonical_code, unwrap, ) @@ -71,7 +72,17 @@ def get_excluded_urls(): return ExcludeList(urls) +def get_traced_request_attrs(): + attrs = configuration.Configuration().TORNADO_TRACED_REQUEST_ATTRS or "" + if attrs: + attrs = [attr.strip() for attr in attrs.split(",")] + else: + attrs = [] + return attrs + + _excluded_urls = get_excluded_urls() +_traced_attrs = get_traced_request_attrs() class TornadoInstrumentor(BaseInstrumentor): @@ -196,7 +207,7 @@ def _get_attributes_from_request(request): if request.remote_ip: attrs["net.peer.ip"] = request.remote_ip - return attrs + return extract_attributes_from_object(request, _traced_attrs, attrs) def _get_operation_name(handler, request): @@ -211,6 +222,7 @@ def _start_span(tracer, handler, start_time) -> _TraceContext: _get_header_from_request_headers, handler.request.headers, ) ) + span = tracer.start_span( _get_operation_name(handler, handler.request), kind=trace.SpanKind.SERVER, diff --git a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py index d900b5d360e..5b429766ec3 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py @@ -138,7 +138,7 @@ def test_not_recording(self): mock_span.is_recording.return_value = False mock_tracer.start_span.return_value = mock_span mock_tracer.use_span.return_value.__enter__ = mock_span - mock_tracer.use_span.return_value.__exit__ = mock_span + mock_tracer.use_span.return_value.__exit__ = True with patch("opentelemetry.trace.get_tracer") as tracer: tracer.return_value = mock_tracer self.fetch("/") @@ -354,6 +354,21 @@ def test_excluded(path): test_excluded("/healthz") test_excluded("/ping") + @patch( + "opentelemetry.instrumentation.tornado._traced_attrs", + ["uri", "full_url", "query"], + ) + def test_traced_attrs(self): + self.fetch("/ping?q=abc&b=123") + spans = self.sorted_spans(self.memory_exporter.get_finished_spans()) + self.assertEqual(len(spans), 2) + server_span = spans[0] + self.assertEqual(server_span.kind, SpanKind.SERVER) + self.assert_span_has_attributes( + server_span, {"uri": "/ping?q=abc&b=123", "query": "q=abc&b=123"} + ) + self.memory_exporter.clear() + class TestTornadoUninstrument(TornadoTest): def test_uninstrument(self): diff --git a/opentelemetry-api/CHANGELOG.md b/opentelemetry-api/CHANGELOG.md index adccf96cdf2..6504826c576 100644 --- a/opentelemetry-api/CHANGELOG.md +++ b/opentelemetry-api/CHANGELOG.md @@ -12,6 +12,8 @@ ([#1194](https://github.com/open-telemetry/opentelemetry-python/pull/1194)) - Make instances of SpanContext immutable ([#1134](https://github.com/open-telemetry/opentelemetry-python/pull/1134)) +- Parent is now always passed in via Context, intead of Span or SpanContext + ([#1146](https://github.com/open-telemetry/opentelemetry-python/pull/1146)) ## Version 0.13b0 diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 5aa5c7f33c7..f10cb0312a0 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -49,8 +49,11 @@ When creating a span that's "detached" from the context the active span doesn't change, and the caller is responsible for managing the span's lifetime:: - # Explicit parent span assignment - child = tracer.start_span("child", parent=parent) + # Explicit parent span assignment is done via the Context + from opentelemetry.trace import set_span_in_context + + context = set_span_in_context(parent) + child = tracer.start_span("child", context=context) try: do_work(span=child) @@ -77,6 +80,7 @@ from contextlib import contextmanager from logging import getLogger +from opentelemetry.context.context import Context from opentelemetry.trace.ids_generator import IdsGenerator, RandomIdsGenerator from opentelemetry.trace.propagation import ( get_current_span, @@ -102,9 +106,6 @@ logger = getLogger(__name__) -# TODO: quarantine -ParentSpan = typing.Optional[typing.Union["Span", "SpanContext"]] - class LinkBase(abc.ABC): def __init__(self, context: "SpanContext") -> None: @@ -228,7 +229,7 @@ class Tracer(abc.ABC): def start_span( self, name: str, - parent: ParentSpan = CURRENT_SPAN, + context: typing.Optional[Context] = None, kind: SpanKind = SpanKind.INTERNAL, attributes: types.Attributes = None, links: typing.Sequence[Link] = (), @@ -242,8 +243,9 @@ def start_span( method, see :meth:`start_as_current_span`. By default the current span in the context will be used as parent, but an - explicit parent can also be specified, either a `Span` or a `opentelemetry.trace.SpanContext`. - If the specified value is `None`, the created span will be a root span. + explicit context can also be specified, by passing in a `Context` containing + a current `Span`. If there is no current span in the global `Context` or in + the specified context, the created span will be a root span. The span can be used as a context manager. On exiting the context manager, the span's end() method will be called. @@ -257,7 +259,8 @@ def start_span( Args: name: The name of the span to be created. - parent: The span's parent. Defaults to the current span. + context: An optional Context containing the span's parent. Defaults to the + global context. kind: The span's kind (relationship to parent). Note that is meaningful even if there is no parent. attributes: The span's attributes. @@ -278,7 +281,7 @@ def start_span( def start_as_current_span( self, name: str, - parent: ParentSpan = CURRENT_SPAN, + context: typing.Optional[Context] = None, kind: SpanKind = SpanKind.INTERNAL, attributes: types.Attributes = None, links: typing.Sequence[Link] = (), @@ -316,7 +319,8 @@ def start_as_current_span( Args: name: The name of the span to be created. - parent: The span's parent. Defaults to the current span. + context: An optional Context containing the span's parent. Defaults to the + global context. kind: The span's kind (relationship to parent). Note that is meaningful even if there is no parent. attributes: The span's attributes. @@ -365,7 +369,7 @@ class DefaultTracer(Tracer): def start_span( self, name: str, - parent: ParentSpan = Tracer.CURRENT_SPAN, + context: typing.Optional[Context] = None, kind: SpanKind = SpanKind.INTERNAL, attributes: types.Attributes = None, links: typing.Sequence[Link] = (), @@ -379,7 +383,7 @@ def start_span( def start_as_current_span( self, name: str, - parent: ParentSpan = Tracer.CURRENT_SPAN, + context: typing.Optional[Context] = None, kind: SpanKind = SpanKind.INTERNAL, attributes: types.Attributes = None, links: typing.Sequence[Link] = (), @@ -459,7 +463,6 @@ def get_tracer_provider() -> TracerProvider: "DefaultTracerProvider", "Link", "LinkBase", - "ParentSpan", "RandomIdsGenerator", "Span", "SpanContext", diff --git a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py index 8627b9a65cb..4b77246ac5e 100644 --- a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py +++ b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py @@ -118,7 +118,7 @@ def inject( See `opentelemetry.trace.propagation.textmap.TextMapPropagator.inject` """ span = trace.get_current_span(context) - span_context = span.get_context() + span_context = span.get_span_context() if span_context == trace.INVALID_SPAN_CONTEXT: return traceparent_string = "00-{:032x}-{:016x}-{:02x}".format( diff --git a/opentelemetry-api/src/opentelemetry/trace/span.py b/opentelemetry-api/src/opentelemetry/trace/span.py index 99620ed1443..2b206468afa 100644 --- a/opentelemetry-api/src/opentelemetry/trace/span.py +++ b/opentelemetry-api/src/opentelemetry/trace/span.py @@ -23,7 +23,7 @@ def end(self, end_time: typing.Optional[int] = None) -> None: """ @abc.abstractmethod - def get_context(self) -> "SpanContext": + def get_span_context(self) -> "SpanContext": """Gets the span's SpanContext. Get an immutable, serializable identifier for this span that can be @@ -237,7 +237,7 @@ class DefaultSpan(Span): def __init__(self, context: "SpanContext") -> None: self._context = context - def get_context(self) -> "SpanContext": + def get_span_context(self) -> "SpanContext": return self._context def is_recording(self) -> bool: diff --git a/opentelemetry-api/tests/propagators/test_global_httptextformat.py b/opentelemetry-api/tests/propagators/test_global_httptextformat.py index 9a97b281297..2668be27c3d 100644 --- a/opentelemetry-api/tests/propagators/test_global_httptextformat.py +++ b/opentelemetry-api/tests/propagators/test_global_httptextformat.py @@ -48,7 +48,7 @@ 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_context = get_current_span(context=ctx).get_span_context() self.assertEqual(span_context.trace_id, self.TRACE_ID) self.assertEqual(span_context.span_id, self.SPAN_ID) diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index 0d5b22b18f5..8e18fcb48d7 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -37,12 +37,14 @@ 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.get_span_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 + span2.get_span_context(), trace.INVALID_SPAN_CONTEXT ) self.assertEqual(span2, trace.INVALID_SPAN) self.assertIs(span2.is_recording(), False) @@ -54,7 +56,7 @@ def test_span(self): def test_default_span(self): span = trace.DefaultSpan(trace.INVALID_SPAN_CONTEXT) - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) + self.assertEqual(span.get_span_context(), trace.INVALID_SPAN_CONTEXT) 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..295e3971a39 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.get_span_context(), trace.SpanContext) def test_headers_with_tracestate(self): """When there is a traceparent and tracestate header, data from @@ -62,7 +62,7 @@ def test_headers_with_tracestate(self): "tracestate": [tracestate_value], }, ) - ).get_context() + ).get_span_context() self.assertEqual(span_context.trace_id, self.TRACE_ID) self.assertEqual(span_context.span_id, self.SPAN_ID) self.assertEqual( @@ -109,7 +109,7 @@ def test_invalid_trace_id(self): }, ) ) - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) + self.assertEqual(span.get_span_context(), trace.INVALID_SPAN_CONTEXT) def test_invalid_parent_id(self): """If the parent id is invalid, we must ignore the full traceparent @@ -140,7 +140,7 @@ def test_invalid_parent_id(self): }, ) ) - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) + self.assertEqual(span.get_span_context(), trace.INVALID_SPAN_CONTEXT) def test_no_send_empty_tracestate(self): """If the tracestate is empty, do not set the header. @@ -179,7 +179,7 @@ def test_format_not_supported(self): }, ) ) - self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT) + self.assertEqual(span.get_span_context(), trace.INVALID_SPAN_CONTEXT) def test_propagate_invalid_context(self): """Do not propagate invalid trace context.""" @@ -202,7 +202,7 @@ def test_tracestate_empty_header(self): }, ) ) - self.assertEqual(span.get_context().trace_state["foo"], "1") + self.assertEqual(span.get_span_context().trace_state["foo"], "1") def test_tracestate_header_with_trailing_comma(self): """Do not propagate invalid trace context. @@ -218,7 +218,7 @@ def test_tracestate_header_with_trailing_comma(self): }, ) ) - self.assertEqual(span.get_context().trace_state["foo"], "1") + self.assertEqual(span.get_span_context().trace_state["foo"], "1") def test_tracestate_keys(self): """Test for valid key patterns in the tracestate @@ -242,9 +242,13 @@ def test_tracestate_keys(self): }, ) ) - self.assertEqual(span.get_context().trace_state["1a-2f@foo"], "bar1") self.assertEqual( - span.get_context().trace_state["1a-_*/2b@foo"], "bar2" + span.get_span_context().trace_state["1a-2f@foo"], "bar1" + ) + self.assertEqual( + span.get_span_context().trace_state["1a-_*/2b@foo"], "bar2" + ) + self.assertEqual(span.get_span_context().trace_state["foo"], "bar3") + self.assertEqual( + span.get_span_context().trace_state["foo-_*/bar"], "bar4" ) - self.assertEqual(span.get_context().trace_state["foo"], "bar3") - self.assertEqual(span.get_context().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..73f068825b1 100644 --- a/opentelemetry-api/tests/trace/test_defaultspan.py +++ b/opentelemetry-api/tests/trace/test_defaultspan.py @@ -27,9 +27,9 @@ def test_ctor(self): trace_state=trace.DEFAULT_TRACE_STATE, ) span = trace.DefaultSpan(context) - self.assertEqual(context, span.get_context()) + self.assertEqual(context, span.get_span_context()) def test_invalid_span(self): 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.get_span_context()) + self.assertFalse(trace.INVALID_SPAN.get_span_context().is_valid) diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py index 8553b1bc63a..6220854ad59 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py @@ -12,11 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. +from typing import Dict, Sequence + from wrapt import ObjectProxy from opentelemetry.trace.status import StatusCanonicalCode +def extract_attributes_from_object( + obj: any, attributes: Sequence[str], existing: Dict[str, str] = None +) -> Dict[str, str]: + extracted = {} + if existing: + extracted.update(existing) + for attr in attributes: + value = getattr(obj, attr, None) + if value is not None: + extracted[attr] = str(value) + return extracted + + def http_status_to_canonical_code( status: int, allow_redirect: bool = True ) -> StatusCanonicalCode: diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index d38ef4a3050..7870da33cb0 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -20,6 +20,8 @@ ([#1162](https://github.com/open-telemetry/opentelemetry-python/pull/1162)) - Adding Resource to MeterRecord ([#1209](https://github.com/open-telemetry/opentelemetry-python/pull/1209)) +- Parent is now always passed in via Context, intead of Span or SpanContext + ([#1146](https://github.com/open-telemetry/opentelemetry-python/pull/1146)) ## Version 0.13b0 diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 5e04d8991b5..d0626a65687 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -350,7 +350,7 @@ class Span(trace_api.Span): name: The name of the operation this span represents context: The immutable span context parent: This span's parent's `opentelemetry.trace.SpanContext`, or - null if this is a root span + None if this is a root span sampler: The sampler used to create this span trace_config: TODO resource: Entity producing telemetry @@ -519,7 +519,7 @@ def to_json(self, indent=4): return json.dumps(f_span, indent=indent) - def get_context(self): + def get_span_context(self): return self.context def set_attribute(self, key: str, value: types.AttributeValue) -> None: @@ -699,13 +699,13 @@ def __init__( def start_as_current_span( self, name: str, - parent: trace_api.ParentSpan = trace_api.Tracer.CURRENT_SPAN, + context: Optional[context_api.Context] = None, kind: trace_api.SpanKind = trace_api.SpanKind.INTERNAL, attributes: types.Attributes = None, links: Sequence[trace_api.Link] = (), record_exception: bool = True, ) -> Iterator[trace_api.Span]: - span = self.start_span(name, parent, kind, attributes, links,) + span = self.start_span(name, context, kind, attributes, links) return self.use_span( span, end_on_exit=True, record_exception=record_exception ) @@ -713,34 +713,34 @@ def start_as_current_span( def start_span( # pylint: disable=too-many-locals self, name: str, - parent: trace_api.ParentSpan = trace_api.Tracer.CURRENT_SPAN, + context: Optional[context_api.Context] = None, kind: trace_api.SpanKind = trace_api.SpanKind.INTERNAL, attributes: types.Attributes = None, links: Sequence[trace_api.Link] = (), start_time: Optional[int] = None, set_status_on_exception: bool = True, ) -> trace_api.Span: - 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() + parent_span_context = trace_api.get_current_span( + context + ).get_span_context() - if parent_context is not None and not isinstance( - parent_context, trace_api.SpanContext + if parent_span_context is not None and not isinstance( + parent_span_context, trace_api.SpanContext ): - raise TypeError("parent must be a Span, SpanContext or None.") + raise TypeError( + "parent_span_context must be a SpanContext or None." + ) - if parent_context is None or not parent_context.is_valid: - parent = parent_context = None + if parent_span_context is None or not parent_span_context.is_valid: + parent_span_context = None trace_id = self.source.ids_generator.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_span_context.trace_id + trace_flags = parent_span_context.trace_flags + trace_state = parent_span_context.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 @@ -748,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_span_context, trace_id, name, attributes, links, ) trace_flags = ( @@ -770,7 +770,7 @@ def start_span( # pylint: disable=too-many-locals span = _Span( name=name, context=context, - parent=parent_context, + parent=parent_span_context, sampler=self.source.sampler, resource=self.source.resource, attributes=sampling_result.attributes.copy(), 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 813b6e85600..8a6b8e2247c 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py @@ -140,7 +140,7 @@ def inject( ) -> None: span = trace.get_current_span(context=context) - span_context = span.get_context() + span_context = span.get_span_context() if span_context == trace.INVALID_SPAN_CONTEXT: return diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py index c40d3e691ee..7a1e10752ea 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/sampling.py @@ -113,7 +113,7 @@ class Sampler(abc.ABC): @abc.abstractmethod def should_sample( self, - parent_context: Optional["SpanContext"], + parent_span_context: Optional["SpanContext"], 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_span_context: Optional["SpanContext"], 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_span_context: Optional["SpanContext"], 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_span_context: Optional["SpanContext"], trace_id: int, name: str, attributes: Attributes = None, # TODO links: Sequence["Link"] = (), ) -> "SamplingResult": - if parent_context is not None: + if parent_span_context is not None: if ( - not parent_context.is_valid - or not parent_context.trace_flags.sampled + not parent_span_context.is_valid + or not parent_span_context.trace_flags.sampled ): return SamplingResult(Decision.DROP) return SamplingResult(Decision.RECORD_AND_SAMPLE, attributes) return self._delegate.should_sample( - parent_context=parent_context, + parent_span_context=parent_span_context, 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..452915d86c4 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.get_span_context()) diff --git a/opentelemetry-sdk/tests/trace/propagation/test_b3_format.py b/opentelemetry-sdk/tests/trace/propagation/test_b3_format.py index b825ea1a755..a788a812c76 100644 --- a/opentelemetry-sdk/tests/trace/propagation/test_b3_format.py +++ b/opentelemetry-sdk/tests/trace/propagation/test_b3_format.py @@ -31,19 +31,19 @@ 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_span_context = trace_api.get_current_span(ctx).get_span_context() - parent = trace._Span("parent", parent_context) + parent = trace._Span("parent", parent_span_context) child = trace._Span( "child", trace_api.SpanContext( - parent_context.trace_id, + parent_span_context.trace_id, trace_api.RandomIdsGenerator().generate_span_id(), is_remote=False, - trace_flags=parent_context.trace_flags, - trace_state=parent_context.trace_state, + trace_flags=parent_span_context.trace_flags, + trace_state=parent_span_context.trace_state, ), - parent=parent.get_context(), + parent=parent.get_span_context(), ) new_carrier = {} @@ -232,7 +232,7 @@ 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() + span_context = trace_api.get_current_span(ctx).get_span_context() self.assertEqual(span_context.trace_id, trace_api.INVALID_TRACE_ID) self.assertEqual(span_context.span_id, trace_api.INVALID_SPAN_ID) @@ -244,7 +244,7 @@ def test_missing_trace_id(self): } ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() + span_context = trace_api.get_current_span(ctx).get_span_context() self.assertEqual(span_context.trace_id, trace_api.INVALID_TRACE_ID) @patch( @@ -268,7 +268,7 @@ def test_invalid_trace_id( } ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() + span_context = trace_api.get_current_span(ctx).get_span_context() self.assertEqual(span_context.trace_id, 1) self.assertEqual(span_context.span_id, 2) @@ -294,7 +294,7 @@ def test_invalid_span_id( } ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() + span_context = trace_api.get_current_span(ctx).get_span_context() self.assertEqual(span_context.trace_id, 1) self.assertEqual(span_context.span_id, 2) @@ -307,7 +307,7 @@ def test_missing_span_id(self): } ctx = FORMAT.extract(get_as_list, carrier) - span_context = trace_api.get_current_span(ctx).get_context() + span_context = trace_api.get_current_span(ctx).get_span_context() self.assertEqual(span_context.span_id, trace_api.INVALID_SPAN_ID) @staticmethod diff --git a/opentelemetry-sdk/tests/trace/test_implementation.py b/opentelemetry-sdk/tests/trace/test_implementation.py index 7e6ede1ae03..961e68d9869 100644 --- a/opentelemetry-sdk/tests/trace/test_implementation.py +++ b/opentelemetry-sdk/tests/trace/test_implementation.py @@ -29,11 +29,13 @@ 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.get_span_context(), INVALID_SPAN_CONTEXT) 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.get_span_context(), INVALID_SPAN_CONTEXT + ) self.assertNotEqual(span2, INVALID_SPAN) self.assertIs(span2.is_recording(), True) @@ -43,5 +45,5 @@ def test_span(self): span = trace._Span() span = trace._Span("name", INVALID_SPAN_CONTEXT) - self.assertEqual(span.get_context(), INVALID_SPAN_CONTEXT) + self.assertEqual(span.get_span_context(), INVALID_SPAN_CONTEXT) self.assertIs(span.is_recording(), True) diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index 7edcfc79b8f..6a0399c28cd 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=too-many-lines import shutil import subprocess import unittest @@ -135,16 +136,19 @@ def test_default_sampler(self): # Check that the default tracer creates real spans via the default # sampler - root_span = tracer.start_span(name="root span", parent=None) + root_span = tracer.start_span(name="root span", context=None) + ctx = trace_api.set_span_in_context(root_span) self.assertIsInstance(root_span, trace.Span) - child_span = tracer.start_span(name="child span", parent=root_span) + child_span = tracer.start_span(name="child span", context=ctx) self.assertIsInstance(child_span, trace.Span) self.assertTrue(root_span.context.trace_flags.sampled) self.assertEqual( - root_span.get_context().trace_flags, trace_api.TraceFlags.SAMPLED + root_span.get_span_context().trace_flags, + trace_api.TraceFlags.SAMPLED, ) self.assertEqual( - child_span.get_context().trace_flags, trace_api.TraceFlags.SAMPLED + child_span.get_span_context().trace_flags, + trace_api.TraceFlags.SAMPLED, ) def test_sampler_no_sampling(self): @@ -153,15 +157,18 @@ def test_sampler_no_sampling(self): # Check that the default tracer creates no-op spans if the sampler # decides not to sampler - root_span = tracer.start_span(name="root span", parent=None) + root_span = tracer.start_span(name="root span", context=None) + ctx = trace_api.set_span_in_context(root_span) self.assertIsInstance(root_span, trace_api.DefaultSpan) - child_span = tracer.start_span(name="child span", parent=root_span) + child_span = tracer.start_span(name="child span", context=ctx) self.assertIsInstance(child_span, trace_api.DefaultSpan) self.assertEqual( - root_span.get_context().trace_flags, trace_api.TraceFlags.DEFAULT + root_span.get_span_context().trace_flags, + trace_api.TraceFlags.DEFAULT, ) self.assertEqual( - child_span.get_context().trace_flags, trace_api.TraceFlags.DEFAULT + child_span.get_span_context().trace_flags, + trace_api.TraceFlags.DEFAULT, ) @@ -174,9 +181,10 @@ def test_start_span_invalid_spancontext(self): eliminates redundant error handling logic in exporters. """ tracer = new_tracer() - new_span = tracer.start_span( - "root", parent=trace_api.INVALID_SPAN_CONTEXT + parent_context = trace_api.set_span_in_context( + trace_api.INVALID_SPAN_CONTEXT ) + new_span = tracer.start_span("root", context=parent_context) self.assertTrue(new_span.context.is_valid) self.assertIsNone(new_span.parent) @@ -250,7 +258,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.get_span_context()) self.assertEqual(child.kind, trace_api.SpanKind.CLIENT) self.assertIsNotNone(child.start_time) @@ -258,8 +266,8 @@ 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() + root_context = root.get_span_context() + child_context = child.get_span_context() self.assertEqual(root_context.trace_id, child_context.trace_id) self.assertNotEqual( root_context.span_id, child_context.span_id @@ -282,13 +290,18 @@ def test_start_span_implicit(self): def test_start_span_explicit(self): tracer = new_tracer() - other_parent = trace_api.SpanContext( - trace_id=0x000000000000000000000000DEADBEEF, - span_id=0x00000000DEADBEF0, - is_remote=False, - trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), + other_parent = trace._Span( + "name", + trace_api.SpanContext( + trace_id=0x000000000000000000000000DEADBEEF, + span_id=0x00000000DEADBEF0, + is_remote=False, + trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), + ), ) + other_parent_context = trace_api.set_span_in_context(other_parent) + self.assertEqual(trace_api.get_current_span(), trace_api.INVALID_SPAN) root = tracer.start_span("root") @@ -299,27 +312,33 @@ def test_start_span_explicit(self): with tracer.use_span(root, True): self.assertIs(trace_api.get_current_span(), root) - with tracer.start_span("stepchild", other_parent) as child: + with tracer.start_span("stepchild", other_parent_context) as child: # The child's parent should be the one passed in, # not the current span. self.assertNotEqual(child.parent, root) - self.assertIs(child.parent, other_parent) + self.assertIs(child.parent, other_parent.get_span_context()) self.assertIsNotNone(child.start_time) self.assertIsNone(child.end_time) # 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) + child_context = child.get_span_context() + self.assertEqual( + other_parent.get_span_context().trace_id, + child_context.trace_id, + ) self.assertNotEqual( - other_parent.span_id, child_context.span_id + other_parent.get_span_context().span_id, + child_context.span_id, ) self.assertEqual( - other_parent.trace_state, child_context.trace_state + other_parent.get_span_context().trace_state, + child_context.trace_state, ) self.assertEqual( - other_parent.trace_flags, child_context.trace_flags + other_parent.get_span_context().trace_flags, + child_context.trace_flags, ) # Verify start_span() did not set the current span. @@ -339,7 +358,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.get_span_context()) # After exiting the child's scope the parent should become the # current span again. @@ -352,12 +371,16 @@ def test_start_as_current_span_implicit(self): def test_start_as_current_span_explicit(self): tracer = new_tracer() - other_parent = trace_api.SpanContext( - trace_id=0x000000000000000000000000DEADBEEF, - span_id=0x00000000DEADBEF0, - is_remote=False, - trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), + other_parent = trace._Span( + "name", + trace_api.SpanContext( + trace_id=0x000000000000000000000000DEADBEEF, + span_id=0x00000000DEADBEF0, + is_remote=False, + trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), + ), ) + other_parent_ctx = trace_api.set_span_in_context(other_parent) self.assertEqual(trace_api.get_current_span(), trace_api.INVALID_SPAN) @@ -369,14 +392,14 @@ def test_start_as_current_span_explicit(self): self.assertIsNone(root.end_time) with tracer.start_as_current_span( - "stepchild", other_parent + "stepchild", other_parent_ctx ) as child: # The child should become the current span as usual, but its # parent should be the one passed in, not the # previously-current span. self.assertIs(trace_api.get_current_span(), child) self.assertNotEqual(child.parent, root) - self.assertIs(child.parent, other_parent) + self.assertIs(child.parent, other_parent.get_span_context()) # After exiting the child's scope the last span on the stack should # become current, not the child's parent. @@ -543,7 +566,7 @@ def test_sampling_attributes(self): "attr-in-both": "decision-attr", } tracer_provider = trace.TracerProvider( - sampling.StaticSampler(sampling.Decision.RECORD_AND_SAMPLE,) + sampling.StaticSampler(sampling.Decision.RECORD_AND_SAMPLE) ) self.tracer = tracer_provider.get_tracer(__name__) @@ -555,7 +578,8 @@ 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.get_span_context().trace_flags, + trace_api.TraceFlags.SAMPLED, ) def test_events(self): diff --git a/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py b/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py index 5be0be9f0ec..fc237fe12b0 100644 --- a/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py +++ b/tests/opentelemetry-docker-tests/tests/mysql/test_mysql_functional.py @@ -68,7 +68,7 @@ def validate_spans(self): self.assertEqual(root_span.name, "rootSpan") self.assertEqual(db_span.name, "mysql.opentelemetry-tests") self.assertIsNotNone(db_span.parent) - self.assertIs(db_span.parent, root_span.get_context()) + self.assertIs(db_span.parent, root_span.get_span_context()) self.assertIs(db_span.kind, trace_api.SpanKind.CLIENT) self.assertEqual(db_span.attributes["db.instance"], MYSQL_DB_NAME) self.assertEqual(db_span.attributes["net.peer.name"], MYSQL_HOST) diff --git a/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py b/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py index e7a0d39b51e..d76cd702ee6 100644 --- a/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py +++ b/tests/opentelemetry-docker-tests/tests/postgres/test_aiopg_functional.py @@ -76,7 +76,7 @@ def validate_spans(self): self.assertEqual(root_span.name, "rootSpan") self.assertEqual(child_span.name, "postgresql.opentelemetry-tests") self.assertIsNotNone(child_span.parent) - self.assertIs(child_span.parent, root_span.get_context()) + self.assertIs(child_span.parent, root_span.get_span_context()) self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT) self.assertEqual( child_span.attributes["db.instance"], POSTGRES_DB_NAME @@ -157,7 +157,7 @@ def validate_spans(self): self.assertEqual(root_span.name, "rootSpan") self.assertEqual(child_span.name, "postgresql.opentelemetry-tests") self.assertIsNotNone(child_span.parent) - self.assertIs(child_span.parent, root_span.get_context()) + self.assertIs(child_span.parent, root_span.get_span_context()) self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT) self.assertEqual( child_span.attributes["db.instance"], POSTGRES_DB_NAME diff --git a/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py b/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py index 27391647818..28db4c064f9 100644 --- a/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py +++ b/tests/opentelemetry-docker-tests/tests/postgres/test_psycopg_functional.py @@ -68,7 +68,7 @@ def validate_spans(self): self.assertEqual(root_span.name, "rootSpan") self.assertEqual(child_span.name, "postgresql.opentelemetry-tests") self.assertIsNotNone(child_span.parent) - self.assertIs(child_span.parent, root_span.get_context()) + self.assertIs(child_span.parent, root_span.get_span_context()) self.assertIs(child_span.kind, trace_api.SpanKind.CLIENT) self.assertEqual( child_span.attributes["db.instance"], POSTGRES_DB_NAME diff --git a/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py b/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py index acb60178d06..577477a2aba 100644 --- a/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py +++ b/tests/opentelemetry-docker-tests/tests/pymongo/test_pymongo_functional.py @@ -51,7 +51,7 @@ def validate_spans(self): self.assertIsNot(root_span, None) self.assertIsNot(pymongo_span, None) self.assertIsNotNone(pymongo_span.parent) - self.assertIs(pymongo_span.parent, root_span.get_context()) + self.assertIs(pymongo_span.parent, root_span.get_span_context()) self.assertIs(pymongo_span.kind, trace_api.SpanKind.CLIENT) self.assertEqual( pymongo_span.attributes["db.instance"], MONGODB_DB_NAME diff --git a/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py b/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py index c5c4d4f4497..7c09025551d 100644 --- a/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py +++ b/tests/opentelemetry-docker-tests/tests/pymysql/test_pymysql_functional.py @@ -65,7 +65,7 @@ def validate_spans(self): self.assertEqual(root_span.name, "rootSpan") self.assertEqual(db_span.name, "mysql.opentelemetry-tests") self.assertIsNotNone(db_span.parent) - self.assertIs(db_span.parent, root_span.get_context()) + self.assertIs(db_span.parent, root_span.get_span_context()) self.assertIs(db_span.kind, trace_api.SpanKind.CLIENT) self.assertEqual(db_span.attributes["db.instance"], MYSQL_DB_NAME) self.assertEqual(db_span.attributes["net.peer.name"], MYSQL_HOST) diff --git a/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py b/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py index 7e6ea2e0446..64984e9c4fa 100644 --- a/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py +++ b/tests/opentelemetry-docker-tests/tests/redis/test_redis_functional.py @@ -109,7 +109,7 @@ def test_parent(self): # confirm the parenting self.assertIsNone(parent_span.parent) - self.assertIs(child_span.parent, parent_span.get_context()) + self.assertIs(child_span.parent, parent_span.get_span_context()) self.assertEqual(parent_span.name, "redis_get") self.assertEqual(parent_span.instrumentation_info.name, "redis_svc") diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py index a438f58eb91..b2d8c0abc51 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/mixins.py @@ -175,7 +175,7 @@ def test_parent(self): # confirm the parenting self.assertIsNone(parent_span.parent) - self.assertIs(child_span.parent, parent_span.get_context()) + self.assertIs(child_span.parent, parent_span.get_span_context()) self.assertEqual(parent_span.name, "sqlalch_op") self.assertEqual(parent_span.instrumentation_info.name, "sqlalch_svc") diff --git a/tests/util/src/opentelemetry/test/mock_textmap.py b/tests/util/src/opentelemetry/test/mock_textmap.py index 92c0f21f0ec..bf46ec32fa1 100644 --- a/tests/util/src/opentelemetry/test/mock_textmap.py +++ b/tests/util/src/opentelemetry/test/mock_textmap.py @@ -84,8 +84,8 @@ def inject( ) -> None: span = trace.get_current_span(context) set_in_carrier( - carrier, self.TRACE_ID_KEY, str(span.get_context().trace_id) + carrier, self.TRACE_ID_KEY, str(span.get_span_context().trace_id) ) set_in_carrier( - carrier, self.SPAN_ID_KEY, str(span.get_context().span_id) + carrier, self.SPAN_ID_KEY, str(span.get_span_context().span_id) )