From 9a20504b2ccf9194266699ee4eff41939dfbd188 Mon Sep 17 00:00:00 2001 From: Kevin Ji <1146876+kevinji@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:02:12 -0700 Subject: [PATCH] Fix use of `link.attributes.dropped`, which may not exist (#4119) --- CHANGELOG.md | 2 ++ .../common/_internal/trace_encoder/__init__.py | 2 +- .../tests/test_otlp_trace_exporter.py | 1 + .../src/opentelemetry/trace/__init__.py | 7 +++++++ opentelemetry-sdk/tests/trace/test_trace.py | 15 ++++++++++++++- 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfdc5686b5..55197c957c 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 +- Fix use of `link.attributes.dropped`, which may not exist + ([#4119](https://github.com/open-telemetry/opentelemetry-python/pull/4119)) - Running mypy on SDK resources ([#4053](https://github.com/open-telemetry/opentelemetry-python/pull/4053)) - Added py.typed file to top-level module diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py index 97cf608ac8..d382159e41 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py +++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py @@ -157,7 +157,7 @@ def _encode_links(links: Sequence[Link]) -> Sequence[PB2SPan.Link]: trace_id=_encode_trace_id(link.context.trace_id), span_id=_encode_span_id(link.context.span_id), attributes=_encode_attributes(link.attributes), - dropped_attributes_count=link.attributes.dropped, + dropped_attributes_count=link.dropped_attributes, flags=_span_flags(link.context), ) pb2_links.append(encoded_link) diff --git a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py index 46624df1e6..c71e5fbd57 100644 --- a/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py +++ b/exporter/opentelemetry-exporter-otlp-proto-grpc/tests/test_otlp_trace_exporter.py @@ -171,6 +171,7 @@ def setUp(self): "attributes": BoundedAttributes( attributes={"a": 1, "b": False} ), + "dropped_attributes": 0, "kind": OTLPSpan.SpanKind.SPAN_KIND_INTERNAL, # pylint: disable=no-member } ) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 5de5a240d6..27400c996f 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -84,6 +84,7 @@ from deprecated import deprecated from opentelemetry import context as context_api +from opentelemetry.attributes import BoundedAttributes from opentelemetry.context.context import Context from opentelemetry.environment_variables import OTEL_PYTHON_TRACER_PROVIDER from opentelemetry.trace.propagation import ( @@ -149,6 +150,12 @@ def __init__( def attributes(self) -> types.Attributes: return self._attributes + @property + def dropped_attributes(self) -> int: + if isinstance(self._attributes, BoundedAttributes): + return self._attributes.dropped + return 0 + _Links = Optional[Sequence[Link]] diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index d039df51ae..779093f736 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -669,6 +669,19 @@ def test_event_dropped_attributes(self): event2 = trace.Event("foo2", {"bar2": "baz2"}) self.assertEqual(event2.dropped_attributes, 0) + def test_link_dropped_attributes(self): + link1 = trace_api.Link( + mock.Mock(spec=trace_api.SpanContext), + BoundedAttributes(0, attributes={"bar1": "baz1"}), + ) + self.assertEqual(link1.dropped_attributes, 1) + + link2 = trace_api.Link( + mock.Mock(spec=trace_api.SpanContext), + {"bar2": "baz2"}, + ) + self.assertEqual(link2.dropped_attributes, 0) + class DummyError(Exception): pass @@ -1897,7 +1910,7 @@ def test_dropped_attributes(self): self.assertEqual(2, span.dropped_attributes) self.assertEqual(3, span.dropped_events) self.assertEqual(2, span.events[0].dropped_attributes) - self.assertEqual(2, span.links[0].attributes.dropped) + self.assertEqual(2, span.links[0].dropped_attributes) def _test_span_limits( self,