From d4e13bdf95190314b0d21a9357f850fa2e6a4cd3 Mon Sep 17 00:00:00 2001 From: soumyadeepm04 <84105194+soumyadeepm04@users.noreply.github.com> Date: Thu, 18 Jul 2024 19:51:51 -0400 Subject: [PATCH] optional scope attribute for tracer creation (#4028) --- CHANGELOG.md | 2 ++ .../src/opentelemetry/trace/__init__.py | 15 +++++++++++- opentelemetry-api/tests/trace/test_globals.py | 6 +++-- opentelemetry-api/tests/trace/test_proxy.py | 2 ++ .../src/opentelemetry/sdk/trace/__init__.py | 2 ++ opentelemetry-sdk/tests/trace/test_trace.py | 24 +++++++++++++++++++ 6 files changed, 48 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 439a9eb9640..3d0a605580d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- optional scope attribute for tracer creation + ([#4028](https://github.com/open-telemetry/opentelemetry-python/pull/4028)) - OTLP exporter is encoding invalid span/trace IDs in the logs fix ([#4006](https://github.com/open-telemetry/opentelemetry-python/pull/4006)) - Update sdk process resource detector `process.command_args` attribute to also include the executable itself diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 28300f408c3..5de5a240d6f 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -189,6 +189,7 @@ def get_tracer( instrumenting_module_name: str, instrumenting_library_version: typing.Optional[str] = None, schema_url: typing.Optional[str] = None, + attributes: typing.Optional[types.Attributes] = None, ) -> "Tracer": """Returns a `Tracer` for use by the given instrumentation library. @@ -216,6 +217,7 @@ def get_tracer( ``importlib.metadata.version(instrumenting_library_name)``. schema_url: Optional. Specifies the Schema URL of the emitted telemetry. + attributes: Optional. Specifies the attributes of the emitted telemetry. """ @@ -230,6 +232,7 @@ def get_tracer( instrumenting_module_name: str, instrumenting_library_version: typing.Optional[str] = None, schema_url: typing.Optional[str] = None, + attributes: typing.Optional[types.Attributes] = None, ) -> "Tracer": # pylint:disable=no-self-use,unused-argument return NoOpTracer() @@ -249,17 +252,20 @@ def get_tracer( instrumenting_module_name: str, instrumenting_library_version: typing.Optional[str] = None, schema_url: typing.Optional[str] = None, + attributes: typing.Optional[types.Attributes] = None, ) -> "Tracer": if _TRACER_PROVIDER: return _TRACER_PROVIDER.get_tracer( instrumenting_module_name, instrumenting_library_version, schema_url, + attributes, ) return ProxyTracer( instrumenting_module_name, instrumenting_library_version, schema_url, + attributes, ) @@ -407,10 +413,12 @@ def __init__( instrumenting_module_name: str, instrumenting_library_version: typing.Optional[str] = None, schema_url: typing.Optional[str] = None, + attributes: typing.Optional[types.Attributes] = None, ): self._instrumenting_module_name = instrumenting_module_name self._instrumenting_library_version = instrumenting_library_version self._schema_url = schema_url + self._attributes = attributes self._real_tracer: Optional[Tracer] = None self._noop_tracer = NoOpTracer() @@ -424,6 +432,7 @@ def _tracer(self) -> Tracer: self._instrumenting_module_name, self._instrumenting_library_version, self._schema_url, + self._attributes, ) return self._real_tracer return self._noop_tracer @@ -492,6 +501,7 @@ def get_tracer( instrumenting_library_version: typing.Optional[str] = None, tracer_provider: Optional[TracerProvider] = None, schema_url: typing.Optional[str] = None, + attributes: typing.Optional[types.Attributes] = None, ) -> "Tracer": """Returns a `Tracer` for use by the given instrumentation library. @@ -503,7 +513,10 @@ def get_tracer( if tracer_provider is None: tracer_provider = get_tracer_provider() return tracer_provider.get_tracer( - instrumenting_module_name, instrumenting_library_version, schema_url + instrumenting_module_name, + instrumenting_library_version, + schema_url, + attributes, ) diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index fdb213bae93..6860f98e9e4 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -33,10 +33,12 @@ class TestGlobals(TraceGlobalsTest, unittest.TestCase): def test_get_tracer(mock_tracer_provider): # type: ignore """trace.get_tracer should proxy to the global tracer provider.""" trace.get_tracer("foo", "var") - mock_tracer_provider.get_tracer.assert_called_with("foo", "var", None) + mock_tracer_provider.get_tracer.assert_called_with( + "foo", "var", None, None + ) mock_provider = Mock() trace.get_tracer("foo", "var", mock_provider) - mock_provider.get_tracer.assert_called_with("foo", "var", None) + mock_provider.get_tracer.assert_called_with("foo", "var", None, None) class TestGlobalsConcurrency(TraceGlobalsTest, ConcurrencyTestBase): diff --git a/opentelemetry-api/tests/trace/test_proxy.py b/opentelemetry-api/tests/trace/test_proxy.py index 8c20d054913..caf847777cf 100644 --- a/opentelemetry-api/tests/trace/test_proxy.py +++ b/opentelemetry-api/tests/trace/test_proxy.py @@ -24,6 +24,7 @@ Span, ) from opentelemetry.util._decorator import _agnosticcontextmanager +from opentelemetry.util.types import Attributes class TestProvider(trace.NoOpTracerProvider): @@ -32,6 +33,7 @@ def get_tracer( instrumenting_module_name: str, instrumenting_library_version: typing.Optional[str] = None, schema_url: typing.Optional[str] = None, + attributes: typing.Optional[Attributes] = None, ) -> trace.Tracer: return TestTracer() diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index a7094b547c9..58cbf01e08b 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -1230,6 +1230,7 @@ def get_tracer( instrumenting_module_name: str, instrumenting_library_version: typing.Optional[str] = None, schema_url: typing.Optional[str] = None, + attributes: typing.Optional[types.Attributes] = None, ) -> "trace_api.Tracer": if self._disabled: logger.warning("SDK is disabled.") @@ -1267,6 +1268,7 @@ def get_tracer( instrumenting_module_name, instrumenting_library_version, schema_url, + attributes, ), ) diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index 9f375643092..d039df51ae4 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -165,6 +165,30 @@ def test_tracer_provider_accepts_concurrent_multi_span_processor(self): span_processor, tracer_provider._active_span_processor ) + def test_get_tracer_sdk(self): + tracer_provider = trace.TracerProvider() + tracer = tracer_provider.get_tracer( + "module_name", + "library_version", + "schema_url", + {"key1": "value1", "key2": 6}, + ) + # pylint: disable=protected-access + self.assertEqual(tracer._instrumentation_scope._name, "module_name") + # pylint: disable=protected-access + self.assertEqual( + tracer._instrumentation_scope._version, "library_version" + ) + # pylint: disable=protected-access + self.assertEqual( + tracer._instrumentation_scope._schema_url, "schema_url" + ) + # pylint: disable=protected-access + self.assertEqual( + tracer._instrumentation_scope._attributes, + {"key1": "value1", "key2": 6}, + ) + @mock.patch.dict("os.environ", {OTEL_SDK_DISABLED: "true"}) def test_get_tracer_with_sdk_disabled(self): tracer_provider = trace.TracerProvider()