debugbundle-python 1.4.2__py3-none-any.whl → 2.0.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.
- debugbundle/capture_hooks.py +65 -0
- debugbundle/core.py +379 -251
- debugbundle/delivery_hooks.py +62 -0
- debugbundle/event_support.py +1 -1
- debugbundle/exception_snapshot.py +74 -0
- debugbundle/flush_aggregates.py +37 -0
- debugbundle/probe_capture.py +101 -0
- debugbundle/process_support.py +59 -0
- debugbundle/queue_admission.py +39 -0
- debugbundle/redaction.py +197 -0
- debugbundle/relay.py +8 -0
- debugbundle/request_capture_policy.py +45 -0
- debugbundle/suppression.py +13 -6
- {debugbundle_python-1.4.2.dist-info → debugbundle_python-2.0.0.dist-info}/METADATA +12 -5
- {debugbundle_python-1.4.2.dist-info → debugbundle_python-2.0.0.dist-info}/RECORD +18 -10
- {debugbundle_python-1.4.2.dist-info → debugbundle_python-2.0.0.dist-info}/WHEEL +0 -0
- {debugbundle_python-1.4.2.dist-info → debugbundle_python-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {debugbundle_python-1.4.2.dist-info → debugbundle_python-2.0.0.dist-info}/top_level.txt +0 -0
debugbundle/suppression.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections import OrderedDict
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from hashlib import sha256
|
|
5
6
|
|
|
@@ -9,6 +10,7 @@ LOOP_THRESHOLD = 10
|
|
|
9
10
|
LOOP_RESET_AFTER_SECONDS = 60.0
|
|
10
11
|
LOOP_CHECKPOINT_SECONDS = 30.0
|
|
11
12
|
MAX_NORMAL_EVENTS_PER_WINDOW = 3
|
|
13
|
+
MAX_TRACKED_FINGERPRINTS = 2_048
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
@dataclass
|
|
@@ -27,25 +29,30 @@ class SuppressionState:
|
|
|
27
29
|
|
|
28
30
|
class EventSuppressionTracker:
|
|
29
31
|
def __init__(self) -> None:
|
|
30
|
-
self._states:
|
|
32
|
+
self._states: OrderedDict[str, SuppressionState] = OrderedDict()
|
|
31
33
|
|
|
32
34
|
def should_capture(self, key: str, now: float) -> bool:
|
|
33
|
-
|
|
35
|
+
fingerprint = sha256(key.encode("utf-8")).hexdigest()
|
|
36
|
+
state = self._states.get(fingerprint)
|
|
34
37
|
if state is None:
|
|
38
|
+
if len(self._states) >= MAX_TRACKED_FINGERPRINTS:
|
|
39
|
+
self._states.popitem(last=False)
|
|
35
40
|
state = SuppressionState(
|
|
36
41
|
window_started_at=now,
|
|
37
42
|
loop_window_started_at=now,
|
|
38
43
|
last_seen_at=now,
|
|
39
44
|
)
|
|
40
|
-
self._states[
|
|
45
|
+
self._states[fingerprint] = state
|
|
46
|
+
else:
|
|
47
|
+
self._states.move_to_end(fingerprint)
|
|
41
48
|
|
|
42
49
|
if state.suppression_mode and now - state.last_seen_at >= LOOP_RESET_AFTER_SECONDS:
|
|
43
|
-
self._states[
|
|
50
|
+
self._states[fingerprint] = SuppressionState(
|
|
44
51
|
window_started_at=now,
|
|
45
52
|
loop_window_started_at=now,
|
|
46
53
|
last_seen_at=now,
|
|
47
54
|
)
|
|
48
|
-
state = self._states[
|
|
55
|
+
state = self._states[fingerprint]
|
|
49
56
|
|
|
50
57
|
if now - state.window_started_at >= DUPLICATE_WINDOW_SECONDS:
|
|
51
58
|
state.window_started_at = now
|
|
@@ -94,7 +101,7 @@ class EventSuppressionTracker:
|
|
|
94
101
|
{
|
|
95
102
|
"event_type": "error_suppressed",
|
|
96
103
|
"payload": {
|
|
97
|
-
"fingerprint":
|
|
104
|
+
"fingerprint": key,
|
|
98
105
|
"suppressed_count": state.pending_suppressed_count,
|
|
99
106
|
"first_seen": _to_iso(state.pending_first_seen_at),
|
|
100
107
|
"last_seen": _to_iso(state.pending_last_seen_at),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: debugbundle-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: DebugBundle SDK for Python
|
|
5
5
|
Author: DebugBundle
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -17,6 +17,8 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
22
|
Classifier: Typing :: Typed
|
|
21
23
|
Requires-Python: >=3.10
|
|
22
24
|
Description-Content-Type: text/markdown
|
|
@@ -24,7 +26,7 @@ License-File: LICENSE
|
|
|
24
26
|
Requires-Dist: httpx<0.29,>=0.27
|
|
25
27
|
Provides-Extra: dev
|
|
26
28
|
Requires-Dist: build<2,>=1; extra == "dev"
|
|
27
|
-
Requires-Dist: django<
|
|
29
|
+
Requires-Dist: django<7,>=5; extra == "dev"
|
|
28
30
|
Requires-Dist: fastapi<1,>=0.115; extra == "dev"
|
|
29
31
|
Requires-Dist: flask<4,>=3; extra == "dev"
|
|
30
32
|
Requires-Dist: jsonschema<5,>=4.23; extra == "dev"
|
|
@@ -49,6 +51,8 @@ Use this package to capture Python backend exceptions, request metadata, structu
|
|
|
49
51
|
|
|
50
52
|
Requires Python 3.10 or newer.
|
|
51
53
|
|
|
54
|
+
Version 2.0.0 protects capture callers with bounded, priority-aware background delivery. Review the [2.0 migration guide](MIGRATION-2.0.md) before upgrading from 1.x.
|
|
55
|
+
|
|
52
56
|
## Automatic capture and application filtering
|
|
53
57
|
|
|
54
58
|
`capture_logging()` attaches the stdlib logging handler and detects installed structlog/loguru integrations. Obtain structlog loggers after attachment. Structlog level filters and `DropEvent` processors run before capture; stdlib-backed structlog loggers also honor logger filters, disabled state and `logging.disable()`. Bound context and async logging are supported. SDK disposal stops capture through cached proxies. DebugBundle has its own minimum capture level; destination-specific filters on other handlers or Loguru sinks do not configure the DebugBundle handler.
|
|
@@ -97,6 +101,7 @@ debugbundle.capture_log("payment retry failed", level="warning", context={"order
|
|
|
97
101
|
debugbundle.capture_message("worker started")
|
|
98
102
|
debugbundle.probe("checkout.cart", {"item_count": len(cart.items)})
|
|
99
103
|
|
|
104
|
+
# Use only during controlled teardown or tests, never on a request path.
|
|
100
105
|
debugbundle.flush()
|
|
101
106
|
```
|
|
102
107
|
|
|
@@ -263,8 +268,8 @@ There is no zero-install fallback for the Python SDK itself in V1. The nearest l
|
|
|
263
268
|
|
|
264
269
|
| Surface | Minimum compatibility version | Recommended production version | Installed-base compatibility lane | Rolling CI lane | Out of scope |
|
|
265
270
|
| --- | --- | --- | --- | --- | --- |
|
|
266
|
-
| Python runtime | 3.10 | 3.
|
|
267
|
-
| Django | 5.x | latest
|
|
271
|
+
| Python runtime | 3.10 | 3.14 | 3.10 through 3.13 remain supported for installed-base coverage | 3.10 through 3.14 | 3.9 and older |
|
|
272
|
+
| Django | 5.x | latest 6.1 patch | 5.x compatibility support | Python 3.14 suite exercises Django 6.1 | Django 4.x and older |
|
|
268
273
|
| Flask | 3.x | latest 3.x patch | 3.x compatibility support | repo release smoke installs Flask 3.x | Flask 2.x and older |
|
|
269
274
|
| FastAPI | 0.115+ | latest 0.115+ patch line | 0.115+ compatibility support | repo tests install FastAPI 0.115+ | standalone Starlette, older FastAPI lines |
|
|
270
275
|
|
|
@@ -275,14 +280,16 @@ Post-V1 planned expansions from `spec/sdk-language-targets.md` remain out of sco
|
|
|
275
280
|
`debugbundle-python` ships as one package in V1, so there is no multi-package version-alignment step like a BOM or plugin family lock.
|
|
276
281
|
|
|
277
282
|
- Pin one `debugbundle-python` version across your service and worker repos when you want identical SDK behavior everywhere.
|
|
278
|
-
- Keep framework dependencies inside the supported lanes above: Django 5.x, Flask 3.x, and FastAPI 0.115+.
|
|
283
|
+
- Keep framework dependencies inside the supported lanes above: Django 5.x or 6.x, Flask 3.x, and FastAPI 0.115+.
|
|
279
284
|
- The packaged HTTP client dependency is `httpx>=0.27,<0.29`; if you override transport behavior in tests or wrappers, stay inside that range unless you retest the SDK.
|
|
280
285
|
|
|
281
286
|
## Safety Defaults
|
|
282
287
|
|
|
283
288
|
- SDK failures are caught internally and do not crash the host process.
|
|
289
|
+
- A forked worker starts with a fresh SDK queue, lock, context and built-in HTTP client. Initialize the SDK in each child when remote configuration must poll there; custom transports must be fork-safe.
|
|
284
290
|
- Sensitive fields are redacted before transport.
|
|
285
291
|
- Duplicate event storms are suppressed locally.
|
|
292
|
+
- Full-queue capture sheds warning/request noise before context scans. Exceptions, ERROR logs, and 5xx request incidents have priority over pending lower-priority events; all-error overloads are bounded and summarized.
|
|
286
293
|
- Runtime context excludes environment variables.
|
|
287
294
|
- Browser relay requests cannot smuggle server-side credentials.
|
|
288
295
|
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
debugbundle/__init__.py,sha256=QH5RY2Cdp3Ry5PNSAhiV9akOMoS2pERRqowFnZ94roc,5131
|
|
2
2
|
debugbundle/acknowledgement.py,sha256=tyI8XLRG9N3-Weo6uiGrAlf_O4tjptVe1x1cG7RjrMc,2314
|
|
3
3
|
debugbundle/before_send.py,sha256=_tmV6ovHUBIxfQPMQ8a0C6r91IAnd4DVs8UcjsKhqX0,7792
|
|
4
|
+
debugbundle/capture_hooks.py,sha256=70Q6ske8JulyuYpeE9FohvMreytf4DUrj4QW9f2-o2Q,1940
|
|
4
5
|
debugbundle/config.py,sha256=ENRSR5jUI7xYdBqUakWws3GIjBk00GWFmwXVE_iQp2Y,9296
|
|
5
|
-
debugbundle/core.py,sha256=
|
|
6
|
-
debugbundle/
|
|
6
|
+
debugbundle/core.py,sha256=XgRx92jSzrP6PjvHHRI0NlwdD53cRmBQ6qN4UtnQqIA,39310
|
|
7
|
+
debugbundle/delivery_hooks.py,sha256=BUqtHuEv1MDOSLv0sUP6D582c06JofsbXhi7I7Y5IGc,2691
|
|
8
|
+
debugbundle/event_support.py,sha256=MtPg2CO7B91U7-zE9XGro0-fynaEnJZmQ6Ms9arfRlg,9046
|
|
9
|
+
debugbundle/exception_snapshot.py,sha256=_2p55F572sL7_ogBL6Raa137HRyUqvSaHVMwpKiC8fs,2831
|
|
10
|
+
debugbundle/flush_aggregates.py,sha256=ukHsIUykeGp4YJsesA_9NCUMarg_BAXVuzO4bqJKH3Y,1464
|
|
7
11
|
debugbundle/logger_integrations.py,sha256=T6LR10_DgDS8C-CUPxtC1kZz3qfX5j0B2YUV7LxDovk,3572
|
|
12
|
+
debugbundle/probe_capture.py,sha256=c1a-ZKHyNeu6CMS5zgi8_wIfpLs5-pe12GEXNMpMTVM,3969
|
|
13
|
+
debugbundle/process_support.py,sha256=D1aFhaP1wOGfMdzkdtEhO54R3XWa8dLCZlfWHWN3qA4,1962
|
|
8
14
|
debugbundle/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
debugbundle/
|
|
10
|
-
debugbundle/
|
|
15
|
+
debugbundle/queue_admission.py,sha256=QtFengGZ4KEVbu1UqSp3u8eLucQeS9dGIwrzq62A5cY,1433
|
|
16
|
+
debugbundle/redaction.py,sha256=mxJgtILpVDUaj8LAhzswfaX1M4Ppyx87lfkhFqbMR8M,9663
|
|
17
|
+
debugbundle/relay.py,sha256=9HkEEVZpqrebzH6A-sSuFVuFjyLg07JuTMpMG8pu7SY,14726
|
|
11
18
|
debugbundle/relay_delivery.py,sha256=VL-nIgJR6mYXqKy-EbA0USWeY_iS_uAr1KBzrnwBnnk,4676
|
|
19
|
+
debugbundle/request_capture_policy.py,sha256=fl1EilWAnBQCdGTafRpY0tMlYUoSJK_7hZyJmPHLkeI,1583
|
|
12
20
|
debugbundle/structlog_integration.py,sha256=hDwCGXTQ8GAjnx2jwlRbpnvLE0y798kFFMsSB3iqOrM,6061
|
|
13
|
-
debugbundle/suppression.py,sha256=
|
|
21
|
+
debugbundle/suppression.py,sha256=V_JvDvcV7tN3EHkfpEJGK1WB2G4nR3GhXvaKd400iFQ,4418
|
|
14
22
|
debugbundle/transport.py,sha256=V289FwFWL6KV5gyzOsesluEMbpRobm_FHu3x8BpOYKU,2014
|
|
15
23
|
debugbundle/trigger_token.py,sha256=YUwIWnnxu1klAVaB8Ltgk_PwWW_PPjq9rzmEbWXeFeM,4455
|
|
16
24
|
debugbundle/integrations/__init__.py,sha256=Jr87ImWXzUXOuFP4WlGleK14VARajSSdGZN_nHt5emw,1161
|
|
@@ -21,8 +29,8 @@ debugbundle/integrations/flask.py,sha256=cgyHbsAH96gpNPf_5IGJYzp2va28JdDgXROBsF-
|
|
|
21
29
|
debugbundle/integrations/relay_django.py,sha256=Wj8BE9D5otU2KmtjgqdKIJ-BvXVcagCKgpLYvnPZ6WE,2281
|
|
22
30
|
debugbundle/integrations/relay_fastapi.py,sha256=-Zl6bvhYMLii__mP6-UvSdwxS5VKsb9OZvk-yy-3hEw,2227
|
|
23
31
|
debugbundle/integrations/relay_flask.py,sha256=VFHkDTJy4LkZzL_Ry_Ba-e_gW6UTG4PBwnLcvB_oXuQ,2011
|
|
24
|
-
debugbundle_python-
|
|
25
|
-
debugbundle_python-
|
|
26
|
-
debugbundle_python-
|
|
27
|
-
debugbundle_python-
|
|
28
|
-
debugbundle_python-
|
|
32
|
+
debugbundle_python-2.0.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
33
|
+
debugbundle_python-2.0.0.dist-info/METADATA,sha256=oX9_gQfmoPs8PCSNucy0tTany71DEiuHsu71IPmYBmg,15231
|
|
34
|
+
debugbundle_python-2.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
35
|
+
debugbundle_python-2.0.0.dist-info/top_level.txt,sha256=RCB9STTFnl1OKdojxz-xhaks2zkRFs1meZXsKnm18LM,12
|
|
36
|
+
debugbundle_python-2.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|