Error tracking and monitoring for Python applications. Capture exceptions, track releases, and debug issues faster.
- Automatic exception capturing with full stack traces
- Breadcrumbs for debugging context
- User context tracking
- Release tracking
- Framework integrations (Flask, Django, FastAPI)
- Async support
- Minimal overhead
pip install statly-observeWith framework integrations:
pip install statly-observe[flask] # Flask support
pip install statly-observe[django] # Django support
pip install statly-observe[fastapi] # FastAPI/Starlette support
pip install statly-observe[all] # All integrations- Go to statly.live/dashboard/observe/setup
- Create an API key for Observe
- Copy your DSN (format:
https://<api-key>@statly.live/<org-slug>)
from statly_observe import Statly
# Initialize the SDK
Statly.init(
dsn="https://sk_live_xxx@statly.live/your-org",
environment="production",
release="1.0.0",
)
# Errors are captured automatically via sys.excepthook
# Manual capture
try:
risky_operation()
except Exception as e:
Statly.capture_exception(e)
# Capture a message
Statly.capture_message("User completed checkout", level="info")
# Set user context
Statly.set_user(
id="user-123",
email="user@example.com",
)
# Add breadcrumb for debugging
Statly.add_breadcrumb(
message="User logged in",
category="auth",
level="info",
)
# Always close before exit
Statly.close()from flask import Flask
from statly_observe import Statly
from statly_observe.integrations.flask import init_flask
app = Flask(__name__)
# Initialize Statly
Statly.init(
dsn="https://sk_live_xxx@statly.live/your-org",
environment="production",
)
# Attach to Flask app
init_flask(app)
@app.route("/")
def index():
return "Hello World"
@app.route("/error")
def error():
raise ValueError("Test error") # Automatically capturedsettings.py:
INSTALLED_APPS = [
# ...
'statly_observe.integrations.django',
]
MIDDLEWARE = [
'statly_observe.integrations.django.StatlyMiddleware',
# ... other middleware (Statly should be first)
]
# Statly configuration
STATLY_DSN = "https://sk_live_xxx@statly.live/your-org"
STATLY_ENVIRONMENT = "production"
STATLY_RELEASE = "1.0.0"wsgi.py or manage.py:
from statly_observe import Statly
from django.conf import settings
Statly.init(
dsn=settings.STATLY_DSN,
environment=settings.STATLY_ENVIRONMENT,
release=settings.STATLY_RELEASE,
)from fastapi import FastAPI
from statly_observe import Statly
from statly_observe.integrations.fastapi import init_fastapi
app = FastAPI()
# Initialize Statly
Statly.init(
dsn="https://sk_live_xxx@statly.live/your-org",
environment="production",
)
# Attach to FastAPI app
init_fastapi(app)
@app.get("/")
async def root():
return {"message": "Hello World"}
@app.get("/error")
async def error():
raise ValueError("Test error") # Automatically capturedfrom statly_observe import Statly
from statly_observe.integrations.wsgi import StatlyWSGIMiddleware
from statly_observe.integrations.asgi import StatlyASGIMiddleware
Statly.init(dsn="https://sk_live_xxx@statly.live/your-org")
# WSGI
app = StatlyWSGIMiddleware(your_wsgi_app)
# ASGI
app = StatlyASGIMiddleware(your_asgi_app)| Option | Type | Default | Description |
|---|---|---|---|
dsn |
str |
Required | Your project's Data Source Name |
environment |
str |
None |
Environment name (production, staging, development) |
release |
str |
None |
Release/version identifier for tracking |
debug |
bool |
False |
Enable debug logging to stderr |
sample_rate |
float |
1.0 |
Sample rate for events (0.0 to 1.0) |
max_breadcrumbs |
int |
100 |
Maximum breadcrumbs to store |
before_send |
callable |
None |
Callback to modify/filter events before sending |
def before_send(event):
# Filter out specific errors
if "KeyboardInterrupt" in event.get("message", ""):
return None # Drop the event
# Scrub sensitive data
if "extra" in event and "password" in event["extra"]:
del event["extra"]["password"]
return event
Statly.init(
dsn="...",
before_send=before_send,
)Capture an exception with optional additional context:
try:
process_payment(order)
except PaymentError as e:
Statly.capture_exception(
e,
extra={
"order_id": order.id,
"amount": order.total,
},
tags={
"payment_provider": "stripe",
},
)Capture a message event:
Statly.capture_message("User signed up", level="info")
Statly.capture_message("Payment failed after 3 retries", level="warning")
Statly.capture_message("Database connection lost", level="error")Levels: "debug" | "info" | "warning" | "error" | "fatal"
Set user context for all subsequent events:
Statly.set_user(
id="user-123",
email="user@example.com",
username="johndoe",
# Custom fields
subscription="premium",
)
# Clear user on logout
Statly.set_user(None)Set tags for filtering and searching:
Statly.set_tag("version", "1.0.0")
Statly.set_tags({
"environment": "production",
"server": "web-1",
"region": "us-east-1",
})Add a breadcrumb for debugging context:
Statly.add_breadcrumb(
message="User clicked checkout button",
category="ui.click",
level="info",
data={
"button_id": "checkout-btn",
"cart_items": 3,
},
)# Flush pending events (keeps SDK running)
Statly.flush()
# Flush and close (use before process exit)
Statly.close()Use context manager for automatic cleanup:
from statly_observe import Statly
with Statly.init(dsn="...") as client:
# Your code here
pass
# Automatically flushed and closedThe SDK automatically detects async contexts:
import asyncio
from statly_observe import Statly
async def main():
Statly.init(dsn="...")
try:
await risky_async_operation()
except Exception as e:
Statly.capture_exception(e)
await Statly.flush_async()
asyncio.run(main())Capture Python logging as breadcrumbs or events:
import logging
from statly_observe import Statly
from statly_observe.integrations.logging import StatlyHandler
Statly.init(dsn="...")
# Add handler to capture logs as breadcrumbs
handler = StatlyHandler(level=logging.INFO)
logging.getLogger().addHandler(handler)
# Now logs are captured
logging.info("User logged in") # Becomes a breadcrumb
logging.error("Database error") # Captured as error event- Python 3.8+
- Works with sync and async code
MIT