Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- Allow passing a custom random number generator to `trace.RandomIdGenerator`.
([#4571](https://github.com/open-telemetry/opentelemetry-python/pull/4571))
- typecheck: add sdk/resources and drop mypy
([#4578](https://github.com/open-telemetry/opentelemetry-python/pull/4578))
- Refactor `BatchLogRecordProcessor` to simplify code and make the control flow more
Expand Down
23 changes: 19 additions & 4 deletions opentelemetry-sdk/src/opentelemetry/sdk/trace/id_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import abc
import random
from random import Random
from typing import Optional

from opentelemetry import trace

Expand Down Expand Up @@ -45,16 +47,29 @@ def generate_trace_id(self) -> int:
class RandomIdGenerator(IdGenerator):
"""The default ID generator for TracerProvider which randomly generates all
bits when generating IDs.

Args:
rng: A random number generator. Defaults to the global random instance.
It is recommended to use a fresh `Random()` instead of the default
to avoid potential conflicts with the global random instance
(duplicate ids across multiple processes when a constant global
random seed is set). In case of a custom implementation, it should
be uniform, as some samplers rely on this randomness to make sampling decisions.
"""

def __init__(self, rng: Optional[Random] = None) -> None:
if rng is None:
rng = random # Just a hack to preserve backward compatibility, otherwise it does not quite match the type hint.
self._rng = rng

def generate_span_id(self) -> int:
span_id = random.getrandbits(64)
span_id = self._rng.getrandbits(64)
while span_id == trace.INVALID_SPAN_ID:
span_id = random.getrandbits(64)
span_id = self._rng.getrandbits(64)
return span_id

def generate_trace_id(self) -> int:
trace_id = random.getrandbits(128)
trace_id = self._rng.getrandbits(128)
while trace_id == trace.INVALID_TRACE_ID:
trace_id = random.getrandbits(128)
trace_id = self._rng.getrandbits(128)
return trace_id