DocumentationPython

Python

Track exceptions raised on your backend. Server errors land in the same Nohmo project as your frontend errors, so a 500 in your API sits next to the JS error it caused in the browser — and feeds the same revenue-impact ranking and the same daily digest.

The package has no runtime dependencies. It uses only the standard library, because an error reporter should never be the thing that breaks the app it is watching.

Install

bash
pip install nohmo

You install nohmo but import nohmo_sdk, the same way pip install pillow gives you import PIL. The import name stays out of the way on purpose: a package called nohmo in site-packages would shadow a nohmo package in your own project.

Django

Add your keys to settings, then add the middleware near the top.

python
# settings.py
NOHMO_PROJECT_ID = "proj_xxx"
NOHMO_API_KEY = "pk_xxx"
NOHMO_RELEASE = "2.4.1" # optional ties errors to a deploy
NOHMO_ENVIRONMENT = "production" # optional
MIDDLEWARE = [
"nohmo_sdk.integrations.django.NohmoMiddleware",
# ... your other middleware
]

Note: Place it high in MIDDLEWARE. It cannot see exceptions raised by middleware listed above it. It uses Django's process_exception hook and returns None, so your error pages, DRF handlers and everything else behave exactly as before.

Flask

python
import nohmo_sdk
from nohmo_sdk.integrations.flask import NohmoFlask
app = Flask(__name__)
nohmo_sdk.init(project_id="proj_xxx", api_key="pk_xxx")
NohmoFlask(app)

FastAPI

python
import nohmo_sdk
from nohmo_sdk.integrations.fastapi import NohmoMiddleware
nohmo_sdk.init(project_id="proj_xxx", api_key="pk_xxx")
app = FastAPI()
app.add_middleware(NohmoMiddleware)

Starlette applies middleware in reverse registration order, so add this last if you want it outermost.

Any other WSGI app

For Pyramid, Bottle, CherryPy or a hand-rolled WSGI application:

python
from nohmo_sdk.integrations.wsgi import NohmoWSGI
application = NohmoWSGI(application)

Capturing manually

Unhandled exceptions are captured automatically. Use these for errors you handle yourself but still want to know about.

python
import nohmo_sdk
try:
charge(order)
except PaymentError as exc:
nohmo_sdk.capture_exception(exc, extra={"order_id": order.id})
nohmo_sdk.capture_message("Reconciliation found a mismatch", level="warning")

Short-lived processes

Events are sent on a background thread and flushed on exit. A management command, cron job or Lambda can exit before that happens, so flush explicitly:

python
nohmo_sdk.flush(timeout=3)

Options

OptionDefaultWhat it does
environment'production'Tags every event
release''Ties errors to a deploy for the causal narrative
server_namehostnameGroups errors per server instance
sample_rate1.0Fraction of events sent
dedup_window5.0Seconds before an identical error is sent again
queue_size1000Bounded — drops rather than growing without limit
batch_size50Events per request
flush_interval5.0Seconds before a partial batch ships
send_default_piiFalseInclude headers, query strings and user email
debugFalseVerbose logging

Privacy

Headers, query strings and user email addresses are not sent unless you set send_default_pii=True. Even then, anything that looks like a credential is redacted: Authorization, Cookie, Set-Cookie, X-API-Key, CSRF tokens, and any key containing secret, token, password or private_key. Matching happens after normalising case and hyphens, so X-API-Key and x_api_key are both caught.

How it behaves under load

It will not block your requests. Capturing appends to a queue; all network I/O happens on a background thread, so a slow or unreachable Nohmo is invisible to your latency.

It will not crash your app. Every public entry point swallows its own exceptions, and calling anything before init() is a no-op rather than an error — a missing environment variable cannot break a deploy.

It will not grow without bound. The queue is capped. A crash loop that outruns the network drops events and logs the count rather than consuming memory until the process is killed.

It survives a fork. gunicorn and uWSGI preload your app and then fork worker processes. Threads do not survive fork(), so an SDK that starts its worker in the master silently sends nothing from every child. This one notices the pid change and restarts in the child.

How errors are grouped

Errors group by exception type plus the deepest frame in your code — framework and site-packages frames are skipped. Only the file basename and line number are used, so the same bug groups together across containers, virtualenvs and development machines.

Note: Python tracebacks print "most recent call last", the opposite of a JavaScript stack. Nohmo reads them from the bottom up, so grouping keys off the line that actually raised rather than your WSGI entry point — which would be identical for every error your app ever produces.