Skip to content

Commit c8df54b

Browse files
authored
Implement IdsGenerator interface for TracerProvider and include default RandomIdsGenerator (#1153)
1 parent 0e0c3e3 commit c8df54b

File tree

12 files changed

+107
-42
lines changed

12 files changed

+107
-42
lines changed

Diff for: docs/api/trace.ids_generator.rst

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
opentelemetry.trace.ids_generator
2+
=================================
3+
4+
.. automodule:: opentelemetry.trace.ids_generator
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:

Diff for: docs/api/trace.rst

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Submodules
88

99
trace.status
1010
trace.span
11+
trace.ids_generator
1112

1213
Module contents
1314
---------------

Diff for: docs/examples/opentelemetry-example-app/tests/test_flask_example.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import opentelemetry_example_app.flask_example as flask_example
2323
from opentelemetry import trace
24-
from opentelemetry.sdk import trace as trace_sdk
2524

2625

2726
class TestFlaskExample(unittest.TestCase):
@@ -46,7 +45,8 @@ def tearDown(self):
4645
self.send_patcher.stop()
4746

4847
def test_full_path(self):
49-
trace_id = trace_sdk.generate_trace_id()
48+
ids_generator = trace.RandomIdsGenerator()
49+
trace_id = ids_generator.generate_trace_id()
5050
# We need to use the Werkzeug test app because
5151
# The headers are injected at the wsgi layer.
5252
# The flask test app will not include these, and
@@ -58,7 +58,7 @@ def test_full_path(self):
5858
headers={
5959
"traceparent": "00-{:032x}-{:016x}-{:02x}".format(
6060
trace_id,
61-
trace_sdk.generate_span_id(),
61+
ids_generator.generate_span_id(),
6262
trace.TraceFlags.SAMPLED,
6363
)
6464
},

Diff for: exporter/opentelemetry-exporter-datadog/tests/test_datadog_format.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ def get_as_list(dict_object, key):
3030
class TestDatadogFormat(unittest.TestCase):
3131
@classmethod
3232
def setUpClass(cls):
33+
ids_generator = trace_api.RandomIdsGenerator()
3334
cls.serialized_trace_id = propagator.format_trace_id(
34-
trace.generate_trace_id()
35+
ids_generator.generate_trace_id()
3536
)
3637
cls.serialized_parent_id = propagator.format_span_id(
37-
trace.generate_span_id()
38+
ids_generator.generate_span_id()
3839
)
3940
cls.serialized_origin = "origin-service"
4041

@@ -107,7 +108,7 @@ def test_context_propagation(self):
107108
"child",
108109
trace_api.SpanContext(
109110
parent_context.trace_id,
110-
trace.generate_span_id(),
111+
trace_api.RandomIdsGenerator().generate_span_id(),
111112
is_remote=False,
112113
trace_flags=parent_context.trace_flags,
113114
trace_state=parent_context.trace_state,
@@ -152,7 +153,7 @@ def test_sampling_priority_auto_reject(self):
152153
"child",
153154
trace_api.SpanContext(
154155
parent_context.trace_id,
155-
trace.generate_span_id(),
156+
trace_api.RandomIdsGenerator().generate_span_id(),
156157
is_remote=False,
157158
trace_flags=parent_context.trace_flags,
158159
trace_state=parent_context.trace_state,

Diff for: opentelemetry-api/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
([#1123](https://github.com/open-telemetry/opentelemetry-python/pull/1123))
77
- Store `int`s as `int`s in the global Configuration object
88
([#1118](https://github.com/open-telemetry/opentelemetry-python/pull/1118))
9+
- Allow for Custom Trace and Span IDs Generation - `IdsGenerator` for TracerProvider
10+
([#1153](https://github.com/open-telemetry/opentelemetry-python/pull/1153))
911

1012
## Version 0.13b0
1113

Diff for: opentelemetry-api/src/opentelemetry/trace/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
from contextlib import contextmanager
7878
from logging import getLogger
7979

80+
from opentelemetry.trace.ids_generator import IdsGenerator, RandomIdsGenerator
8081
from opentelemetry.trace.propagation import (
8182
get_current_span,
8283
set_span_in_context,
@@ -436,6 +437,7 @@ def get_tracer_provider() -> TracerProvider:
436437
__all__ = [
437438
"DEFAULT_TRACE_OPTIONS",
438439
"DEFAULT_TRACE_STATE",
440+
"IdsGenerator",
439441
"INVALID_SPAN",
440442
"INVALID_SPAN_CONTEXT",
441443
"INVALID_SPAN_ID",
@@ -446,6 +448,7 @@ def get_tracer_provider() -> TracerProvider:
446448
"Link",
447449
"LinkBase",
448450
"ParentSpan",
451+
"RandomIdsGenerator",
449452
"Span",
450453
"SpanContext",
451454
"SpanKind",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import abc
16+
import random
17+
18+
19+
class IdsGenerator(abc.ABC):
20+
@abc.abstractmethod
21+
def generate_span_id(self) -> int:
22+
"""Get a new span ID.
23+
24+
Returns:
25+
A 64-bit int for use as a span ID
26+
"""
27+
28+
@abc.abstractmethod
29+
def generate_trace_id(self) -> int:
30+
"""Get a new trace ID.
31+
32+
Implementations should at least make the 64 least significant bits
33+
uniformly random. Samplers like the `TraceIdRatioBased` sampler rely on
34+
this randomness to make sampling decisions.
35+
36+
See `the specification on TraceIdRatioBased <https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/sdk.md#traceidratiobased>`_.
37+
38+
Returns:
39+
A 128-bit int for use as a trace ID
40+
"""
41+
42+
43+
class RandomIdsGenerator(IdsGenerator):
44+
"""The default IDs generator for TracerProvider which randomly generates all
45+
bits when generating IDs.
46+
"""
47+
48+
def generate_span_id(self) -> int:
49+
return random.getrandbits(64)
50+
51+
def generate_trace_id(self) -> int:
52+
return random.getrandbits(128)

Diff for: opentelemetry-sdk/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
([#1128](https://github.com/open-telemetry/opentelemetry-python/pull/1128))
99
- Add support for `OTEL_BSP_MAX_QUEUE_SIZE`, `OTEL_BSP_SCHEDULE_DELAY_MILLIS`, `OTEL_BSP_MAX_EXPORT_BATCH_SIZE` and `OTEL_BSP_EXPORT_TIMEOUT_MILLIS` environment variables
1010
([#1105](https://github.com/open-telemetry/opentelemetry-python/pull/1120))
11+
- Allow for Custom Trace and Span IDs Generation - `IdsGenerator` for TracerProvider
12+
([#1153](https://github.com/open-telemetry/opentelemetry-python/pull/1153))
1113

1214
## Version 0.13b0
1315

Diff for: opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py

+7-20
Original file line numberDiff line numberDiff line change
@@ -663,24 +663,6 @@ def record_exception(self, exception: Exception) -> None:
663663
)
664664

665665

666-
def generate_span_id() -> int:
667-
"""Get a new random span ID.
668-
669-
Returns:
670-
A random 64-bit int for use as a span ID
671-
"""
672-
return random.getrandbits(64)
673-
674-
675-
def generate_trace_id() -> int:
676-
"""Get a new random trace ID.
677-
678-
Returns:
679-
A random 128-bit int for use as a trace ID
680-
"""
681-
return random.getrandbits(128)
682-
683-
684666
class Tracer(trace_api.Tracer):
685667
"""See `opentelemetry.trace.Tracer`.
686668
@@ -733,7 +715,7 @@ def start_span( # pylint: disable=too-many-locals
733715

734716
if parent_context is None or not parent_context.is_valid:
735717
parent = parent_context = None
736-
trace_id = generate_trace_id()
718+
trace_id = self.source.ids_generator.generate_trace_id()
737719
trace_flags = None
738720
trace_state = None
739721
else:
@@ -757,7 +739,7 @@ def start_span( # pylint: disable=too-many-locals
757739
)
758740
context = trace_api.SpanContext(
759741
trace_id,
760-
generate_span_id(),
742+
self.source.ids_generator.generate_span_id(),
761743
is_remote=False,
762744
trace_flags=trace_flags,
763745
trace_state=trace_state,
@@ -826,10 +808,15 @@ def __init__(
826808
active_span_processor: Union[
827809
SynchronousMultiSpanProcessor, ConcurrentMultiSpanProcessor
828810
] = None,
811+
ids_generator: trace_api.IdsGenerator = None,
829812
):
830813
self._active_span_processor = (
831814
active_span_processor or SynchronousMultiSpanProcessor()
832815
)
816+
if ids_generator is None:
817+
self.ids_generator = trace_api.RandomIdsGenerator()
818+
else:
819+
self.ids_generator = ids_generator
833820
self.resource = resource
834821
self.sampler = sampler
835822
self._atexit_handler = None

Diff for: opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import opentelemetry.trace as trace
1919
from opentelemetry.context import Context
20-
from opentelemetry.sdk.trace import generate_span_id, generate_trace_id
2120
from opentelemetry.trace.propagation.textmap import (
2221
Getter,
2322
Setter,
@@ -103,8 +102,9 @@ def extract(
103102
self._trace_id_regex.fullmatch(trace_id) is None
104103
or self._span_id_regex.fullmatch(span_id) is None
105104
):
106-
trace_id = generate_trace_id()
107-
span_id = generate_span_id()
105+
ids_generator = trace.get_tracer_provider().ids_generator
106+
trace_id = ids_generator.generate_trace_id()
107+
span_id = ids_generator.generate_span_id()
108108
sampled = "0"
109109

110110
else:

Diff for: opentelemetry-sdk/tests/trace/propagation/test_b3_format.py

+17-8
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def get_child_parent_new_carrier(old_carrier):
3838
"child",
3939
trace_api.SpanContext(
4040
parent_context.trace_id,
41-
trace.generate_span_id(),
41+
trace_api.RandomIdsGenerator().generate_span_id(),
4242
is_remote=False,
4343
trace_flags=parent_context.trace_flags,
4444
trace_state=parent_context.trace_state,
@@ -56,14 +56,15 @@ def get_child_parent_new_carrier(old_carrier):
5656
class TestB3Format(unittest.TestCase):
5757
@classmethod
5858
def setUpClass(cls):
59+
ids_generator = trace_api.RandomIdsGenerator()
5960
cls.serialized_trace_id = b3_format.format_trace_id(
60-
trace.generate_trace_id()
61+
ids_generator.generate_trace_id()
6162
)
6263
cls.serialized_span_id = b3_format.format_span_id(
63-
trace.generate_span_id()
64+
ids_generator.generate_span_id()
6465
)
6566
cls.serialized_parent_id = b3_format.format_span_id(
66-
trace.generate_span_id()
67+
ids_generator.generate_span_id()
6768
)
6869

6970
def test_extract_multi_header(self):
@@ -246,8 +247,12 @@ def test_missing_trace_id(self):
246247
span_context = trace_api.get_current_span(ctx).get_context()
247248
self.assertEqual(span_context.trace_id, trace_api.INVALID_TRACE_ID)
248249

249-
@patch("opentelemetry.sdk.trace.propagation.b3_format.generate_trace_id")
250-
@patch("opentelemetry.sdk.trace.propagation.b3_format.generate_span_id")
250+
@patch(
251+
"opentelemetry.sdk.trace.propagation.b3_format.trace.RandomIdsGenerator.generate_trace_id"
252+
)
253+
@patch(
254+
"opentelemetry.sdk.trace.propagation.b3_format.trace.RandomIdsGenerator.generate_span_id"
255+
)
251256
def test_invalid_trace_id(
252257
self, mock_generate_span_id, mock_generate_trace_id
253258
):
@@ -268,8 +273,12 @@ def test_invalid_trace_id(
268273
self.assertEqual(span_context.trace_id, 1)
269274
self.assertEqual(span_context.span_id, 2)
270275

271-
@patch("opentelemetry.sdk.trace.propagation.b3_format.generate_trace_id")
272-
@patch("opentelemetry.sdk.trace.propagation.b3_format.generate_span_id")
276+
@patch(
277+
"opentelemetry.sdk.trace.propagation.b3_format.trace.RandomIdsGenerator.generate_trace_id"
278+
)
279+
@patch(
280+
"opentelemetry.sdk.trace.propagation.b3_format.trace.RandomIdsGenerator.generate_span_id"
281+
)
273282
def test_invalid_span_id(
274283
self, mock_generate_span_id, mock_generate_trace_id
275284
):

Diff for: opentelemetry-sdk/tests/trace/test_trace.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -615,14 +615,15 @@ def test_invalid_event_attributes(self):
615615
self.assertEqual(root.events[3].attributes, {"attr2": (1, 2)})
616616

617617
def test_links(self):
618+
ids_generator = trace_api.RandomIdsGenerator()
618619
other_context1 = trace_api.SpanContext(
619-
trace_id=trace.generate_trace_id(),
620-
span_id=trace.generate_span_id(),
620+
trace_id=ids_generator.generate_trace_id(),
621+
span_id=ids_generator.generate_span_id(),
621622
is_remote=False,
622623
)
623624
other_context2 = trace_api.SpanContext(
624-
trace_id=trace.generate_trace_id(),
625-
span_id=trace.generate_span_id(),
625+
trace_id=ids_generator.generate_trace_id(),
626+
span_id=ids_generator.generate_span_id(),
626627
is_remote=False,
627628
)
628629

0 commit comments

Comments
 (0)