Skip to content

Commit ddf7eeb

Browse files
authored
Allow None in sequence attributes values (open-telemetry#998) (open-telemetry#1256)
1 parent 97cbc9f commit ddf7eeb

File tree

4 files changed

+41
-21
lines changed

4 files changed

+41
-21
lines changed

opentelemetry-api/src/opentelemetry/util/types.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
bool,
2121
int,
2222
float,
23-
Sequence[str],
24-
Sequence[bool],
25-
Sequence[int],
26-
Sequence[float],
23+
Sequence[Union[None, str]],
24+
Sequence[Union[None, bool]],
25+
Sequence[Union[None, int]],
26+
Sequence[Union[None, float]],
2727
]
2828
Attributes = Optional[Mapping[str, AttributeValue]]
2929
AttributesFormatter = Callable[[], Attributes]

opentelemetry-sdk/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
([#1251](https://github.com/open-telemetry/opentelemetry-python/pull/1251))
77
- Fix b3 propagator entrypoint
88
([#1265](https://github.com/open-telemetry/opentelemetry-python/pull/1265))
9+
- Allow None in sequence attributes values
10+
([#998](https://github.com/open-telemetry/opentelemetry-python/pull/998))
911

1012
## Version 0.14b0
1113

opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -308,34 +308,44 @@ def attributes(self) -> types.Attributes:
308308
def _is_valid_attribute_value(value: types.AttributeValue) -> bool:
309309
"""Checks if attribute value is valid.
310310
311-
An attribute value is valid if it is one of the valid types. If the value
312-
is a sequence, it is only valid if all items in the sequence are of valid
313-
type, not a sequence, and are of the same type.
311+
An attribute value is valid if it is one of the valid types.
312+
If the value is a sequence, it is only valid if all items in the sequence:
313+
- are of the same valid type or None
314+
- are not a sequence
314315
"""
315316

316317
if isinstance(value, Sequence):
317318
if len(value) == 0:
318319
return True
319320

320-
first_element_type = type(value[0])
321-
322-
if first_element_type not in VALID_ATTR_VALUE_TYPES:
323-
logger.warning(
324-
"Invalid type %s in attribute value sequence. Expected one of "
325-
"%s or a sequence of those types",
326-
first_element_type.__name__,
327-
[valid_type.__name__ for valid_type in VALID_ATTR_VALUE_TYPES],
328-
)
329-
return False
330-
331-
for element in list(value)[1:]:
332-
if not isinstance(element, first_element_type):
321+
sequence_first_valid_type = None
322+
for element in value:
323+
if element is None:
324+
continue
325+
element_type = type(element)
326+
if element_type not in VALID_ATTR_VALUE_TYPES:
327+
logger.warning(
328+
"Invalid type %s in attribute value sequence. Expected one of "
329+
"%s or None",
330+
element_type.__name__,
331+
[
332+
valid_type.__name__
333+
for valid_type in VALID_ATTR_VALUE_TYPES
334+
],
335+
)
336+
return False
337+
# The type of the sequence must be homogeneous. The first non-None
338+
# element determines the type of the sequence
339+
if sequence_first_valid_type is None:
340+
sequence_first_valid_type = element_type
341+
elif not isinstance(element, sequence_first_valid_type):
333342
logger.warning(
334343
"Mixed types %s and %s in attribute value sequence",
335-
first_element_type.__name__,
344+
sequence_first_valid_type.__name__,
336345
type(element).__name__,
337346
)
338347
return False
348+
339349
elif not isinstance(value, VALID_ATTR_VALUE_TYPES):
340350
logger.warning(
341351
"Invalid type %s for attribute value. Expected one of %s or a "

opentelemetry-sdk/tests/trace/test_trace.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,14 @@ def test_check_attribute_helper(self):
564564
self.assertTrue(trace._is_valid_attribute_value("hi"))
565565
self.assertTrue(trace._is_valid_attribute_value(3.4))
566566
self.assertTrue(trace._is_valid_attribute_value(15))
567+
# None in sequences are valid
568+
self.assertTrue(trace._is_valid_attribute_value(["A", None, None]))
569+
self.assertTrue(
570+
trace._is_valid_attribute_value(["A", None, None, "B"])
571+
)
572+
self.assertTrue(trace._is_valid_attribute_value([None, None]))
573+
self.assertFalse(trace._is_valid_attribute_value(["A", None, 1]))
574+
self.assertFalse(trace._is_valid_attribute_value([None, "A", None, 1]))
567575

568576
def test_sampling_attributes(self):
569577
sampling_attributes = {

0 commit comments

Comments
 (0)