Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optional scope attribute for tracer creation #4028

Merged
merged 10 commits into from
Jul 18, 2024
15 changes: 14 additions & 1 deletion opentelemetry-api/src/opentelemetry/trace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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.
"""


Expand All @@ -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()
Expand All @@ -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,
)


Expand Down Expand Up @@ -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()

Expand All @@ -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
Expand Down Expand Up @@ -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.

Expand All @@ -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,
)


Expand Down
6 changes: 4 additions & 2 deletions opentelemetry-api/tests/trace/test_globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
2 changes: 2 additions & 0 deletions opentelemetry-api/tests/trace/test_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
Span,
)
from opentelemetry.util._decorator import _agnosticcontextmanager
from opentelemetry.util.types import Attributes


class TestProvider(trace.NoOpTracerProvider):
Expand All @@ -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()

Expand Down
2 changes: 2 additions & 0 deletions opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Expand Down Expand Up @@ -1267,6 +1268,7 @@ def get_tracer(
instrumenting_module_name,
instrumenting_library_version,
schema_url,
attributes,
),
)

Expand Down
32 changes: 28 additions & 4 deletions opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

from deprecated import deprecated

from opentelemetry.attributes import BoundedAttributes
from opentelemetry.util.types import Attributes


class InstrumentationInfo:
"""Immutable information about an instrumentation library module.
Expand Down Expand Up @@ -82,42 +85,56 @@ class InstrumentationScope:
properties.
"""

__slots__ = ("_name", "_version", "_schema_url")
__slots__ = ("_name", "_version", "_schema_url", "_attributes")

def __init__(
self,
name: str,
version: Optional[str] = None,
schema_url: Optional[str] = None,
attributes: Optional[Attributes] = None,
) -> None:
self._name = name
self._version = version
if schema_url is None:
schema_url = ""
self._schema_url = schema_url
self._attributes = BoundedAttributes(attributes=attributes)

def __repr__(self) -> str:
return f"{type(self).__name__}({self._name}, {self._version}, {self._schema_url})"
return f"{type(self).__name__}({self._name}, {self._version}, {self._schema_url}, {self._attributes})"

def __hash__(self) -> int:
return hash((self._name, self._version, self._schema_url))

def __eq__(self, value: object) -> bool:
if not isinstance(value, InstrumentationScope):
return NotImplemented
return (self._name, self._version, self._schema_url) == (
return (
self._name,
self._version,
self._schema_url,
self._attributes,
) == (
value._name,
value._version,
value._schema_url,
value._attributes,
)

def __lt__(self, value: object) -> bool:
if not isinstance(value, InstrumentationScope):
return NotImplemented
return (self._name, self._version, self._schema_url) < (
return (
self._name,
self._version,
self._schema_url,
self._attributes,
) < (
value._name,
value._version,
value._schema_url,
value._attributes,
)

@property
Expand All @@ -132,12 +149,19 @@ def version(self) -> Optional[str]:
def name(self) -> str:
return self._name

@property
def attributes(self) -> Attributes:
return self._attributes

def to_json(self, indent=4) -> str:
return dumps(
{
"name": self._name,
"version": self._version,
"schema_url": self._schema_url,
"attributes": (
dict(self._attributes) if bool(self._attributes) else None
),
},
indent=indent,
)
4 changes: 2 additions & 2 deletions opentelemetry-sdk/tests/metrics/test_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def setUpClass(cls):
metrics=[cls.metric_0, cls.metric_1, cls.metric_2],
schema_url="schema_url_0",
)
cls.scope_metrics_0_str = f'{{"scope": {{"name": "name_0", "version": "version_0", "schema_url": "schema_url_0"}}, "metrics": [{cls.metric_0_str}, {cls.metric_1_str}, {cls.metric_2_str}], "schema_url": "schema_url_0"}}'
cls.scope_metrics_0_str = f'{{"scope": {{"name": "name_0", "version": "version_0", "schema_url": "schema_url_0", "attributes": null}}, "metrics": [{cls.metric_0_str}, {cls.metric_1_str}, {cls.metric_2_str}], "schema_url": "schema_url_0"}}'

cls.scope_metrics_1 = ScopeMetrics(
scope=InstrumentationScope(
Expand All @@ -189,7 +189,7 @@ def setUpClass(cls):
metrics=[cls.metric_0, cls.metric_1, cls.metric_2],
schema_url="schema_url_1",
)
cls.scope_metrics_1_str = f'{{"scope": {{"name": "name_1", "version": "version_1", "schema_url": "schema_url_1"}}, "metrics": [{cls.metric_0_str}, {cls.metric_1_str}, {cls.metric_2_str}], "schema_url": "schema_url_1"}}'
cls.scope_metrics_1_str = f'{{"scope": {{"name": "name_1", "version": "version_1", "schema_url": "schema_url_1", "attributes": null}}, "metrics": [{cls.metric_0_str}, {cls.metric_1_str}, {cls.metric_2_str}], "schema_url": "schema_url_1"}}'

cls.resource_metrics_0 = ResourceMetrics(
resource=Resource(
Expand Down
24 changes: 24 additions & 0 deletions opentelemetry-sdk/tests/trace/test_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading