diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ed8f89e244..c6a84910d08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#1818](https://github.com/open-telemetry/opentelemetry-python/pull/1818)) - Update transient errors retry timeout and retryable status codes ([#1842](https://github.com/open-telemetry/opentelemetry-python/pull/1842)) +- Fix start span behavior when excess links and attributes are included + ([#1856](https://github.com/open-telemetry/opentelemetry-python/pull/1856)) ### Removed - Moved `opentelemetry-instrumentation` to contrib repository. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py index 1bb8ed264fc..981368049fb 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py @@ -81,11 +81,8 @@ def extend(self, seq): @classmethod def from_seq(cls, maxlen, seq): seq = tuple(seq) - if len(seq) > maxlen: - raise ValueError bounded_list = cls(maxlen) - # pylint: disable=protected-access - bounded_list._dq = deque(seq, maxlen=maxlen) + bounded_list.extend(seq) return bounded_list @@ -140,9 +137,7 @@ def __len__(self): @classmethod def from_map(cls, maxlen, mapping): mapping = OrderedDict(mapping) - if len(mapping) > maxlen: - raise ValueError bounded_dict = cls(maxlen) - # pylint: disable=protected-access - bounded_dict._dict = mapping + for key, value in mapping.items(): + bounded_dict[key] = value return bounded_dict diff --git a/opentelemetry-sdk/tests/test_util.py b/opentelemetry-sdk/tests/test_util.py index cacc77dbd98..e003e70789c 100644 --- a/opentelemetry-sdk/tests/test_util.py +++ b/opentelemetry-sdk/tests/test_util.py @@ -61,8 +61,9 @@ def test_from_seq(self): self.assertEqual(len(tuple(blist)), list_len) # sequence too big - with self.assertRaises(ValueError): - BoundedList.from_seq(list_len / 2, self.base) + blist = BoundedList.from_seq(list_len // 2, base_copy) + self.assertEqual(len(blist), list_len // 2) + self.assertEqual(blist.dropped, list_len - (list_len // 2)) def test_append_no_drop(self): """Append max capacity elements to the list without dropping elements.""" @@ -167,8 +168,10 @@ def test_from_map(self): self.assertEqual(len(tuple(bdict)), dic_len) # map too big - with self.assertRaises(ValueError): - BoundedDict.from_map(dic_len / 2, self.base) + half_len = dic_len // 2 + bdict = BoundedDict.from_map(half_len, self.base) + self.assertEqual(len(tuple(bdict)), half_len) + self.assertEqual(bdict.dropped, dic_len - half_len) def test_bounded_dict(self): # create empty dict diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index e2e55bf9d08..236c604e879 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -21,8 +21,6 @@ from typing import Optional from unittest import mock -import pytest - from opentelemetry import trace as trace_api from opentelemetry.context import Context from opentelemetry.sdk import resources, trace @@ -538,6 +536,26 @@ def test_disallow_direct_span_creation(self): # pylint: disable=abstract-class-instantiated trace.Span("name", mock.Mock(spec=trace_api.SpanContext)) + def test_surplus_span_links(self): + # pylint: disable=protected-access + max_links = trace._SPAN_LINK_COUNT_LIMIT + links = [ + trace_api.Link(trace_api.SpanContext(0x1, idx, is_remote=False)) + for idx in range(0, 16 + max_links) + ] + tracer = new_tracer() + with tracer.start_as_current_span("span", links=links) as root: + self.assertEqual(len(root.links), max_links) + + def test_surplus_span_attributes(self): + max_attrs = trace.SPAN_ATTRIBUTE_COUNT_LIMIT + attributes = {str(idx): idx for idx in range(0, 16 + max_attrs)} + tracer = new_tracer() + with tracer.start_as_current_span( + "span", attributes=attributes + ) as root: + self.assertEqual(len(root.attributes), max_attrs) + class TestSpan(unittest.TestCase): # pylint: disable=too-many-public-methods @@ -1303,11 +1321,15 @@ def test_span_environment_limits(self): ) for _ in range(100) ] - with pytest.raises(ValueError): - with tracer.start_as_current_span("root", links=some_links): - pass - with tracer.start_as_current_span("root") as root: + some_attrs = { + "init_attribute_{}".format(idx): idx for idx in range(100) + } + with tracer.start_as_current_span( + "root", links=some_links, attributes=some_attrs + ) as root: + self.assertEqual(len(root.links), 30) + self.assertEqual(len(root.attributes), 10) for idx in range(100): root.set_attribute("my_attribute_{}".format(idx), 0) root.add_event("my_event_{}".format(idx))