Server

Python SDK

Server-side error tracking for Python — sankofa-catch on PyPI. Errors, transactions, profiling, and WSGI + ASGI middlewares.

The Sankofa Python SDK is published to PyPI as sankofa-catch. Like the other server SDKs, it focuses on Catch — error capture, breadcrumbs, transactions, profiling — with WSGI and ASGI middleware adapters for any Python web framework.

For installation and project setup, see Install on Python.

Requirements

  • Python 3.9+ (3.11+ recommended)
  • pip 22+

Build artifact identifiers

FieldValue
PyPI packagesankofa-catch
Import namesankofa_catch
Version0.1.0

Initialize

Call init once at startup, before any imports that may throw:

Pythonapp.py
import os
import sankofa_catch

sankofa_catch.init(
  api_key=os.environ["SANKOFA_KEY"],
  endpoint="https://api.sankofa.dev",
  release=os.environ.get("RELEASE_SHA"),
  environment=os.environ.get("ENV", "production"),
  traces_sample_rate=0.1,
)

Init parameters

api_keystrRequired
Server-side API key.
endpointstrRequired
Server base URL.
releasestr
Commit SHA / version tag for source-map matching.
environmentstrdefault production
Free-form label tagged onto every event.
app_versionstr
Your app's user-facing version string.
server_namestr
Hostname / pod identifier — auto-detected if omitted.
autocapture_consolebooldefault True
Capture print() / logging.error as breadcrumbs.
capture_unhandledbooldefault True
Auto-capture sys.excepthook.
traces_sample_ratefloatdefault 0.1
Distributed-tracing sample rate (0.0–1.0).
disable_disk_queuebooldefault False
Set True for short-lived processes.
read_flag_snapshotCallable[[], dict]
Optional callback for flag context on error events.
read_config_snapshotCallable[[], dict]
Optional callback for config context on error events.
debugbooldefault False
Verbose logging.

Capture errors

Python
import sankofa_catch

try:
  charge_card(amount)
except Exception as exc:
  event_id = sankofa_catch.capture_exception(exc)
  print(f"Captured exception {event_id}")

# Non-error event
sankofa_catch.capture_message("Payment retry attempted", level="info")

WSGI middleware

For any WSGI framework (Flask, Django, Pyramid, Bottle, etc.):

Pythonapp.py
from flask import Flask
import sankofa_catch
from sankofa_catch.wsgi import SankofaWSGI

sankofa_catch.init(api_key=os.environ["SANKOFA_KEY"], endpoint="https://api.sankofa.dev")

app = Flask(__name__)
app.wsgi_app = SankofaWSGI(app.wsgi_app)

@app.route("/")
def home():
  return "ok"

For Django:

Pythonwsgi.py
import os
import sankofa_catch
from sankofa_catch.wsgi import SankofaWSGI
from django.core.wsgi import get_wsgi_application

sankofa_catch.init(api_key=os.environ["SANKOFA_KEY"], endpoint="https://api.sankofa.dev")

application = SankofaWSGI(get_wsgi_application())

ASGI middleware

For FastAPI, Starlette, or any ASGI framework:

Pythonmain.py
from fastapi import FastAPI
import sankofa_catch
from sankofa_catch.asgi import SankofaASGI

sankofa_catch.init(api_key=os.environ["SANKOFA_KEY"], endpoint="https://api.sankofa.dev")

app = FastAPI()
app.add_middleware(SankofaASGI)

@app.get("/")
async def home():
  return {"ok": True}

Both middlewares:

  • Generate a unique request ID (or read incoming traceparent);
  • Stamp $request_method, $request_path, $user_agent on every event;
  • Catch unhandled exceptions in the request and forward them to capture_exception.

User context, tags, breadcrumbs

Python
sankofa_catch.set_user({
  "id": "user_123",
  "email": "ada@example.com",
  "plan": "pro",
})

sankofa_catch.set_tags({"feature": "billing", "region": "eu-west"})
sankofa_catch.set_extra("amount", 49.99)

sankofa_catch.add_breadcrumb({
  "category": "user-action",
  "message": "Clicked checkout",
  "level": "info",
  "data": {"form_id": "checkout"},
})

Transactions and spans

Python
tx = sankofa_catch.start_transaction(
  name="checkout_handler",
  op="http.server",
)

try:
  span = tx.start_child(name="db.query.orders", op="db")
  orders = run_db_query()
  span.finish()

  tx.set_status("ok")
except Exception:
  tx.set_status("internal_error")
  raise
finally:
  tx.finish()

Profiling

Python
profiler = sankofa_catch.start_profile(sampling_interval_us=10_000)
try:
  # ... do work ...
  pass
finally:
  profiler.stop()

Web vitals

Python
sankofa_catch.capture_vital(
  name="lcp",
  value=2400.0,
  rating="needs-improvement",
  url=request.path,
)

Graceful shutdown

For long-running processes:

Python
import atexit
atexit.register(sankofa_catch.flush)
atexit.register(sankofa_catch.shutdown)

For Celery workers, hook the worker_shutdown signal:

Python
from celery.signals import worker_shutdown

@worker_shutdown.connect
def on_worker_shutdown(**kwargs):
  sankofa_catch.flush()
  sankofa_catch.shutdown()

For Django, manually call sankofa_catch.capture_exception from your process_exception middleware or signal handlers — there's no automatic Django integration today.

API summary

FunctionDescription
sankofa_catch.init(...)Initialize the SDK.
sankofa_catch.get_client()Get the global client.
sankofa_catch.capture_exception(err)Record an error, returns event ID.
sankofa_catch.capture_message(msg, level=...)Record a non-error event.
sankofa_catch.add_breadcrumb(crumb)Add a breadcrumb.
sankofa_catch.set_user(user)Set the current user.
sankofa_catch.set_tags(tags)Set tags.
sankofa_catch.set_extra(key, value)Set un-indexed extras.
sankofa_catch.start_transaction(...)Begin a transaction.
sankofa_catch.start_profile(...)Begin a profile.
sankofa_catch.capture_vital(...)Record a Web-Vitals-style metric.
sankofa_catch.flush()Drain the queue.
sankofa_catch.shutdown()Flush + dispose.
sankofa_catch.wsgi.SankofaWSGIWSGI middleware.
sankofa_catch.asgi.SankofaASGIASGI middleware.

What's next

Edit this page on GitHub