pip install squasher: that name on PyPI belongs to a different project.
Send errors with OpenTelemetry
This setup is tested with the OpenTelemetry Python SDK 1.45 on Python 3.13, with Django 6.1, Flask 3.1, FastAPI 0.141, and Gunicorn 26.1
Install the packages
opentelemetry-bootstrap finds the libraries in your environment, such as Django, Flask,
FastAPI, or requests, and installs their instrumentation packages. It also installs the
logging instrumentation.2
Set the exporter variables
http/protobuf. OTLP requests do not need
the project ID: Squasher finds the project from the key. To use a gRPC exporter, send it to the
Collector URL on port 443 as described in Send over gRPC.
To get a key, see
Create an ingest key.3
Start your app with opentelemetry-instrument
- Django
- Flask
- FastAPI
- Gunicorn
DJANGO_SETTINGS_MODULE in the environment. --noreload is necessary: the reloader
starts a second process that is not instrumented.Keep the exporter TLS-safe
OpenTelemetry Python OTLP/HTTP exporter versions before1.45.0 are affected by
CVE-2026-112006 when
OTEL_EXPORTER_OTLP_CERTIFICATE (or a signal-specific certificate variable) is set to an empty
value. Keep the exporter at 1.45.0 or newer. Leave certificate variables unset when the normal
system certificate store is enough; if you set one, use a real certificate file path. Do not set
OTEL_EXPORTER_OTLP_INSECURE=true for Squasher endpoints.
Add this startup check before opentelemetry-instrument creates exporters:
curl verifies the certificate and hostname by default. /ready checks the ingest worker’s
configured readiness credentials and regional collector before returning 2xx. The probe sends the
configured ingest header only over HTTPS; it does not send telemetry.
The app sends traces, logs, and metrics to Squasher. Automatic AI triage
runs only on issues from the production environment, so set deployment.environment.name to
production in production.
How errors become issues
- An unhandled exception in a request. The framework instrumentation sets the span status to
error and records the exception on the span. Squasher makes an issue from the span. Django and
Flask put the exception in the status message, so the issue title is, for example,
RuntimeError: Squasher test error. FastAPI leaves the message empty, so the title is the span name, for exampleGET /squasher-test. The issue page shows the stack trace of the exception. - A log record at error level or above. Squasher makes an issue titled with the log message.
logger.exception("Checkout failed")sends the exception type, message, and stack trace as attributes of the record.
Internal Server Error: /checkout. So one exception can make two issues: one from the span and one
from the log record.
The issue page shows the stack trace from the exception.stacktrace attribute of the span event or
the log record.
Send errors with the HTTP API
Post each error to the ingest endpoint with the standard library. This example needs Python 3.10 or later.squasher_report.py
message is the only required field. stack is shown as the stack trace on the issue page. The
request sends the error at once and blocks for up to 5 seconds, so in a web request, send it from a
background thread or a task queue. See the HTTP API for all fields and for
batches.
Send a test error
- OpenTelemetry: add a route that raises
RuntimeError("Squasher test error"), and open it once. - HTTP API: run
capture_exception(RuntimeError("Squasher test error"))once.
Give the setup to a coding agent
Copy this prompt into your coding agent to set up Python the same way:Next steps
OpenTelemetry
See which OTLP data Squasher accepts.
HTTP API
See every field of the ingest endpoint.
Read AI triage
Learn what the triage summary tells you.
Troubleshooting
Find out why an event does not appear.