telemetry-dev 0.2.8__tar.gz → 0.2.9__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.
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/PKG-INFO +1 -1
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/pyproject.toml +1 -1
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/pyproject.toml.orig +1 -1
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_capture.py +46 -14
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/LICENSE +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/README.md +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/__init__.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_client.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_config.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_context.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_logs.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_metrics.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_observe.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_processor.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_semconv.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_serialize.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/_spans.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/otel.py +0 -0
- {telemetry_dev-0.2.8 → telemetry_dev-0.2.9}/src/telemetry_dev/py.typed +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import re
|
|
5
6
|
from collections.abc import Iterable, Mapping, Sequence
|
|
6
7
|
from itertools import chain
|
|
7
8
|
from typing import Final, cast
|
|
@@ -11,6 +12,36 @@ _DEFAULT_MAX_ITEMS: Final = 1024
|
|
|
11
12
|
_MAX_DEPTH: Final = 32
|
|
12
13
|
_BASE_ITEM_BYTES: Final = 16
|
|
13
14
|
|
|
15
|
+
# Code points whose JSON form is longer than their UTF-8 form, mapped to the extra bytes.
|
|
16
|
+
_SHORT_ESCAPE_EXTRA: Final = 1 # '"', '\\', \b \t \n \f \r: 1 byte raw, 2 escaped
|
|
17
|
+
_CONTROL_ESCAPE_EXTRA: Final = 5 # other code points below 0x20: 1 byte raw, 6 as \u00XX
|
|
18
|
+
_SURROGATE_ESCAPE_EXTRA: Final = 3 # a surrogate code point: 3 bytes raw, 6 as \uXXXX
|
|
19
|
+
_JSON_ESCAPED: Final = re.compile('["\\\\\x00-\x1f\ud800-\udfff]')
|
|
20
|
+
_JSON_STRING_CHUNK: Final = 4096
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _escape_extra(character: str) -> int:
|
|
24
|
+
code = ord(character)
|
|
25
|
+
if character in '"\\\b\t\n\f\r':
|
|
26
|
+
return _SHORT_ESCAPE_EXTRA
|
|
27
|
+
if code < 0x20:
|
|
28
|
+
return _CONTROL_ESCAPE_EXTRA
|
|
29
|
+
return _SURROGATE_ESCAPE_EXTRA
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _json_string_bytes(value: str, limit: int | None) -> int:
|
|
33
|
+
# Every code point costs at least one byte, so a string longer than the limit needs no scan.
|
|
34
|
+
if limit is not None and len(value) > limit:
|
|
35
|
+
return len(value)
|
|
36
|
+
size = 0
|
|
37
|
+
for start in range(0, len(value), _JSON_STRING_CHUNK):
|
|
38
|
+
chunk = value[start : start + _JSON_STRING_CHUNK]
|
|
39
|
+
size += len(chunk.encode("utf-8", "surrogatepass"))
|
|
40
|
+
size += sum(_escape_extra(match.group()) for match in _JSON_ESCAPED.finditer(chunk))
|
|
41
|
+
if limit is not None and size > limit:
|
|
42
|
+
return size
|
|
43
|
+
return size
|
|
44
|
+
|
|
14
45
|
|
|
15
46
|
class CaptureBudget:
|
|
16
47
|
"""Track a hard byte and item budget before retaining streamed provider data."""
|
|
@@ -32,6 +63,18 @@ class CaptureBudget:
|
|
|
32
63
|
max_bytes=client.max_attribute_length if client is not None else _DEFAULT_MAX_BYTES
|
|
33
64
|
)
|
|
34
65
|
|
|
66
|
+
@staticmethod
|
|
67
|
+
def json_string_bytes(value: str, limit: int | None = None) -> int:
|
|
68
|
+
"""Return the UTF-8 bytes ``value`` occupies inside a JSON string, without the quotes.
|
|
69
|
+
|
|
70
|
+
Matches the TypeScript SDK's measure: ``"``, ``\\``, and ``\\b \\t \\n \\f \\r`` cost 2
|
|
71
|
+
bytes, other control characters cost 6 (``\\u00XX``), and every surrogate code point
|
|
72
|
+
costs 6 (``\\uXXXX``); anything else costs its UTF-8 width. The budget charges a string
|
|
73
|
+
this plus its per-item cost, which covers the quotes and separators. Counting stops
|
|
74
|
+
once the total passes ``limit``, so a result above ``limit`` is only a lower bound.
|
|
75
|
+
"""
|
|
76
|
+
return _json_string_bytes(value, limit)
|
|
77
|
+
|
|
35
78
|
@property
|
|
36
79
|
def remaining_bytes(self) -> int:
|
|
37
80
|
"""Return bytes still available for retained capture state."""
|
|
@@ -98,20 +141,9 @@ class CaptureBudget:
|
|
|
98
141
|
if value is None or isinstance(value, bool | int | float):
|
|
99
142
|
return byte_count, item_count
|
|
100
143
|
if isinstance(value, str):
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
1
|
|
105
|
-
if codepoint <= 0x7F
|
|
106
|
-
else 2
|
|
107
|
-
if codepoint <= 0x7FF
|
|
108
|
-
else 3
|
|
109
|
-
if codepoint <= 0xFFFF
|
|
110
|
-
else 4
|
|
111
|
-
)
|
|
112
|
-
if byte_count > remaining_bytes:
|
|
113
|
-
return None
|
|
114
|
-
return byte_count, item_count
|
|
144
|
+
# Mapping keys come through here too, so they are charged at their escaped size.
|
|
145
|
+
byte_count += _json_string_bytes(value, remaining_bytes - byte_count)
|
|
146
|
+
return (byte_count, item_count) if byte_count <= remaining_bytes else None
|
|
115
147
|
if isinstance(value, bytes | bytearray | memoryview):
|
|
116
148
|
length = value.nbytes if isinstance(value, memoryview) else len(value)
|
|
117
149
|
# Structured attributes serialize binary values as base64 text.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|