Files
Evan Purkhiser 64dfeaa1f1 ref(skills): move superseded skills to skills-legacy (#265)
These per-SDK skills, plus a handful of setup/workflow skills, are superseded
by the sentry-instrument skill and the references/sdks/ trees. Move them under
skills-legacy/ so they are excluded from the plugin build and skipped by the
drift automation, while skills.sentry.dev can still serve them as a fallback
for existing URL consumers.

Moves 26 skills: the 19 per-SDK skills plus sentry-sdk-skill-creator,
sentry-fix-issues, the three sentry-span-streaming-* skills,
sentry-instrument-logging, and sentry-instrumentation-guide. Regenerates
SKILL_TREE.md and repaths the moved entries in CODEOWNERS.

sentry-sdk is intentionally left in place; its removal is handled in a
separate PR.
2026-07-10 11:51:09 -04:00

8.1 KiB
Raw Permalink Blame History

Logging — Sentry Python SDK

Minimum SDK: sentry-sdk 2.35.0+ for structured Sentry Logs (enable_logs=True)

Two Logging Systems

System Produces Requires
Sentry Structured Logs Searchable log records in Sentry Logs UI enable_logs=True + sentry_sdk.logger.*
LoggingIntegration (classic) Breadcrumbs and/or error events from stdlib logging Auto-enabled by default

These run simultaneously. They are not mutually exclusive.

Configuration

import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
import logging

sentry_sdk.init(
    dsn="https://<key>@<org>.ingest.sentry.io/<project>",
    enable_logs=True,                    # required for structured Sentry Logs
    integrations=[
        LoggingIntegration(
            sentry_logs_level=logging.INFO,   # stdlib records → Sentry Logs (requires enable_logs=True)
            level=logging.INFO,               # stdlib records → breadcrumbs
            event_level=logging.ERROR,        # stdlib records → Sentry error events
        ),
    ],
)

LoggingIntegration parameters

Parameter Default Effect
sentry_logs_level INFO Records ≥ level → structured Sentry Logs (needs enable_logs=True)
level INFO Records ≥ level → breadcrumbs (attached to next error event)
event_level ERROR Records ≥ level → standalone Sentry error events

Code Examples

Sentry Structured Logs — direct API

import sentry_sdk
from sentry_sdk import logger as sentry_logger

sentry_sdk.init(dsn="...", enable_logs=True)

sentry_logger.trace("Starting database connection {database}", database="users")
sentry_logger.debug("Cache miss for user {user_id}", user_id=123)
sentry_logger.info("Updated global cache")
sentry_logger.warning("Rate limit reached for endpoint {endpoint}", endpoint="/api/results/")
sentry_logger.error(
    "Failed to process payment. Order: {order_id}. Amount: {amount}",
    order_id="or_2342",
    amount=99.99,
)
sentry_logger.fatal("Database {database} connection pool exhausted", database="users")

Template {attribute_name} placeholders become individually searchable attributes in the Sentry Logs UI.

Extra structured attributes

from sentry_sdk import logger as sentry_logger

sentry_logger.error(
    "Payment processing failed",
    attributes={
        "payment.provider": "stripe",
        "payment.method": "credit_card",
        "payment.currency": "USD",
        "user.subscription_tier": "premium",
    },
)

stdlib logging → Sentry Logs

import logging
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration

sentry_sdk.init(
    dsn="...",
    enable_logs=True,
    integrations=[LoggingIntegration(sentry_logs_level=logging.INFO)],
)

logger = logging.getLogger(__name__)
logger.info("User signed in", extra={"user_id": 42, "region": "eu-west-1"})
# extra fields become searchable attributes on the log entry

Loguru integration

import sentry_sdk
from loguru import logger

# LoguruIntegration auto-activates when loguru is installed
sentry_sdk.init(dsn="...", enable_logs=True)

logger.info("Application started")
logger.error("Critical failure in payment module")

Manual configuration for full control:

import sentry_sdk
from sentry_sdk.integrations.loguru import LoguruIntegration, LoggingLevels

sentry_sdk.init(
    dsn="...",
    enable_logs=True,
    integrations=[
        LoguruIntegration(
            sentry_logs_level=LoggingLevels.INFO.value,    # → structured logs
            level=LoggingLevels.INFO.value,                # → breadcrumbs
            event_level=LoggingLevels.ERROR.value,         # → error events
        )
    ],
)

before_send_log hook — filter and modify

import sentry_sdk
from typing import Optional

def before_log(log, hint) -> Optional[dict]:
    # Drop all INFO logs
    if log["severity_text"] == "info":
        return None
    # Add custom attribute
    log["attributes"]["processed_by"] = "before_log"
    return log

sentry_sdk.init(dsn="...", enable_logs=True, before_send_log=before_log)

Log object schema

Key Type Description
severity_text str "trace" / "debug" / "info" / "warning" / "error" / "fatal"
severity_number int 1–24 (OpenTelemetry spec)
body str Rendered message string
attributes dict Custom key-value pairs
time_unix_nano int Unix epoch in nanoseconds
trace_id str | None Associated trace ID

Suppress noisy loggers

Events/breadcrumbs and Sentry Logs have separate ignore lists. ignore_logger() only suppresses breadcrumbs and error events — it does not affect Sentry Logs. This means framework loggers silenced for events (e.g. django.server) can still be captured as Sentry Logs.

from sentry_sdk.integrations.logging import (
    ignore_logger,
    ignore_logger_for_sentry_logs,
    unignore_logger,
    unignore_logger_for_sentry_logs,
)

# Suppress breadcrumbs and error events only (Sentry Logs still captured)
ignore_logger("a.spammy.logger")
ignore_logger("boto3.*")   # glob patterns supported

# Suppress Sentry Logs only (breadcrumbs and error events still captured)
ignore_logger_for_sentry_logs("a.noisy.logger")

# Reverse a previous ignore
unignore_logger("a.spammy.logger")
unignore_logger_for_sentry_logs("a.noisy.logger")
Helper Affects
ignore_logger(name) Breadcrumbs + error events only
ignore_logger_for_sentry_logs(name) Sentry Logs only
unignore_logger(name) Reverses ignore_logger()
unignore_logger_for_sentry_logs(name) Reverses ignore_logger_for_sentry_logs()

Decision Table

Goal Tool
Searchable structured records in Sentry Logs UI sentry_sdk.logger.* + enable_logs=True
Bridge existing stdlib logging to Sentry Logs LoggingIntegration(sentry_logs_level=...) + enable_logs=True
Bridge loguru to Sentry Logs LoguruIntegration(sentry_logs_level=...) + enable_logs=True
Breadcrumbs for error context LoggingIntegration(level=logging.INFO) (default)
Auto-create error events from log calls LoggingIntegration(event_level=logging.ERROR) (default)
Drop/modify a log before sending before_send_log callback
Suppress a logger from breadcrumbs/events only ignore_logger(name)
Suppress a logger from Sentry Logs only ignore_logger_for_sentry_logs(name)
Re-enable a previously ignored logger unignore_logger(name) / unignore_logger_for_sentry_logs(name)

Automatically Added Attributes

Every log record receives these automatically:

Attribute Source
sentry.environment init(environment=...)
sentry.release init(release=...)
sentry.sdk.name / sentry.sdk.version SDK metadata
server.address hostname
sentry.message.template Original template string
sentry.message.parameter.* Template placeholder values
user.id, user.name, user.email Active scope user (if set)

Troubleshooting

Issue Solution
sentry_sdk.logger.* calls have no effect Ensure enable_logs=True is set in sentry_sdk.init()
stdlib logs not appearing as Sentry Logs Set sentry_logs_level in LoggingIntegration and enable_logs=True
Logger's own level filters out records SDK respects the logger's configured level — set it to logging.INFO or lower
Too many log records hitting quota Use before_send_log to filter by severity or attribute
Loguru not auto-activating Verify loguru is installed; or add LoguruIntegration() explicitly
ignore_logger() still sending Sentry Logs Expected — ignore_logger() only suppresses breadcrumbs/events; use ignore_logger_for_sentry_logs() to suppress Sentry Logs
Framework logger (e.g. django.server) not appearing in Sentry Logs It may be in the default Sentry Logs ignore list; call unignore_logger_for_sentry_logs("django.server")