debugbundle-python 1.5.0__tar.gz → 2.0.0__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.
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/PKG-INFO +6 -1
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/README.md +5 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/pyproject.toml +1 -1
- debugbundle_python-2.0.0/src/debugbundle/capture_hooks.py +65 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/core.py +342 -259
- debugbundle_python-2.0.0/src/debugbundle/delivery_hooks.py +62 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/event_support.py +1 -1
- debugbundle_python-2.0.0/src/debugbundle/exception_snapshot.py +74 -0
- debugbundle_python-2.0.0/src/debugbundle/flush_aggregates.py +37 -0
- debugbundle_python-2.0.0/src/debugbundle/probe_capture.py +101 -0
- debugbundle_python-2.0.0/src/debugbundle/process_support.py +59 -0
- debugbundle_python-2.0.0/src/debugbundle/queue_admission.py +39 -0
- debugbundle_python-2.0.0/src/debugbundle/request_capture_policy.py +45 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/suppression.py +13 -6
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle_python.egg-info/PKG-INFO +6 -1
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle_python.egg-info/SOURCES.txt +11 -0
- debugbundle_python-2.0.0/tests/test_delivery_hooks.py +108 -0
- debugbundle_python-2.0.0/tests/test_exception_snapshot.py +95 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_hooks.py +36 -2
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_remote_config.py +8 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_schema_validation.py +2 -1
- debugbundle_python-2.0.0/tests/test_sdk.py +1213 -0
- debugbundle_python-2.0.0/tests/test_suppression.py +9 -0
- debugbundle_python-1.5.0/tests/test_sdk.py +0 -567
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/LICENSE +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/setup.cfg +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/__init__.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/acknowledgement.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/before_send.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/config.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/integrations/__init__.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/integrations/common.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/integrations/django.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/integrations/fastapi.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/integrations/flask.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/integrations/relay_django.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/integrations/relay_fastapi.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/integrations/relay_flask.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/logger_integrations.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/py.typed +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/redaction.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/relay.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/relay_delivery.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/structlog_integration.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/transport.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle/trigger_token.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle_python.egg-info/dependency_links.txt +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle_python.egg-info/requires.txt +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/src/debugbundle_python.egg-info/top_level.txt +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_before_send.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_contracts.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_framework_integrations.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_http_integration.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_optional_imports.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_privacy_conformance.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_relay.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_relay_delivery.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_repository_metadata.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_smoke_script.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_structlog_filtering.py +0 -0
- {debugbundle_python-1.5.0 → debugbundle_python-2.0.0}/tests/test_trigger_token.py +0 -0
|
@@ -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
|
|
@@ -51,6 +51,8 @@ Use this package to capture Python backend exceptions, request metadata, structu
|
|
|
51
51
|
|
|
52
52
|
Requires Python 3.10 or newer.
|
|
53
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
|
+
|
|
54
56
|
## Automatic capture and application filtering
|
|
55
57
|
|
|
56
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.
|
|
@@ -99,6 +101,7 @@ debugbundle.capture_log("payment retry failed", level="warning", context={"order
|
|
|
99
101
|
debugbundle.capture_message("worker started")
|
|
100
102
|
debugbundle.probe("checkout.cart", {"item_count": len(cart.items)})
|
|
101
103
|
|
|
104
|
+
# Use only during controlled teardown or tests, never on a request path.
|
|
102
105
|
debugbundle.flush()
|
|
103
106
|
```
|
|
104
107
|
|
|
@@ -283,8 +286,10 @@ Post-V1 planned expansions from `spec/sdk-language-targets.md` remain out of sco
|
|
|
283
286
|
## Safety Defaults
|
|
284
287
|
|
|
285
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.
|
|
286
290
|
- Sensitive fields are redacted before transport.
|
|
287
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.
|
|
288
293
|
- Runtime context excludes environment variables.
|
|
289
294
|
- Browser relay requests cannot smuggle server-side credentials.
|
|
290
295
|
|
|
@@ -10,6 +10,8 @@ Use this package to capture Python backend exceptions, request metadata, structu
|
|
|
10
10
|
|
|
11
11
|
Requires Python 3.10 or newer.
|
|
12
12
|
|
|
13
|
+
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.
|
|
14
|
+
|
|
13
15
|
## Automatic capture and application filtering
|
|
14
16
|
|
|
15
17
|
`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.
|
|
@@ -58,6 +60,7 @@ debugbundle.capture_log("payment retry failed", level="warning", context={"order
|
|
|
58
60
|
debugbundle.capture_message("worker started")
|
|
59
61
|
debugbundle.probe("checkout.cart", {"item_count": len(cart.items)})
|
|
60
62
|
|
|
63
|
+
# Use only during controlled teardown or tests, never on a request path.
|
|
61
64
|
debugbundle.flush()
|
|
62
65
|
```
|
|
63
66
|
|
|
@@ -242,8 +245,10 @@ Post-V1 planned expansions from `spec/sdk-language-targets.md` remain out of sco
|
|
|
242
245
|
## Safety Defaults
|
|
243
246
|
|
|
244
247
|
- SDK failures are caught internally and do not crash the host process.
|
|
248
|
+
- 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.
|
|
245
249
|
- Sensitive fields are redacted before transport.
|
|
246
250
|
- Duplicate event storms are suppressed locally.
|
|
251
|
+
- 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.
|
|
247
252
|
- Runtime context excludes environment variables.
|
|
248
253
|
- Browser relay requests cannot smuggle server-side credentials.
|
|
249
254
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Logger adapter and bounded capture admission for callback-heavy paths."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import re
|
|
7
|
+
import time
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from .process_support import ensure_current_process
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from .core import DebugBundleSdk
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def try_capture_lock(sdk: DebugBundleSdk) -> bool:
|
|
17
|
+
ensure_current_process(sdk)
|
|
18
|
+
for _ in range(8):
|
|
19
|
+
if sdk._lock.acquire(blocking=False):
|
|
20
|
+
return True
|
|
21
|
+
time.sleep(0)
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DebugBundleLogHandler(logging.Handler):
|
|
26
|
+
def __init__(self, sdk: DebugBundleSdk) -> None:
|
|
27
|
+
super().__init__()
|
|
28
|
+
self._sdk = sdk
|
|
29
|
+
|
|
30
|
+
def emit(self, record: logging.LogRecord) -> None:
|
|
31
|
+
if not self._sdk._log_level_eligible(record.levelname.lower()):
|
|
32
|
+
return
|
|
33
|
+
self._sdk.capture_log(
|
|
34
|
+
safe_log_message(record),
|
|
35
|
+
level=record.levelname.lower(),
|
|
36
|
+
context={
|
|
37
|
+
"logger_name": record.name,
|
|
38
|
+
"pathname": record.pathname,
|
|
39
|
+
"lineno": record.lineno,
|
|
40
|
+
},
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
_PLACEHOLDER = re.compile(r"%[sdif]")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def safe_log_message(record: logging.LogRecord) -> str:
|
|
48
|
+
template = record.msg
|
|
49
|
+
if type(template) is not str:
|
|
50
|
+
return "[non-string log message withheld]"
|
|
51
|
+
template = template[:16_384]
|
|
52
|
+
args = record.args
|
|
53
|
+
if not args:
|
|
54
|
+
return template
|
|
55
|
+
if type(args) is not tuple or len(args) > 8:
|
|
56
|
+
return template + " [log arguments withheld]"
|
|
57
|
+
safe_args = [
|
|
58
|
+
value[:1024] if type(value) is str else str(value) if type(value) in (int, float, bool)
|
|
59
|
+
else "[unsupported argument]"
|
|
60
|
+
for value in args
|
|
61
|
+
]
|
|
62
|
+
if len(_PLACEHOLDER.findall(template)) != len(safe_args):
|
|
63
|
+
return (template + " [args: " + ", ".join(safe_args) + "]")[:16_384]
|
|
64
|
+
iterator = iter(safe_args)
|
|
65
|
+
return _PLACEHOLDER.sub(lambda _match: next(iterator), template)[:16_384]
|