structlog-sentry
A structlog processor that forwards leveled log events to Sentry as breadcrumbs and captured events.
Repository Health
Technical Analysis
structlog-sentry is a small integration library that plugs a SentryProcessor into a structlog pipeline. It maps structlog’s leveled logging directly onto Sentry’s two-tier reporting model: lower-severity events become breadcrumbs attached to whatever event fires next, while events at or above a configurable threshold are captured as standalone Sentry issues, complete with exception info, tags, and context pulled from the structlog event_dict.
Because it works entirely within a single processor callable, adopting it requires no changes to how an application logs — teams keep calling log.info(...) and log.error(...) as usual, and Sentry reporting happens as a side effect of the existing logging calls. The processor exposes fine-grained controls (per-call sentry_skip, ignore_loggers, tag_keys, as_context) so teams can tune exactly what reaches Sentry without wrapping every call site in conditional logic.
What You Get
- A drop-in
SentryProcessorthat slots into an existing structlogprocessorslist - Automatic promotion of warning-and-above events into standalone Sentry issues, with lower levels recorded as breadcrumbs
- Exception capture that correctly handles both raised-exception context and explicit
exc_info=Truecalls without breaking downstreamformat_exc_infoprocessing - Configurable tagging of event_dict keys as Sentry tags, either an explicit key list or all keys via
tag_keys="__all__" - A per-call
sentry_skipescape hatch and anignore_loggersallowlist for excluding noisy or sensitive loggers - Full type hints and a
py.typedmarker for static-analysis support in consuming projects
Common Use Cases
- Wiring existing structlog-based services into Sentry without touching call sites, by adding one processor to the pipeline
- Deduplicating error reporting when both structlog and Sentry’s stdlib logging integration are present, by disabling the latter and relying solely on this processor
- Attaching request-scoped or business-context fields (user id, tenant, request path) from the event_dict as Sentry tags for faster triage
- Selectively silencing specific noisy loggers (e.g. health-check or retry loggers) from ever reaching Sentry
- Giving breadcrumb trails leading up to an error, built automatically from INFO-level structlog calls made earlier in the same request
Under The Hood
Architecture
The entire library is one processor class in structlog_sentry/__init__.py that implements structlog’s processor protocol — a callable of the form (logger, name, event_dict) -> EventDict. Internally it splits into small private helpers that mirror Sentry’s own concepts: _get_event_and_hint and _handle_event build and submit a full Sentry event (with exception info resolved by _figure_out_exc_info), while _get_breadcrumb_and_hint and _handle_breadcrumb build and attach a breadcrumb instead. A _can_record gate checks the log’s originating logger name against Sentry’s own ignored-logger set plus a user-supplied list before either path runs. All actual submission is delegated to a sentry_sdk.Scope (defaulting to the active isolation scope), so the processor holds no network or transport logic of its own — it is a translation layer between structlog’s event_dict and Sentry’s event/breadcrumb shapes, and its correctness depends entirely on staying aligned with sentry_sdk’s internal event schema and isolation-scope API.
Tech Stack
A Poetry-managed Python package targeting Python 3.7+, with sentry-sdk ^2.15.0 and structlog as its only runtime dependencies. Development tooling is pytest with pytest-cov and pytest-mock, run across environments via tox, with pre-commit hooks enforcing lint/format rules before commit. GitHub Actions workflows cover linting and commit-message validation on pull requests, a dedicated test workflow, and a tag-triggered release workflow that builds and publishes the package to PyPI via Poetry.
Code Quality
The single test module exercises the processor extensively: enabled/disabled/skip flags, per-level breadcrumb vs. event routing, exception capture from both raised exceptions and explicit exc_info=True, tag assembly (explicit key list and "__all__"), logger-name resolution fallback order, ignored-logger filtering, and breadcrumb payload shape including custom exclusion lists. Tests avoid hitting the network by installing a custom CaptureTransport that intercepts Sentry envelopes locally. The source is fully type-hinted (from __future__ import annotations, explicit Optional/Any/generic types) and ships a py.typed marker so consumers get static-analysis support; CI runs both a dedicated lint job and a test job on every pull request.
What Makes It Unique
Rather than reimplementing a logging-to-Sentry bridge from scratch, the processor defers all actual event submission to the official sentry_sdk, keeping its own surface area to level-based routing and event_dict-to-Sentry-shape translation. Its most distinctive design choice is deliberately not consuming the exc_info key from the event_dict — a documented fix for a specific ordering conflict with structlog’s own format_exc_info processor — which lets the two coexist in the same pipeline where a naive implementation would silently break one or the other.