diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 7f305dcc0d9..d2f1816cb8a 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -18,7 +18,6 @@ import random import threading from contextlib import contextmanager -from numbers import Number from types import TracebackType from typing import Iterator, Optional, Sequence, Tuple, Type @@ -233,12 +232,16 @@ def set_attribute(self, key: str, value: types.AttributeValue) -> None: logger.warning("Setting attribute on ended span.") return + if not key: + logger.warning("invalid key (empty or null)") + return + if isinstance(value, Sequence): error_message = self._check_attribute_value_sequence(value) if error_message is not None: logger.warning("%s in attribute value sequence", error_message) return - elif not isinstance(value, (bool, str, Number, Sequence)): + elif not isinstance(value, (bool, str, int, float)): logger.warning("invalid type for attribute value") return @@ -254,10 +257,7 @@ def _check_attribute_value_sequence(sequence: Sequence) -> Optional[str]: first_element_type = type(sequence[0]) - if issubclass(first_element_type, Number): - first_element_type = Number - - if first_element_type not in (bool, str, Number): + if first_element_type not in (bool, str, int, float): return "invalid type" for element in sequence: diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index 188c019acc1..2a50f88c258 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -391,7 +391,7 @@ def test_attributes(self): root.set_attribute("empty-list", []) root.set_attribute("list-of-bools", [True, True, False]) - root.set_attribute("list-of-numerics", [123, 3.14, 0]) + root.set_attribute("list-of-numerics", [123, 314, 0]) self.assertEqual(len(root.attributes), 10) self.assertEqual(root.attributes["component"], "http") @@ -409,7 +409,7 @@ def test_attributes(self): root.attributes["list-of-bools"], [True, True, False] ) self.assertEqual( - root.attributes["list-of-numerics"], [123, 3.14, 0] + root.attributes["list-of-numerics"], [123, 314, 0] ) attributes = { @@ -440,6 +440,9 @@ def test_invalid_attribute_values(self): "list-with-non-primitive-data-type", [dict(), 123] ) + root.set_attribute("", 123) + root.set_attribute(None, 123) + self.assertEqual(len(root.attributes), 0) def test_check_sequence_helper(self): @@ -458,8 +461,18 @@ def test_check_sequence_helper(self): ), "different type", ) + self.assertEqual( + trace.Span._check_attribute_value_sequence([1, 2, 3.4, 5]), + "different type", + ) + self.assertIsNone( + trace.Span._check_attribute_value_sequence([1, 2, 3, 5]) + ) + self.assertIsNone( + trace.Span._check_attribute_value_sequence([1.2, 2.3, 3.4, 4.5]) + ) self.assertIsNone( - trace.Span._check_attribute_value_sequence([1, 2, 3.4, 5]) + trace.Span._check_attribute_value_sequence([True, False]) ) self.assertIsNone( trace.Span._check_attribute_value_sequence(["ss", "dw", "fw"])