devalerts 0.2.1__tar.gz → 0.2.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.
- {devalerts-0.2.1 → devalerts-0.2.2}/PKG-INFO +17 -5
- {devalerts-0.2.1 → devalerts-0.2.2}/README.md +16 -4
- {devalerts-0.2.1 → devalerts-0.2.2}/pyproject.toml +1 -1
- {devalerts-0.2.1 → devalerts-0.2.2}/src/devalerts/__init__.py +14 -2
- {devalerts-0.2.1 → devalerts-0.2.2}/LICENSE +0 -0
- {devalerts-0.2.1 → devalerts-0.2.2}/src/devalerts/_alert.py +0 -0
- {devalerts-0.2.1 → devalerts-0.2.2}/src/devalerts/_celery.py +0 -0
- {devalerts-0.2.1 → devalerts-0.2.2}/src/devalerts/_store.py +0 -0
- {devalerts-0.2.1 → devalerts-0.2.2}/src/devalerts/_telegram.py +0 -0
- {devalerts-0.2.1 → devalerts-0.2.2}/src/devalerts/cli.py +0 -0
- {devalerts-0.2.1 → devalerts-0.2.2}/src/devalerts/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devalerts
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Send unhandled Python exceptions straight to a Telegram chat. No backend, no account, no database — just your own bot token.
|
|
5
5
|
Keywords: telegram,error-tracking,exception-monitoring,alerts,logging,monitoring,asgi
|
|
6
6
|
Author: sslinNn
|
|
@@ -151,16 +151,28 @@ devalerts.init(bot_token="...", chat_id=123456789, tags={"env": "production"})
|
|
|
151
151
|
🖥️ prod-web-2 (env=production)
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
-
Add ad-hoc tags to a single call — they override `init()`'s tags
|
|
155
|
-
collision:
|
|
154
|
+
Add ad-hoc tags to a single call — they override `init()`'s tags (and each
|
|
155
|
+
other) on a key collision:
|
|
156
156
|
|
|
157
157
|
```python
|
|
158
158
|
devalerts.report(extra={"request_id": "abc123"})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Used as a decorator, `capture()` tags the alert with the wrapped function's
|
|
162
|
+
name as `job` automatically — no `extra` needed:
|
|
159
163
|
|
|
160
|
-
|
|
161
|
-
|
|
164
|
+
```python
|
|
165
|
+
@devalerts.capture()
|
|
166
|
+
def nightly_sync(): ...
|
|
162
167
|
```
|
|
163
168
|
|
|
169
|
+
```
|
|
170
|
+
🔴 ValueError: boom
|
|
171
|
+
🖥️ prod-web-2 (job=nightly_sync)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Pass `extra={"job": "..."}` explicitly to override the auto-detected name.
|
|
175
|
+
|
|
164
176
|
## Manually reporting a caught exception
|
|
165
177
|
|
|
166
178
|
```python
|
|
@@ -124,16 +124,28 @@ devalerts.init(bot_token="...", chat_id=123456789, tags={"env": "production"})
|
|
|
124
124
|
🖥️ prod-web-2 (env=production)
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
Add ad-hoc tags to a single call — they override `init()`'s tags
|
|
128
|
-
collision:
|
|
127
|
+
Add ad-hoc tags to a single call — they override `init()`'s tags (and each
|
|
128
|
+
other) on a key collision:
|
|
129
129
|
|
|
130
130
|
```python
|
|
131
131
|
devalerts.report(extra={"request_id": "abc123"})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Used as a decorator, `capture()` tags the alert with the wrapped function's
|
|
135
|
+
name as `job` automatically — no `extra` needed:
|
|
132
136
|
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
```python
|
|
138
|
+
@devalerts.capture()
|
|
139
|
+
def nightly_sync(): ...
|
|
135
140
|
```
|
|
136
141
|
|
|
142
|
+
```
|
|
143
|
+
🔴 ValueError: boom
|
|
144
|
+
🖥️ prod-web-2 (job=nightly_sync)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Pass `extra={"job": "..."}` explicitly to override the auto-detected name.
|
|
148
|
+
|
|
137
149
|
## Manually reporting a caught exception
|
|
138
150
|
|
|
139
151
|
```python
|
|
@@ -130,17 +130,29 @@ def report(
|
|
|
130
130
|
class capture(contextlib.ContextDecorator):
|
|
131
131
|
"""Context manager / decorator: report any exception raised inside the block or
|
|
132
132
|
function, then re-raise it. Use ``@capture()`` on a function instead of wrapping
|
|
133
|
-
its body in a manual ``try/except`` or ``with`` block.
|
|
133
|
+
its body in a manual ``try/except`` or ``with`` block.
|
|
134
|
+
|
|
135
|
+
Used as a decorator, the wrapped function's name is tagged automatically as
|
|
136
|
+
``job`` -- no need to pass ``extra={"job": ...}`` by hand. Used as a bare
|
|
137
|
+
``with capture():`` block, there's no function to name, so only explicit
|
|
138
|
+
``extra`` tags apply."""
|
|
134
139
|
|
|
135
140
|
def __init__(self, *, extra: dict[str, str] | None = None) -> None:
|
|
136
141
|
self._extra = extra
|
|
142
|
+
self._job_name: str | None = None
|
|
143
|
+
|
|
144
|
+
def __call__(self, func):
|
|
145
|
+
self._job_name = func.__qualname__
|
|
146
|
+
return super().__call__(func)
|
|
137
147
|
|
|
138
148
|
def __enter__(self) -> "capture":
|
|
139
149
|
return self
|
|
140
150
|
|
|
141
151
|
def __exit__(self, exc_type, exc_value, tb) -> Literal[False]:
|
|
142
152
|
if exc_type is not None:
|
|
143
|
-
|
|
153
|
+
tags = {"job": self._job_name} if self._job_name else {}
|
|
154
|
+
tags.update(self._extra or {})
|
|
155
|
+
_send_exception(exc_type, exc_value, tb, extra=tags)
|
|
144
156
|
return False
|
|
145
157
|
|
|
146
158
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|