otlp-test-data 0.9.4__py3-none-any.whl → 0.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- otlp_test_data/__init__.py +192 -0
- {otlp_test_data-0.9.4.dist-info → otlp_test_data-0.10.0.dist-info}/METADATA +6 -4
- otlp_test_data-0.10.0.dist-info/RECORD +4 -0
- otlp_test_data-0.9.4.dist-info/RECORD +0 -4
- otlp_test_data.py +0 -95
- {otlp_test_data-0.9.4.dist-info → otlp_test_data-0.10.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import dataclasses
|
|
5
|
+
import json
|
|
6
|
+
import random
|
|
7
|
+
from typing import Sequence, TYPE_CHECKING
|
|
8
|
+
from typing_extensions import reveal_type as reveal_type # temp
|
|
9
|
+
|
|
10
|
+
import freezegun
|
|
11
|
+
import opentelemetry.trace
|
|
12
|
+
from google.protobuf.json_format import MessageToDict
|
|
13
|
+
from opentelemetry.exporter.otlp.proto.common._internal import trace_encoder
|
|
14
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
15
|
+
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
|
|
16
|
+
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter
|
|
17
|
+
from opentelemetry.sdk.resources import Resource
|
|
18
|
+
from opentelemetry.trace import set_tracer_provider, get_tracer_provider
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from google.protobuf.message import Message
|
|
22
|
+
from opentelemetry.sdk.trace import ReadableSpan
|
|
23
|
+
from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
|
|
24
|
+
ExportTraceServiceRequest,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
tracer = opentelemetry.trace.get_tracer(__name__)
|
|
29
|
+
provider = TracerProvider()
|
|
30
|
+
exporter = InMemorySpanExporter()
|
|
31
|
+
provider.add_span_processor(SimpleSpanProcessor(exporter))
|
|
32
|
+
set_tracer_provider(provider)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclasses.dataclass
|
|
36
|
+
class Config:
|
|
37
|
+
start_time: str = "2020-01-01 00:00:00Z"
|
|
38
|
+
random_seed: int = 42
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
time: freezegun.api.FrozenDateTimeFactory = None # type: ignore
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def sample_proto(config: Config | None = None) -> bytes:
|
|
45
|
+
return _proto_to_bytes(_spans_to_proto_object(sample_spans(config)))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def sample_json(config: Config | None = None) -> bytes:
|
|
49
|
+
return _proto_to_json(_spans_to_proto_object(sample_spans(config)))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def sample_spans(config: Config | None = None) -> Sequence[ReadableSpan]:
|
|
53
|
+
"""Creates and finishes two spans, then returns them as a list."""
|
|
54
|
+
global time
|
|
55
|
+
config = config or Config()
|
|
56
|
+
resource = Resource.create(
|
|
57
|
+
attributes={
|
|
58
|
+
"service.namespace": "1234-1234", # a unique id
|
|
59
|
+
"service.name": "my-service",
|
|
60
|
+
"service.instance.id": "123",
|
|
61
|
+
"int": 42,
|
|
62
|
+
"float": 3.14,
|
|
63
|
+
"bool": False,
|
|
64
|
+
"str": "sss",
|
|
65
|
+
"ints": [42, 0],
|
|
66
|
+
"floats": [3.14, 2.72],
|
|
67
|
+
"strs": ["sss", "shh"],
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
del exporter._finished_spans[:]
|
|
71
|
+
get_tracer_provider()._resource = resource # type: ignore
|
|
72
|
+
|
|
73
|
+
random.seed(config.random_seed)
|
|
74
|
+
|
|
75
|
+
with freezegun.freeze_time(config.start_time) as time: # type: ignore
|
|
76
|
+
workload()
|
|
77
|
+
|
|
78
|
+
return exporter.get_finished_spans()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _spans_to_proto_object(spans: Sequence[ReadableSpan]) -> ExportTraceServiceRequest:
|
|
82
|
+
return trace_encoder.encode_spans(spans)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _proto_to_bytes(data: Message) -> bytes:
|
|
86
|
+
return data.SerializePartialToString()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# FIXME: there are probably 3 different enumerated types in the API
|
|
90
|
+
def _proto_to_json(data: Message) -> bytes:
|
|
91
|
+
dic = MessageToDict(data)
|
|
92
|
+
|
|
93
|
+
for rs in dic["resourceSpans"]:
|
|
94
|
+
for ss in rs["scopeSpans"]:
|
|
95
|
+
for sp in ss["spans"]:
|
|
96
|
+
for k in "parentSpanId spanId traceId".split():
|
|
97
|
+
if k in sp:
|
|
98
|
+
sp[k] = base64.b64decode(sp[k]).hex()
|
|
99
|
+
sp["kind"] = {
|
|
100
|
+
"SPAN_KIND_UNSPECIFIED": 0,
|
|
101
|
+
"SPAN_KIND_INTERNAL": 1,
|
|
102
|
+
"SPAN_KIND_SERVER": 2,
|
|
103
|
+
"SPAN_KIND_CLIENT": 3,
|
|
104
|
+
"SPAN_KIND_PRODUCER": 4,
|
|
105
|
+
"SPAN_KIND_CONSUMER": 5,
|
|
106
|
+
}[sp["kind"]]
|
|
107
|
+
|
|
108
|
+
return json.dumps(dic).encode("utf-8")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def workload():
|
|
112
|
+
series_of_spans()
|
|
113
|
+
# nested_spans()
|
|
114
|
+
# attribute_types()
|
|
115
|
+
# repeated_attributes()
|
|
116
|
+
# events()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def series_of_spans():
|
|
120
|
+
with tracer.start_as_current_span("span-one") as one:
|
|
121
|
+
one.set_attribute("count", "one")
|
|
122
|
+
time.tick()
|
|
123
|
+
|
|
124
|
+
with tracer.start_as_current_span("span-two") as two:
|
|
125
|
+
two.set_attribute("count", "two")
|
|
126
|
+
time.tick()
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def nested_spans():
|
|
130
|
+
outer()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@tracer.start_as_current_span("outer")
|
|
134
|
+
def outer():
|
|
135
|
+
time.tick()
|
|
136
|
+
inner()
|
|
137
|
+
time.tick()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@tracer.start_as_current_span("inner")
|
|
141
|
+
def inner():
|
|
142
|
+
opentelemetry.trace.get_current_span().set_attribute("an-attribute", 42)
|
|
143
|
+
time.tick()
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def attribute_types():
|
|
147
|
+
with tracer.start_as_current_span("attribute-types") as span:
|
|
148
|
+
span.set_attributes(
|
|
149
|
+
{"int": 42, "bool": False, "float": 3.14, "str": "string-cheese"}
|
|
150
|
+
)
|
|
151
|
+
span.set_attributes(
|
|
152
|
+
{
|
|
153
|
+
"ints": [1, 42],
|
|
154
|
+
"bools": [True, False],
|
|
155
|
+
"floats": [2.72, 3.14],
|
|
156
|
+
"strs": ["string-cheese", "strung-cheese"],
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def repeated_attributes():
|
|
162
|
+
with tracer.start_as_current_span("attribute-types") as span:
|
|
163
|
+
span.set_attribute("int", 42)
|
|
164
|
+
span.set_attribute("int", 99)
|
|
165
|
+
|
|
166
|
+
with tracer.start_as_current_span("attribute-types") as span:
|
|
167
|
+
span.set_attributes({"int": 42})
|
|
168
|
+
span.set_attributes({"int": 99})
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def events():
|
|
172
|
+
with tracer.start_as_current_span("attribute-types") as span:
|
|
173
|
+
span.add_event("first event")
|
|
174
|
+
time.tick()
|
|
175
|
+
|
|
176
|
+
span.add_event("second event")
|
|
177
|
+
time.tick()
|
|
178
|
+
|
|
179
|
+
span.add_event(
|
|
180
|
+
"event with attributes",
|
|
181
|
+
attributes={
|
|
182
|
+
"int": 42,
|
|
183
|
+
"bool": False,
|
|
184
|
+
"float": 3.14,
|
|
185
|
+
"str": "string-cheese",
|
|
186
|
+
"ints": [1, 42],
|
|
187
|
+
"bools": [True, False],
|
|
188
|
+
"floats": [2.72, 3.14],
|
|
189
|
+
"strs": ["string-cheese", "strung-cheese"],
|
|
190
|
+
},
|
|
191
|
+
)
|
|
192
|
+
time.tick()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: otlp-test-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Produces OTLP data using OTEL instrumentation
|
|
5
5
|
Classifier: Development Status :: 3 - Alpha
|
|
6
6
|
Classifier: Framework :: OpenTelemetry
|
|
@@ -37,9 +37,10 @@ Produces OTLP data using OTEL instrumentation.
|
|
|
37
37
|
|
|
38
38
|
### Features
|
|
39
39
|
|
|
40
|
-
-
|
|
40
|
+
- Fixed, configurable timestamps
|
|
41
41
|
- aims to cover as much of OTEL API as possible
|
|
42
|
-
-
|
|
42
|
+
- Cover all valid data types
|
|
43
|
+
- Events
|
|
43
44
|
|
|
44
45
|
### Limitations
|
|
45
46
|
|
|
@@ -48,7 +49,8 @@ Produces OTLP data using OTEL instrumentation.
|
|
|
48
49
|
|
|
49
50
|
### TODO
|
|
50
51
|
|
|
51
|
-
- Events
|
|
52
52
|
- Links
|
|
53
53
|
- Baggage
|
|
54
54
|
- Schemata, when https://github.com/open-telemetry/opentelemetry-python/pull/4359 lands
|
|
55
|
+
- Attribute value type coercion, e.g. `class Str(str): ...` and objects with `__str__(self)`.
|
|
56
|
+
- Exceptions
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
otlp_test_data/__init__.py,sha256=7GjDanu2fUzjJDGcwmc9c3sk30HagEcwKChAdWdP42o,5551
|
|
2
|
+
otlp_test_data-0.10.0.dist-info/METADATA,sha256=zOkJOyrE3uWsBPC_HMZ5RVJ4lN0V1W-MTrfIVY88HFk,2112
|
|
3
|
+
otlp_test_data-0.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
4
|
+
otlp_test_data-0.10.0.dist-info/RECORD,,
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
otlp_test_data.py,sha256=AddLeT3jimGkpm9ejMpk64VpP1GzBh5JS9gOlPAa-G0,3091
|
|
2
|
-
otlp_test_data-0.9.4.dist-info/METADATA,sha256=MBAd2l_5Si7lmLjz8fy9LYaUhGDnfnF7FRn0TEHUPmA,2012
|
|
3
|
-
otlp_test_data-0.9.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
4
|
-
otlp_test_data-0.9.4.dist-info/RECORD,,
|
otlp_test_data.py
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import base64
|
|
4
|
-
import dataclasses
|
|
5
|
-
import json
|
|
6
|
-
import random
|
|
7
|
-
from typing import Sequence, TYPE_CHECKING
|
|
8
|
-
from typing_extensions import reveal_type as reveal_type # temp
|
|
9
|
-
|
|
10
|
-
import freezegun
|
|
11
|
-
from google.protobuf.json_format import MessageToDict
|
|
12
|
-
from opentelemetry.exporter.otlp.proto.common._internal import trace_encoder
|
|
13
|
-
from opentelemetry.sdk.trace import TracerProvider
|
|
14
|
-
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
|
|
15
|
-
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter
|
|
16
|
-
|
|
17
|
-
if TYPE_CHECKING:
|
|
18
|
-
from google.protobuf.message import Message
|
|
19
|
-
from opentelemetry.sdk.trace import ReadableSpan
|
|
20
|
-
from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
|
|
21
|
-
ExportTraceServiceRequest,
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@dataclasses.dataclass
|
|
26
|
-
class Config:
|
|
27
|
-
start_time: str = "2020-01-01 00:00:00Z"
|
|
28
|
-
random_seed: int = 42
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
time = None
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def sample_proto(config: Config | None = None) -> bytes:
|
|
35
|
-
return _proto_to_bytes(_spans_to_proto_object(sample_spans(config)))
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def sample_json(config: Config | None = None) -> bytes:
|
|
39
|
-
return _proto_to_json(_spans_to_proto_object(sample_spans(config)))
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def sample_spans(config: Config | None = None) -> Sequence[ReadableSpan]:
|
|
43
|
-
"""Creates and finishes two spans, then returns them as a list."""
|
|
44
|
-
global time
|
|
45
|
-
config = config or Config()
|
|
46
|
-
tracer_provider = TracerProvider()
|
|
47
|
-
exporter = InMemorySpanExporter()
|
|
48
|
-
tracer_provider.add_span_processor(SimpleSpanProcessor(exporter))
|
|
49
|
-
tracer = tracer_provider.get_tracer(__name__)
|
|
50
|
-
|
|
51
|
-
with freezegun.freeze_time(config.start_time) as time:
|
|
52
|
-
random.seed(config.random_seed)
|
|
53
|
-
|
|
54
|
-
# FIXME the workload section is expected to grow a lot
|
|
55
|
-
# TODO: attributes
|
|
56
|
-
# bool, int, float, str
|
|
57
|
-
# list[bool], ...
|
|
58
|
-
# tuple[bool], ...
|
|
59
|
-
# Sequence[bool], ... (maybe)
|
|
60
|
-
with tracer.start_as_current_span("span-one"):
|
|
61
|
-
time.tick()
|
|
62
|
-
with tracer.start_as_current_span("span-two"):
|
|
63
|
-
time.tick()
|
|
64
|
-
|
|
65
|
-
return exporter.get_finished_spans()
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def _spans_to_proto_object(spans: Sequence[ReadableSpan]) -> ExportTraceServiceRequest:
|
|
69
|
-
return trace_encoder.encode_spans(spans)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def _proto_to_bytes(data: Message) -> bytes:
|
|
73
|
-
return data.SerializePartialToString()
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
# FIXME: there are probably 3 different enumerated types in the API
|
|
77
|
-
def _proto_to_json(data: Message) -> bytes:
|
|
78
|
-
dic = MessageToDict(data)
|
|
79
|
-
|
|
80
|
-
for rs in dic["resourceSpans"]:
|
|
81
|
-
for ss in rs["scopeSpans"]:
|
|
82
|
-
for sp in ss["spans"]:
|
|
83
|
-
for k in "parentSpanId spanId traceId".split():
|
|
84
|
-
if k in sp:
|
|
85
|
-
sp[k] = base64.b64decode(sp[k]).hex()
|
|
86
|
-
sp["kind"] = {
|
|
87
|
-
"SPAN_KIND_UNSPECIFIED": 0,
|
|
88
|
-
"SPAN_KIND_INTERNAL": 1,
|
|
89
|
-
"SPAN_KIND_SERVER": 2,
|
|
90
|
-
"SPAN_KIND_CLIENT": 3,
|
|
91
|
-
"SPAN_KIND_PRODUCER": 4,
|
|
92
|
-
"SPAN_KIND_CONSUMER": 5,
|
|
93
|
-
}[sp["kind"]]
|
|
94
|
-
|
|
95
|
-
return json.dumps(dic).encode("utf-8")
|
|
File without changes
|