watchdock-errors 0.1.0__tar.gz → 0.1.2__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.
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/PKG-INFO +1 -1
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/pyproject.toml +1 -1
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/__init__.py +10 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/client.py +22 -4
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/config.py +1 -1
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/integrations/django.py +5 -6
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors.egg-info/PKG-INFO +1 -1
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/README.md +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/setup.cfg +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/event.py +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/integrations/__init__.py +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/integrations/fastapi.py +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/utils.py +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors.egg-info/SOURCES.txt +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors.egg-info/dependency_links.txt +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors.egg-info/requires.txt +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors.egg-info/top_level.txt +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/tests/test_client.py +0 -0
- {watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/tests/test_event.py +0 -0
|
@@ -63,6 +63,12 @@ def init(
|
|
|
63
63
|
timeout=timeout,
|
|
64
64
|
)
|
|
65
65
|
_client = WatchdockClient(_config)
|
|
66
|
+
logger.info(
|
|
67
|
+
"watchdock_errors: initialised — endpoint=%s environment=%s release=%s",
|
|
68
|
+
_config.ingest_url,
|
|
69
|
+
environment,
|
|
70
|
+
release or "unset",
|
|
71
|
+
)
|
|
66
72
|
|
|
67
73
|
|
|
68
74
|
def capture_exception(exc: BaseException | None = None, request_context: dict | None = None) -> None:
|
|
@@ -87,7 +93,10 @@ def capture_exception(exc: BaseException | None = None, request_context: dict |
|
|
|
87
93
|
|
|
88
94
|
event = build_event(exc, _config, request_context=request_context)
|
|
89
95
|
if event is not None:
|
|
96
|
+
logger.info("watchdock_errors: capturing exception — %s: %s", type(exc).__name__, exc)
|
|
90
97
|
_client.capture(event)
|
|
98
|
+
else:
|
|
99
|
+
logger.debug("watchdock_errors: event dropped by before_send hook")
|
|
91
100
|
|
|
92
101
|
|
|
93
102
|
def capture_message(message: str, request_context: dict | None = None) -> None:
|
|
@@ -99,6 +108,7 @@ def capture_message(message: str, request_context: dict | None = None) -> None:
|
|
|
99
108
|
|
|
100
109
|
event = build_event(None, _config, message=message, request_context=request_context)
|
|
101
110
|
if event is not None:
|
|
111
|
+
logger.info("watchdock_errors: capturing message — %s", message)
|
|
102
112
|
_client.capture(event)
|
|
103
113
|
|
|
104
114
|
|
|
@@ -26,13 +26,15 @@ class WatchdockClient:
|
|
|
26
26
|
self._queue: queue.Queue[dict | None] = queue.Queue(maxsize=100)
|
|
27
27
|
self._thread = threading.Thread(target=self._worker, daemon=True, name="watchdock-errors")
|
|
28
28
|
self._thread.start()
|
|
29
|
+
logger.debug("watchdock_errors: background transport thread started")
|
|
29
30
|
|
|
30
31
|
def capture(self, event: dict) -> None:
|
|
31
32
|
"""Enqueue an event for asynchronous delivery. Never blocks or raises."""
|
|
32
33
|
try:
|
|
33
34
|
self._queue.put_nowait(event)
|
|
35
|
+
logger.debug("watchdock_errors: event enqueued (queue size ~%d)", self._queue.qsize())
|
|
34
36
|
except queue.Full:
|
|
35
|
-
logger.
|
|
37
|
+
logger.warning("watchdock_errors: event queue full — dropping event")
|
|
36
38
|
|
|
37
39
|
def flush(self, timeout: float = 2.0) -> None:
|
|
38
40
|
"""Block until the queue is drained or timeout expires."""
|
|
@@ -58,6 +60,8 @@ class WatchdockClient:
|
|
|
58
60
|
self._queue.task_done()
|
|
59
61
|
|
|
60
62
|
def _send(self, event: dict) -> None:
|
|
63
|
+
exc_type = event.get("exception", {}).get("type", "event")
|
|
64
|
+
logger.info("watchdock_errors: sending %s to %s", exc_type, self._config.ingest_url)
|
|
61
65
|
try:
|
|
62
66
|
response = requests.post(
|
|
63
67
|
self._config.ingest_url,
|
|
@@ -69,7 +73,21 @@ class WatchdockClient:
|
|
|
69
73
|
},
|
|
70
74
|
timeout=self._config.timeout,
|
|
71
75
|
)
|
|
72
|
-
if response.status_code
|
|
73
|
-
logger.
|
|
76
|
+
if response.status_code in (200, 201, 202):
|
|
77
|
+
logger.info("watchdock_errors: event accepted (%s)", response.status_code)
|
|
78
|
+
else:
|
|
79
|
+
logger.warning(
|
|
80
|
+
"watchdock_errors: ingest rejected — status=%s body=%s",
|
|
81
|
+
response.status_code,
|
|
82
|
+
response.text[:500],
|
|
83
|
+
)
|
|
84
|
+
except requests.exceptions.ConnectionError as e:
|
|
85
|
+
logger.error("watchdock_errors: connection failed — %s — is the endpoint reachable?", e)
|
|
86
|
+
except requests.exceptions.Timeout:
|
|
87
|
+
logger.error(
|
|
88
|
+
"watchdock_errors: request timed out after %ss — endpoint=%s",
|
|
89
|
+
self._config.timeout,
|
|
90
|
+
self._config.ingest_url,
|
|
91
|
+
)
|
|
74
92
|
except Exception:
|
|
75
|
-
logger.
|
|
93
|
+
logger.error("watchdock_errors: unexpected error sending event", exc_info=True)
|
|
@@ -17,7 +17,7 @@ class SDKConfig:
|
|
|
17
17
|
|
|
18
18
|
# Internal — appended to every event payload
|
|
19
19
|
sdk_name: str = field(default="watchdock-errors", init=False, repr=False)
|
|
20
|
-
sdk_version: str = field(default="0.1.
|
|
20
|
+
sdk_version: str = field(default="0.1.2", init=False, repr=False)
|
|
21
21
|
|
|
22
22
|
@property
|
|
23
23
|
def ingest_url(self) -> str:
|
{watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/integrations/django.py
RENAMED
|
@@ -34,12 +34,11 @@ class DjangoErrorMiddleware:
|
|
|
34
34
|
self.get_response = get_response
|
|
35
35
|
|
|
36
36
|
def __call__(self, request: "HttpRequest") -> "HttpResponse":
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return response
|
|
37
|
+
return self.get_response(request)
|
|
38
|
+
|
|
39
|
+
def process_exception(self, request: "HttpRequest", exception: Exception) -> None:
|
|
40
|
+
watchdock_errors.capture_exception(exception, request_context=_build_request_context(request))
|
|
41
|
+
return None
|
|
43
42
|
|
|
44
43
|
|
|
45
44
|
def _build_request_context(request: "HttpRequest") -> dict:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/integrations/__init__.py
RENAMED
|
File without changes
|
{watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors/integrations/fastapi.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors.egg-info/requires.txt
RENAMED
|
File without changes
|
{watchdock_errors-0.1.0 → watchdock_errors-0.1.2}/src/watchdock_errors.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|