otlp-json 0.9.3__tar.gz → 0.9.4__tar.gz
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_json-0.9.3 → otlp_json-0.9.4}/PKG-INFO +1 -1
- {otlp_json-0.9.3 → otlp_json-0.9.4}/otlp_json/__init__.py +31 -51
- {otlp_json-0.9.3 → otlp_json-0.9.4}/pyproject.toml +1 -1
- {otlp_json-0.9.3 → otlp_json-0.9.4}/uv.lock +7 -7
- {otlp_json-0.9.3 → otlp_json-0.9.4}/.github/workflows/ci.yaml +0 -0
- {otlp_json-0.9.3 → otlp_json-0.9.4}/.gitignore +0 -0
- {otlp_json-0.9.3 → otlp_json-0.9.4}/.pre-commit-config.yaml +0 -0
- {otlp_json-0.9.3 → otlp_json-0.9.4}/otlp_json/py.typed +0 -0
- {otlp_json-0.9.3 → otlp_json-0.9.4}/readme.md +0 -0
- {otlp_json-0.9.3 → otlp_json-0.9.4}/test/test_pure_python.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: otlp-json
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.4
|
|
4
4
|
Summary: 🐍Lightweight OTEL span to JSON converter, no dependencies, pure Python🐍
|
|
5
5
|
Project-URL: Repository, https://github.com/dimaqq/otlp-json
|
|
6
6
|
Project-URL: Issues, https://github.com/dimaqq/otlp-json/issues
|
|
@@ -7,6 +7,8 @@ from typing import Any, TYPE_CHECKING
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
8
|
from typing_extensions import TypeAlias
|
|
9
9
|
|
|
10
|
+
from opentelemetry.trace import Link
|
|
11
|
+
from opentelemetry._logs import LogRecord
|
|
10
12
|
from opentelemetry.sdk.trace import ReadableSpan, Event
|
|
11
13
|
from opentelemetry.sdk.resources import Resource
|
|
12
14
|
from opentelemetry.sdk.util.instrumentation import InstrumentationScope
|
|
@@ -66,26 +68,27 @@ def encode_spans(spans: Sequence[ReadableSpan]) -> bytes:
|
|
|
66
68
|
|
|
67
69
|
|
|
68
70
|
def _resource(resource: Resource):
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
# TODO: add schema_url once that lands in opentelemetry-sdk
|
|
72
|
+
return _attributes(resource)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _attributes(
|
|
76
|
+
thing: Resource | InstrumentationScope | ReadableSpan | Event | Link | LogRecord,
|
|
77
|
+
) -> dict[str, Any]:
|
|
78
|
+
rv = {"attributes": [], "dropped_attributes_count": 0}
|
|
79
|
+
|
|
80
|
+
assert thing.attributes is not None
|
|
81
|
+
for k, v in thing.attributes.items():
|
|
71
82
|
try:
|
|
72
83
|
rv["attributes"].append({"key": k, "value": _value(v)})
|
|
73
84
|
except ValueError:
|
|
74
85
|
pass
|
|
75
86
|
|
|
76
|
-
|
|
77
|
-
# - Event
|
|
78
|
-
# - Link
|
|
79
|
-
# - InstrumentationScope
|
|
80
|
-
# - LogRecord (out of scope for this library)
|
|
81
|
-
# - Resource
|
|
82
|
-
rv["dropped_attributes_count"] = len(resource.attributes) - len(rv["attributes"]) # type: ignore
|
|
87
|
+
rv["dropped_attributes_count"] = len(thing.attributes) - len(rv["attributes"]) # type: ignore
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if not rv["dropped_attributes_count"]:
|
|
88
|
-
del rv["dropped_attributes_count"]
|
|
89
|
+
for k in ("attributes", "dropped_attributes_count"):
|
|
90
|
+
if not rv[k]:
|
|
91
|
+
del rv[k]
|
|
89
92
|
|
|
90
93
|
return rv
|
|
91
94
|
|
|
@@ -99,8 +102,9 @@ def _homogeneous_array(value: list[_LEAF_VALUE]) -> list[_LEAF_VALUE]:
|
|
|
99
102
|
|
|
100
103
|
def _value(value: _VALUE) -> dict[str, Any]:
|
|
101
104
|
# Attribute value can be a primitive type, excluging None...
|
|
102
|
-
#
|
|
103
|
-
#
|
|
105
|
+
# protobuf allows bytes, but I think OTLP spec does not?
|
|
106
|
+
# protobuf allows k:v pairs, but I think OTLP doesn't.
|
|
107
|
+
# TODO: read up the spec and validate the allowed type range.
|
|
104
108
|
for klass, (key, post) in _VALUE_TYPES.items():
|
|
105
109
|
if isinstance(value, klass):
|
|
106
110
|
return {key: post(value)}
|
|
@@ -109,7 +113,10 @@ def _value(value: _VALUE) -> dict[str, Any]:
|
|
|
109
113
|
|
|
110
114
|
|
|
111
115
|
def _scope(scope: InstrumentationScope):
|
|
112
|
-
rv = {
|
|
116
|
+
rv = {
|
|
117
|
+
"name": scope.name,
|
|
118
|
+
**_attributes(scope),
|
|
119
|
+
}
|
|
113
120
|
if scope.version:
|
|
114
121
|
rv["version"] = scope.version
|
|
115
122
|
return rv
|
|
@@ -123,29 +130,16 @@ def _span(span: ReadableSpan):
|
|
|
123
130
|
"traceId": _trace_id(span.context.trace_id),
|
|
124
131
|
"spanId": _span_id(span.context.span_id),
|
|
125
132
|
"flags": 0x100 | ([0, 0x200][bool(span.parent and span.parent.is_remote)]),
|
|
126
|
-
"startTimeUnixNano": str(span.start_time),
|
|
127
|
-
"endTimeUnixNano": str(span.end_time), #
|
|
133
|
+
"startTimeUnixNano": str(span.start_time),
|
|
134
|
+
"endTimeUnixNano": str(span.end_time), # can this be unset?
|
|
128
135
|
"status": _status(span.status),
|
|
129
|
-
|
|
136
|
+
**_attributes(span),
|
|
130
137
|
}
|
|
131
138
|
|
|
132
139
|
if span.parent:
|
|
133
140
|
rv["parentSpanId"] = _span_id(span.parent.span_id)
|
|
134
141
|
|
|
135
|
-
|
|
136
|
-
try:
|
|
137
|
-
rv["attributes"].append({"key": k, "value": _value(v)})
|
|
138
|
-
except ValueError:
|
|
139
|
-
pass
|
|
140
|
-
|
|
141
|
-
rv["dropped_attributes_count"] = len(span.attributes) - len(rv["attributes"]) # type: ignore
|
|
142
|
-
|
|
143
|
-
if not rv["attributes"]:
|
|
144
|
-
del rv["attributes"]
|
|
145
|
-
|
|
146
|
-
if not rv["dropped_attributes_count"]:
|
|
147
|
-
del rv["dropped_attributes_count"]
|
|
148
|
-
|
|
142
|
+
# TODO: is this field really nullable?
|
|
149
143
|
if span.events:
|
|
150
144
|
rv["events"] = [_event(e) for e in span.events]
|
|
151
145
|
|
|
@@ -165,7 +159,7 @@ def _span_id(span_id: int) -> str:
|
|
|
165
159
|
|
|
166
160
|
|
|
167
161
|
def _status(status: Status) -> dict[str, Any]:
|
|
168
|
-
# FIXME
|
|
162
|
+
# FIXME: need an example of bad status
|
|
169
163
|
return {}
|
|
170
164
|
|
|
171
165
|
|
|
@@ -173,21 +167,7 @@ def _event(event: Event) -> dict[str, Any]:
|
|
|
173
167
|
rv = {
|
|
174
168
|
"name": event.name,
|
|
175
169
|
"timeUnixNano": str(event.timestamp),
|
|
176
|
-
|
|
170
|
+
**_attributes(event),
|
|
177
171
|
}
|
|
178
|
-
|
|
179
|
-
for k, v in event.attributes.items(): # type: ignore
|
|
180
|
-
try:
|
|
181
|
-
rv["attributes"].append({"key": k, "value": _value(v)})
|
|
182
|
-
except ValueError:
|
|
183
|
-
pass
|
|
184
|
-
|
|
185
|
-
rv["dropped_attributes_count"] = len(event.attributes) - len(rv["attributes"]) # type: ignore
|
|
186
|
-
|
|
187
|
-
if not rv["attributes"]:
|
|
188
|
-
del rv["attributes"]
|
|
189
|
-
|
|
190
|
-
if not rv["dropped_attributes_count"]:
|
|
191
|
-
del rv["dropped_attributes_count"]
|
|
192
|
-
|
|
172
|
+
# TODO: any optional attributes?
|
|
193
173
|
return rv
|
|
@@ -374,7 +374,7 @@ wheels = [
|
|
|
374
374
|
|
|
375
375
|
[[package]]
|
|
376
376
|
name = "otlp-json"
|
|
377
|
-
version = "0.9.
|
|
377
|
+
version = "0.9.3"
|
|
378
378
|
source = { editable = "." }
|
|
379
379
|
|
|
380
380
|
[package.dev-dependencies]
|
|
@@ -405,7 +405,7 @@ testing = [
|
|
|
405
405
|
|
|
406
406
|
[[package]]
|
|
407
407
|
name = "otlp-test-data"
|
|
408
|
-
version = "0.11.
|
|
408
|
+
version = "0.11.2"
|
|
409
409
|
source = { registry = "https://pypi.org/simple" }
|
|
410
410
|
dependencies = [
|
|
411
411
|
{ name = "freezegun" },
|
|
@@ -414,9 +414,9 @@ dependencies = [
|
|
|
414
414
|
{ name = "opentelemetry-exporter-otlp" },
|
|
415
415
|
{ name = "opentelemetry-exporter-otlp-proto-http" },
|
|
416
416
|
]
|
|
417
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
417
|
+
sdist = { url = "https://files.pythonhosted.org/packages/df/d7/21bed69e7f201abbdb27bf84bea1a02f65991efc60d88aaeb4001c9069ad/otlp_test_data-0.11.2.tar.gz", hash = "sha256:6be622eaa675e08568d140ce0863f0dfbf3eeb7dd1b567d66633ddd79d4d9632", size = 37707 }
|
|
418
418
|
wheels = [
|
|
419
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
419
|
+
{ url = "https://files.pythonhosted.org/packages/4c/62/462acb3181f178832c286e8b6f9787a6983dd5bdd9588564624a861db837/otlp_test_data-0.11.2-py3-none-any.whl", hash = "sha256:419190181f221d611d24dba8850e980d69bc7e1195bd36f0c4e5ec6a3bcdcc7e", size = 3584 },
|
|
420
420
|
]
|
|
421
421
|
|
|
422
422
|
[[package]]
|
|
@@ -457,15 +457,15 @@ wheels = [
|
|
|
457
457
|
|
|
458
458
|
[[package]]
|
|
459
459
|
name = "pyright"
|
|
460
|
-
version = "1.1.
|
|
460
|
+
version = "1.1.395"
|
|
461
461
|
source = { registry = "https://pypi.org/simple" }
|
|
462
462
|
dependencies = [
|
|
463
463
|
{ name = "nodeenv" },
|
|
464
464
|
{ name = "typing-extensions" },
|
|
465
465
|
]
|
|
466
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
466
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fb/47/a2e1dfd70f9f0db34f70d5b108c82be57bf24185af69c95acff57f9239fa/pyright-1.1.395.tar.gz", hash = "sha256:53703169068c160bfb41e1b44ba3e2512492869c26cfad927e1268cb3fbb1b1c", size = 3813566 }
|
|
467
467
|
wheels = [
|
|
468
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
468
|
+
{ url = "https://files.pythonhosted.org/packages/5f/a1/531897f8caa6c6cc99862cd1c908ddd8a366a51d968e83ab4523ded98b30/pyright-1.1.395-py3-none-any.whl", hash = "sha256:f9bc726870e740c6c77c94657734d90563a3e9765bb523b39f5860198ed75eef", size = 5688787 },
|
|
469
469
|
]
|
|
470
470
|
|
|
471
471
|
[[package]]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|