mirror of
https://github.com/getsentry/sentry-for-ai.git
synced 2026-09-14 14:28:22 +08:00
64dfeaa1f1
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.
8.1 KiB
8.1 KiB
Logging — Sentry Python SDK
Minimum SDK:
sentry-sdk2.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") |