Skip to content

Commit d0bde24

Browse files
authored
bugfix: RandomIdGenerator can generate invalid Span/Trace Ids (#3949)
1 parent ba22b16 commit d0bde24

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
- Fix RandomIdGenerator can generate invalid Span/Trace Ids
11+
([#3949](https://github.com/open-telemetry/opentelemetry-python/pull/3949))
1012
- Add Python 3.12 to tox
1113
([#3616](https://github.com/open-telemetry/opentelemetry-python/pull/3616))
1214

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import abc
1616
import random
1717

18+
from opentelemetry import trace
19+
1820

1921
class IdGenerator(abc.ABC):
2022
@abc.abstractmethod
@@ -46,7 +48,13 @@ class RandomIdGenerator(IdGenerator):
4648
"""
4749

4850
def generate_span_id(self) -> int:
49-
return random.getrandbits(64)
51+
span_id = random.getrandbits(64)
52+
while span_id == trace.INVALID_SPAN_ID:
53+
span_id = random.getrandbits(64)
54+
return span_id
5055

5156
def generate_trace_id(self) -> int:
52-
return random.getrandbits(128)
57+
trace_id = random.getrandbits(128)
58+
while trace_id == trace.INVALID_TRACE_ID:
59+
trace_id = random.getrandbits(128)
60+
return trace_id

opentelemetry-sdk/tests/trace/test_trace.py

+32
Original file line numberDiff line numberDiff line change
@@ -2061,3 +2061,35 @@ def test_tracer_provider_init_default(self, resource_patch, sample_patch):
20612061
sample_patch.assert_called_once()
20622062
self.assertIsNotNone(tracer_provider._span_limits)
20632063
self.assertIsNotNone(tracer_provider._atexit_handler)
2064+
2065+
2066+
class TestRandomIdGenerator(unittest.TestCase):
2067+
_TRACE_ID_MAX_VALUE = 2**128 - 1
2068+
_SPAN_ID_MAX_VALUE = 2**64 - 1
2069+
2070+
@patch(
2071+
"random.getrandbits",
2072+
side_effect=[trace_api.INVALID_SPAN_ID, 0x00000000DEADBEF0],
2073+
)
2074+
def test_generate_span_id_avoids_invalid(self, mock_getrandbits):
2075+
generator = RandomIdGenerator()
2076+
span_id = generator.generate_span_id()
2077+
2078+
self.assertNotEqual(span_id, trace_api.INVALID_SPAN_ID)
2079+
mock_getrandbits.assert_any_call(64)
2080+
self.assertEqual(mock_getrandbits.call_count, 2)
2081+
2082+
@patch(
2083+
"random.getrandbits",
2084+
side_effect=[
2085+
trace_api.INVALID_TRACE_ID,
2086+
0x000000000000000000000000DEADBEEF,
2087+
],
2088+
)
2089+
def test_generate_trace_id_avoids_invalid(self, mock_getrandbits):
2090+
generator = RandomIdGenerator()
2091+
trace_id = generator.generate_trace_id()
2092+
2093+
self.assertNotEqual(trace_id, trace_api.INVALID_TRACE_ID)
2094+
mock_getrandbits.assert_any_call(128)
2095+
self.assertEqual(mock_getrandbits.call_count, 2)

0 commit comments

Comments
 (0)