Skip to content

Python (Sentry-compatible SDK)

Use the official sentry-sdk for Python with a Belvador DSN and the data-scrubbing hook Belvador provides.

Markdown
On this page

For Python Belvador uses the official sentry-sdk with your Belvador DSN, plus the init options and scrubbing hook below.

Before you start#

  • A project with platform Python and its DSN.

  • A Python version supported by the current sentry-sdk release (see Sentry's Python guide).

1. Install#

Terminal
pip install --upgrade "sentry-sdk"

2. Initialize at start-up#

Put this where your app starts — before your web framework is imported is best, so its integration is set up too.

app.py
import osimport sentry_sdkimport reSENSITIVE_KEY = re.compile(r"password|passwd|pwd|secret|api_key|apikey|api-key|access_token|auth|credentials|credit_card|card_number|cvv|private_key|privatekey|session|cookie|token|bearer|ssn|dob", re.I)DROP_HEADER = re.compile(r"^(authorization|proxy-authorization|cookie|set-cookie|x-forwarded-for|x-real-ip|cf-connecting-ip|true-client-ip)$", re.I)IN_TEXT = [    (re.compile(r"\bBearer\s+[A-Za-z0-9._~+/-]+=*", re.I), "Bearer [Filtered]"),    (re.compile(r"\beyJ[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}"), "[Filtered]"),    (re.compile(r"\b[sr]k_(live|test)_[A-Za-z0-9]{8,}\b"), "[Filtered]"),    (re.compile(r"([?&#;\s\"']?[^=&#\s\"':]*(?:token|key|secret|password|session|auth)[^=&#\s\"':]*[\"']?\s*[=:]\s*[\"']?)[^&#\s\"',}]+", re.I), r"\1[Filtered]"),]def scrub_text(text):    for pattern, repl in IN_TEXT:        text = pattern.sub(repl, text)    return textdef scrub_value(value, depth=0):    if isinstance(value, str):        return scrub_text(value)    if depth > 8:        return value    if isinstance(value, (list, tuple)):        return [scrub_value(v, depth + 1) for v in value]    if isinstance(value, dict):        return {k: "[Filtered]" if SENSITIVE_KEY.search(str(k)) else scrub_value(v, depth + 1) for k, v in value.items()}    return valuedef scrub_event(event, hint):    request = event.get("request")    if request:        for field in ("data", "cookies", "env"):            request.pop(field, None)        headers = request.get("headers") or {}        for name in list(headers):            if DROP_HEADER.match(name):                del headers[name]            elif SENSITIVE_KEY.search(name):                headers[name] = "[Filtered]"        if isinstance(request.get("url"), str):            request["url"] = scrub_text(request["url"])        if request.get("query_string"):            request["query_string"] = scrub_value(request["query_string"])    user = event.get("user")    if user is not None:        event["user"] = {"id": user["id"]} if "id" in user else None    if event.get("message"):        event["message"] = scrub_text(event["message"])    if event.get("logentry"):        event["logentry"] = scrub_value(event["logentry"])    for ex in (event.get("exception") or {}).get("values") or []:        if ex.get("value"):            ex["value"] = scrub_text(ex["value"])    for field in ("extra", "contexts", "tags"):        if event.get(field):            event[field] = scrub_value(event[field])    crumbs = event.get("breadcrumbs")    if isinstance(crumbs, dict) and crumbs.get("values"):        crumbs["values"] = [scrub_value(b) for b in crumbs["values"]]    return eventsentry_sdk.init(    dsn=os.environ.get("BELVADOR_DSN", "https://<public-key>@ingest.belvador.dev/<project-id>"),    release=os.environ.get("APP_VERSION"),    environment=os.environ.get("APP_ENV", "production"),    send_default_pii=False,    traces_sample_rate=0,    max_breadcrumbs=50,    max_value_length=8192,    before_send=scrub_event,)
OptionWhy
dsnReads BELVADOR_DSN from the environment, with the project DSN as fallback
release, environmentFrom APP_VERSION and APP_ENV (default production)
send_default_pii=FalseNo IP addresses, cookies or user details added by the SDK
traces_sample_rate=0The Sentry SDK sends no spans; for traces use OpenTelemetry
max_breadcrumbs=50, max_value_length=8192Same bounds as Belvador's own SDKs
before_send=scrub_eventRemoves request bodies, cookies, auth headers and client IP headers; keeps only user.id; masks values under sensitive names and credentials in text

Frameworks#

sentry-sdk turns on integrations for frameworks it finds installed, such as Django, Flask and FastAPI, so unhandled errors in requests are reported. Framework-specific options are in Sentry's Python guide. Belvador has not verified each framework.

Report errors you handle#

Python
import sentry_sdktry:    charge_card(order)except PaymentError as error:    sentry_sdk.capture_exception(error)    raise

Check that it works#

Python
import sentry_sdksentry_sdk.capture_exception(Exception("Belvador Python test"))sentry_sdk.flush(timeout=2)

Run it with the same sentry_sdk.init(...) as your app. The issue appears in the project within a few seconds.

Limits to know#

  • The scrubbing hook is pattern-based. A secret under an unusual name, or inside a free-text message, can slip through.

  • Keep traces_sample_rate=0; tracing data is not stored and is counted as Not supported yet in the project's intake numbers.

  • Scheduled jobs and Celery beat tasks can report runs with sentry_sdk.crons — see Monitors with the official Sentry SDKs.

Posts on this topic

All posts

Spotted something wrong or missing? Tell us: hello@belvador.dev