Skip to main content

errorgap

Python notifier for Errorgap. Captures exceptions, normalizes tracebacks with bounded source excerpts for readable frames, and ships notices to an Errorgap server. Single package covers plain Python, Django, Flask, and FastAPI.

Install

pip install errorgap

For framework integrations:

pip install "errorgap[django]"   # or [flask], [fastapi]

Requires Python 3.9+.

Configure

import errorgap

errorgap.init(
    endpoint=...,
    project_slug=...,
    api_key=...,
    environment="production",
)

init reads the same values from ERRORGAP_ENDPOINT, ERRORGAP_PROJECT_SLUG, ERRORGAP_PROJECT_ID, and ERRORGAP_API_KEY if you don't pass them. By default it installs a sys.excepthook to catch uncaught exceptions in scripts; pass capture_globals=False to skip.

Manual notification

try:
    risky()
except Exception as exc:
    errorgap.notify(exc, context={"component": "billing"})
    raise

notify returns a DeliveryResult (status, body, error, queued). The SDK never raises.

Filtering, hooks and delivery

import re
import errorgap

def before_notify(notice):
    if notice["errors"][0]["type"] == "Http404":
        return False                      # drop it
    notice["context"]["team"] = "billing"  # or change it

errorgap.init(
    filter_keys=("password", "token", re.compile(r"^ssn$")),
    ignore_environments=["test"],
    before_notify=before_notify,
)

filter_keys (substrings or compiled patterns) are masked at any depth in params and session. Values that cannot be serialized, reference cycles and oversized strings or collections are cut rather than losing the notice. An exception's cause chain (raise … from, or the exception being handled when it was raised) is reported with it, and the Django middleware names the signed-in user.

Notices are queued (at most queue_size, oldest dropped first) and sent by a background thread with a timeout per request. A send that fails on the network or with a 5xx is retried up to three times; after a 429 the SDK stops sending for the server's Retry-After. With release unset it is read from ERRORGAP_RELEASE, the hosting platform's commit variable or the git checkout.

Remote settings

Errors and performance data can each be switched off for a project in errorgap (Project settings › What SDKs send). Running apps follow within ten minutes, with no deploy: the SDK re-reads GET /api/projects/:slug/config on a background thread. If errorgap cannot be reached, everything stays on. errorgap.init(remote_settings=False) (or ERRORGAP_REMOTE_SETTINGS=false) ignores the project's switches.

Django

Add to MIDDLEWARE:

MIDDLEWARE = [
    "errorgap.django.ErrorgapMiddleware",
    # ... your existing middleware ...
]

With apm_enabled=True each request is also an APM transaction grouped by its URL pattern (/orders/<int:order_id>); errors raised during it carry its transaction id, and the browser SDK's x-errorgap-trace header is recorded. Record spans from a view with errorgap.django.spans(request).database(sql, ms).

Flask

from flask import Flask
from errorgap.flask import init_app

app = Flask(__name__)
init_app(app)

init_app also times each request as an APM transaction (sent with apm_enabled=True) grouped by its URL rule (/orders/<int:id>), and errors raised during the request carry its transaction id. Record spans from a view with errorgap.flask.spans():

from errorgap.flask import spans

@app.route("/orders/<int:order_id>")
def order(order_id):
    started = time.perf_counter()
    row = db.execute("SELECT * FROM orders WHERE id = %s", (order_id,)).fetchone()
    spans().database("SELECT * FROM orders WHERE id = %s", (time.perf_counter() - started) * 1000)
    return row

WSGI

Any WSGI app gets the same request transactions from errorgap.wsgi.ErrorgapMiddleware. Set environ["errorgap.route"] to the matched route template to group requests (otherwise the raw path is used).

from errorgap.wsgi import ErrorgapMiddleware

application = ErrorgapMiddleware(application)

Transactions and jobs

with errorgap.track_transaction("GET", "/orders/{id}", "/orders/123") as txn:
    txn.spans.database("SELECT * FROM orders WHERE id = 123", 4.2)
    txn.status_code = 200

with errorgap.track_job("ReceiptJob", queue="mailers") as txn:
    send_receipt()

Both time the block and deliver on exit even if it raises. Errors reported inside carry the transaction id (context.transaction_id), so errorgap shows the error a request raised on its trace. The id lives in a ContextVar, so concurrent threads and asyncio tasks never share one; errorgap.current_transaction_id() returns the id in effect.

When the errorgap browser SDK (@errorgap/browser 0.3+) is on the page, its API calls send an x-errorgap-trace header. The WSGI, Django and FastAPI middleware (and so Flask's init_app) record it, and track_transaction(..., trace_id=header) accepts it, so errorgap's browser Performance view links each call to the server request that answered it. Malformed values are ignored.

FastAPI

from fastapi import FastAPI
from errorgap.fastapi import ErrorgapMiddleware

app = FastAPI()
app.add_middleware(ErrorgapMiddleware)

With apm_enabled=True each request is also an APM transaction grouped by its route path (/orders/{order_id}); errors raised during it carry its transaction id, and the browser SDK's x-errorgap-trace header is recorded. Record spans from an endpoint with errorgap.fastapi.spans(request).database(sql, ms) (take request: Request as a parameter).

Other frameworks, Celery and logging

You use Add
Starlette, Quart, Litestar, Falcon (ASGI), Sanic (ASGI), Django ASGI app = errorgap.asgi.ErrorgapMiddleware(app)
Bottle, Falcon, Pyramid, CherryPy, any WSGI app app = errorgap.wsgi.ErrorgapMiddleware(app)
aiohttp web.Application(middlewares=[errorgap.aiohttp.errorgap_middleware])
Tornado class BaseHandler(errorgap.tornado.ErrorgapMixin, tornado.web.RequestHandler)
Celery errorgap.celery.install()
logging logging.getLogger().addHandler(errorgap.log_handler.ErrorgapHandler())

Import the submodule you use (from errorgap.celery import install). Celery tasks are timed as job transactions and a failed task is reported with its name, id, queue, retry count and arguments. The logging handler reports logger.exception(...) as that exception and a plain logger.error("…") as a LoggedError; it reports ERROR and above unless you pass a level.

Sign-ins

Report sign-ins to your app; errorgap shows them beside SSH logins in Security › Logins and flags a new IP, country or hour for a user. Off until you opt in, since events carry user names and IPs:

errorgap.init(project_slug="ox-coffee", auth_events=True, app_name="oxcoffee-web")

Django needs nothing else: with ErrorgapMiddleware installed, Django's user_logged_in and user_login_failed signals are reported (the user's get_username(); Django masks the password before the signal). Elsewhere, or for other outcomes:

errorgap.sign_in("success" if ok else "failure", user=email, request=request)
errorgap.sign_in("mfa_failure", user=email, request=request)

Outcomes: success, failure, password_reset, mfa_failure, locked. A Django, Flask or Starlette request supplies the IP, user agent and path (without the query string); behind a proxy, pass ip= yourself. Never pass passwords or tokens; errorgap can also store user names hashed (Security › Logins › Web apps › Privacy).

Configuration reference

Argument Default Notes
endpoint ERRORGAP_ENDPOINT or http://127.0.0.1:3030 Base URL, no trailing slash
project_slug ERRORGAP_PROJECT_SLUG Required
project_id ERRORGAP_PROJECT_ID Optional, embedded in payload
api_key ERRORGAP_API_KEY Sent as x-errorgap-project-key
environment ERRORGAP_ENVIRONMENT, ENV, or development
root_directory os.getcwd() Marks application frames; readable dependency frames also include bounded source excerpts
async_ True Background-thread delivery
logger logging.getLogger("errorgap") Pass None to silence
filter_keys ("password", "token", ...) Substring match, case-insensitive
apm_enabled False Send APM transactions
apm_sample_rate 1.0 Fraction of transactions sent (errors are unaffected)
auth_events False Send sign-ins (sign_in, Django login signals)
app_name ERRORGAP_APP_NAME or the project slug The app's name in Security › Logins
capture_globals True Install sys.excepthook

Graceful shutdown

errorgap.flush(timeout=5)     # wait for queued deliveries
errorgap.shutdown(timeout=5)  # flush + tear down background thread

Verify

curl -sS -X POST "$ERRORGAP_ENDPOINT/api/projects/$ERRORGAP_PROJECT_SLUG/notices" \
  -H "content-type: application/json" \
  -H "x-errorgap-project-key: $ERRORGAP_API_KEY" \
  -d '{"errors":[{"type":"ErrorgapInstallTest","message":"Errorgap install verification"}],"context":{"environment":"development"}}'

Then trigger a real error and confirm it appears in the Errorgap UI.

Development

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest

License

MIT.

Metadata

Release files for errorgap 0.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for errorgap 0.5.1
File Size Uploaded Provenance Actions
errorgap-0.5.1.tar.gz 37.8 kB With provenance Details for errorgap-0.5.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for errorgap 0.5.1
File Interpreter ABI Platform Actions
errorgap-0.5.1-py3-none-any.whl Python 3 none any Details for errorgap-0.5.1-py3-none-any.whl

Total release size: 75.5 kB

Release files / errorgap-0.5.1.tar.gz

Download URL errorgap-0.5.1.tar.gz
Size 37.8 kB
Tags Source
SHA-256 checksum
How to use checksums
7b48ade4792efdaa21c56f4dddef4c3b57dc0e1a29bee2cbf68552f871acea0e
BLAKE2b-256 checksum
How to use checksums
9119f7e6329f3ae1faf6a5c5cf5e2041a2a3211f9f7c81f541d4af8b30f4a087
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release files / errorgap-0.5.1-py3-none-any.whl

Download URL errorgap-0.5.1-py3-none-any.whl
Size 37.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a31ef46c6ccc22659ba2516dc1759c9843dd21714a26d5569e29f8e45b36a3db
BLAKE2b-256 checksum
How to use checksums
c753a4e453537cb4a208dc65fc1222b229d4974adc35f83156ca7e1c23070d09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Security for errorgap 0.5.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for errorgap-0.5.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page