Skip to content

Sentry Integration

LogXide provides seamless integration with Sentry for automatic error tracking and monitoring. When Sentry is configured in your application, LogXide automatically detects it and sends WARNING, ERROR, and CRITICAL level logs to Sentry.

Installation

To use Sentry integration, install LogXide with the sentry extra:

pip install logxide[sentry]

Quick Start

LogXide automatically detects and integrates with Sentry when you configure it:

# 1. Configure Sentry as usual
import sentry_sdk
sentry_sdk.init(
    dsn="https://your-dsn@sentry.io/project-id",
    environment="production",
    traces_sample_rate=1.0,
)

# 2. Use LogXide - Sentry integration is automatic!
from logxide import logging

logger = logging.getLogger(__name__)

# These will automatically go to Sentry
logger.warning("This warning will appear in Sentry")
logger.error("This error will be tracked in Sentry")
logger.critical("Critical issues are sent to Sentry")

# These won't go to Sentry (below WARNING level)
logger.info("Info messages are not sent to Sentry")
logger.debug("Debug messages are not sent to Sentry")

That's it! No additional configuration needed.

Detection requires a configured SDK

Auto-detection attaches a Sentry handler only when the Sentry SDK is already configured — that is, sentry_sdk.init() (or the equivalent environment variables) has run before you use LogXide. Merely having sentry-sdk installed but never initialized does not attach a Sentry handler. As of 0.2.1, importing an unconfigured Sentry SDK also no longer forces process-global caller-frame collection onto unrelated handlers, so logs whose format string does not need caller info stay on the fast path.

Manual Handler Configuration

For more control, you can manually configure the Sentry handler:

from logxide import logging, SentryHandler

# Create a logger
logger = logging.getLogger('myapp')

# Create and configure Sentry handler
sentry_handler = SentryHandler(
    level=logging.ERROR,  # Only send ERROR and above
    with_breadcrumbs=False  # Disable breadcrumbs
)

# Add handler to logger
logger.addHandler(sentry_handler)

Features

Automatic Level Filtering

By default, LogXide sends only WARNING level and above to Sentry to avoid noise:

  • DEBUG: Not sent to Sentry
  • INFO: Not sent to Sentry
  • WARNING: Sent to Sentry
  • ERROR: Sent to Sentry
  • CRITICAL: Sent to Sentry

Exception Tracking

Exceptions are automatically captured with full stack traces:

logger = logging.getLogger(__name__)

try:
    1 / 0
except ZeroDivisionError:
    # This sends the exception to Sentry with stack trace
    logger.exception("Division by zero occurred")

Rich Context

LogXide automatically includes rich context in Sentry events:

# Context is automatically included
logger.error("Database connection failed", extra={
    "database": "production",
    "host": "db.example.com",
    "retry_count": 3
})

The following context is automatically captured: - Logger name - Thread and process information - Source code location (file, line, function) - Timestamp - Custom extra data

Structured Logging with Sentry

Use Sentry's scope for additional context:

import sentry_sdk

# Add user context
with sentry_sdk.configure_scope() as scope:
    scope.user = {"id": "123", "username": "alice"}
    logger.error("User action failed")  # Includes user context

# Add custom tags
with sentry_sdk.configure_scope() as scope:
    scope.set_tag("module", "payment")
    scope.set_tag("action", "process_order")
    logger.error("Payment processing failed")

# Add breadcrumbs for debugging
sentry_sdk.add_breadcrumb(
    message="User clicked checkout",
    category="ui",
    level="info"
)
logger.error("Checkout failed")  # Breadcrumb trail included

Configuration Options

Control Sentry Integration

Configure the SDK before constructing a handler: availability is checked at handler creation, not again for every log. Attach the handler with addHandler, not basicConfig(handlers=...), which this adapter does not support. This dedicated logger uses the direct LogXide getLogger API and does not propagate to the automatically configured root handler, avoiding duplicate events.

import sentry_sdk

sentry_sdk.init(dsn="your-dsn")

from logxide import SentryHandler, getLogger, logging

logger = getLogger("myapp.sentry")
logger.setLevel(logging.WARNING)
logger.propagate = False
sentry_handler = SentryHandler()
logger.addHandler(sentry_handler)

if sentry_handler.is_available:
    print("Sentry is configured and ready")

Environment Variables

LogXide respects standard Sentry environment variables:

export SENTRY_DSN="https://your-dsn@sentry.io/project-id"
export SENTRY_ENVIRONMENT="production"
export SENTRY_RELEASE="myapp@1.0.0"

Custom Filtering

After configuring the SDK, use a dedicated logger with a handler-level filter. Python handler filters receive a LogRecord with getMessage(); raw LogXide logger filters receive a dictionary instead, so do not attach this filter with logger.addFilter. Disable propagation so an unfiltered root Sentry handler cannot forward the same message.

from logxide import SentryHandler, getLogger, logging

class SensitiveDataFilter(logging.Filter):
    def filter(self, record):
        # Check the rendered message, including %-format arguments.
        return 'password' not in record.getMessage().lower()

logger = getLogger("myapp.sentry.filtered")
logger.setLevel(logging.WARNING)
logger.propagate = False
sentry_handler = SentryHandler()
sentry_handler.addFilter(SensitiveDataFilter())
logger.addHandler(sentry_handler)

This example drops matching messages only on this logger's Sentry route. It is not general data scrubbing: it does not inspect extra, exception contents, other loggers, or events captured by Sentry framework integrations. Never log secrets; configure SDK event scrubbing separately for those other paths.

Best Practices

1. Use Appropriate Log Levels

# Good practices
logger.debug("Detailed debug info")  # Development only
logger.info("User logged in")  # Normal operations
logger.warning("API rate limit approaching")  # Warnings to Sentry
logger.error("Failed to process payment")  # Errors to Sentry
logger.critical("Database connection lost")  # Critical to Sentry

2. Include Helpful Context

# Include relevant context
logger.error("Order processing failed", extra={
    "order_id": order.id,
    "user_id": user.id,
    "payment_method": order.payment_method,
    "error_code": "PAYMENT_DECLINED"
})

3. Use Exception Logging

try:
    process_order(order)
except ProcessingError as e:
    # Use exception() to include stack trace
    logger.exception("Order processing failed: %s", e, extra={
        "order_id": order.id
    })
# Use consistent messages for grouping in Sentry
logger.error("Database query timeout", extra={
    "query": str(query),
    "duration": query_time,
    "table": "orders"
})

Performance Considerations

Asynchronous Sending

LogXide and Sentry both use asynchronous sending to avoid blocking:

# This returns immediately
logger.error("Error message")  # Sent async to Sentry

# Force synchronous flush if needed
import sentry_sdk
sentry_sdk.flush()  # Wait for all events to be sent

Rate Limiting

Sentry has built-in rate limiting. For high-volume applications:

# Configure sampling
sentry_sdk.init(
    dsn="...",
    sample_rate=0.25,  # Send 25% of events
    traces_sample_rate=0.1,  # 10% of performance data
)

Disable in Development

import os

# Only enable Sentry in production
if os.getenv("ENVIRONMENT") == "production":
    sentry_sdk.init(dsn="...")

from logxide import logging  # Auto-detects Sentry config

Troubleshooting

Sentry Not Receiving Events

  1. Check Sentry Configuration:

    import sentry_sdk
    print(sentry_sdk.Hub.current.client)  # Should not be None
    

  2. Verify Handler is Active:

    from logxide import SentryHandler
    handler = SentryHandler()
    print(handler.is_available)  # Should be True
    

  3. Check Log Levels:

    # Make sure level is WARNING or above
    logger.setLevel(logging.WARNING)
    

  4. Force Flush:

    # Ensure events are sent before exit
    logging.flush()
    sentry_sdk.flush(timeout=2.0)
    

Testing Sentry Integration

# Test script
import sentry_sdk
sentry_sdk.init(dsn="your-dsn")

from logxide import logging
logger = logging.getLogger("test")

# Test different levels
logger.warning("Test warning")
logger.error("Test error")

try:
    raise ValueError("Test exception")
except ValueError:
    logger.exception("Test exception logging")

# Ensure delivery
logging.flush()
sentry_sdk.flush(timeout=2.0)
print("Check your Sentry dashboard!")

Integration with Frameworks

Flask

import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration

sentry_sdk.init(
    dsn="your-dsn",
    integrations=[FlaskIntegration()]
)

from flask import Flask
from logxide import logging

app = Flask(__name__)
logger = logging.getLogger(__name__)

@app.errorhandler(500)
def handle_error(error):
    logger.error("Internal server error", exc_info=error)
    return "Internal Server Error", 500

Django

# settings.py
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration

sentry_sdk.init(
    dsn="your-dsn",
    integrations=[DjangoIntegration()]
)

# Use LogXide in your views
from logxide import logging
logger = logging.getLogger(__name__)

def my_view(request):
    logger.info("View accessed")  # Not sent to Sentry
    logger.error("View error")  # Sent to Sentry

FastAPI

import sentry_sdk
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware

sentry_sdk.init(dsn="your-dsn")

from fastapi import FastAPI
from fastapi.responses import JSONResponse
from logxide import logging

app = FastAPI()
app.add_middleware(SentryAsgiMiddleware)

logger = logging.getLogger(__name__)

@app.exception_handler(Exception)
async def exception_handler(request, exc):
    logger.exception("Unhandled exception", exc_info=exc)
    return JSONResponse(
        status_code=500,
        content={"error": "Internal server error"}
    )

Advanced Usage

Custom Event Processors

def process_event(event, hint):
    # Modify event before sending to Sentry
    if 'user' in event:
        # Anonymize user data
        event['user']['id'] = hash(event['user'].get('id', ''))
    return event

sentry_sdk.init(
    dsn="your-dsn",
    before_send=process_event
)

Performance Monitoring

import sentry_sdk

# Enable performance monitoring
sentry_sdk.init(
    dsn="your-dsn",
    traces_sample_rate=1.0,
    profiles_sample_rate=1.0,
)

# LogXide will include timing information
with sentry_sdk.start_transaction(op="process", name="order_processing"):
    logger.info("Processing order")
    # ... processing logic ...
    logger.info("Order processed")

Security Considerations

Filtering Sensitive Data

# Don't log sensitive information
logger.error("Login failed for user", extra={
    "username": user.username,
    # Don't include: "password": user.password
})

# Use Sentry's data scrubbing
sentry_sdk.init(
    dsn="your-dsn",
    send_default_pii=False,  # Don't send personally identifiable info
)

Compliance

For GDPR and privacy compliance:

sentry_sdk.init(
    dsn="your-dsn",
    attach_stacktrace=False,  # Don't attach stack traces
    send_default_pii=False,  # Don't send PII
    request_bodies="never",  # Never send request bodies
)

Summary

LogXide's Sentry integration provides:

  • Automatic integration once the Sentry SDK is configured
  • Smart filtering of log levels
  • Rich context capture
  • Security-conscious defaults
  • High performance with async sending
  • Full control when needed

Just install, configure Sentry as usual, and LogXide handles the rest!