Error Monitoring¶
An unhandled exception in production is either logged to a file nobody
tails, or it's in front of you the moment it happens. zeython.error_monitoring
is the second option: an opt-in Sentry integration that
reports unhandled request exceptions, jobs that exhaust their retries, and
scheduled tasks that raise -- the same three places docs/observability.md,
docs/queues.md, and docs/scheduling.md already log to, now also sent
somewhere you get paged for.
Requires the sentry extra: pip install zeython[sentry].
Setup¶
# main.py
from zeython import Application, ErrorMonitoringServiceProvider
app = Application()
app.register(ErrorMonitoringServiceProvider(app))
Not registered by default. ErrorMonitoringServiceProvider.register() is a
no-op if SENTRY_DSN isn't set -- safe to always register, including in
dev/test environments that never configure one.
Configurable via .env:
SENTRY_DSN-- required to do anything at all.SENTRY_TRACES_SAMPLE_RATE-- default0.0(errors only, no performance tracing).SENTRY_RELEASE-- optional;APP_ENV/app.envis passed through as the Sentryenvironmentautomatically.
What gets reported¶
- Unhandled request exceptions -- anything that reaches
unhandled_exception_handler(a genuine bug, not anHTTPExceptionsubclass likeNotFoundException-- those are expected control flow, handled separately, and never reported). Tagged withrequest_id,path, andmethod. - A queued job that exhausts its retries (
InMemoryQueue/RedisQueue, see Background Jobs) -- only the final, exhausted attempt, not every individual retry. A transient failure a retry then fixes isn't worth an alert. Tagged withjob. - A scheduled task that raises (see Scheduling) --
every failure, since a scheduled task has no retry concept to begin
with. Tagged with
scheduled_event.
Reporting your own exceptions¶
report_exception() is the same function the framework calls internally
-- use it anywhere you catch and handle an exception yourself but still
want it visible:
from zeython import report_exception
try:
await risky_operation()
except SomeExpectedError as exc:
report_exception(exc, operation="risky_operation")
# handle it and continue -- still worth knowing it happened
Always safe to call, whether or not ErrorMonitoringServiceProvider is
registered or sentry-sdk is even installed -- a no-op in both cases,
never a crash from calling it in an app that hasn't configured error
monitoring.
Testing¶
ErrorMonitoringServiceProvider and report_exception() are both plain,
mockable Python -- monkeypatch report_exception where it's imported to
assert it was called, without a real Sentry DSN or network call: