Skip to main content
There is no Squasher package for Python, so use OpenTelemetry or the HTTP API. Do not run 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

This guide uses OTLP/HTTP, so set the protocol to 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

Set 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 before 1.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:
This rejects the empty certificate setting and insecure transport before the exporter starts. To check the endpoint’s certificate and that the ingest header is attached to the HTTPS request, run this from the same runtime or deployment:
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 example GET /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.
Django and Flask also log each unhandled exception at error level, for example 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
Call it where you catch an error:
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.
Then select Issues in the sidebar of your project. If the error does not appear, see Troubleshooting.

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.