## There is nothing to install

Thermite speaks Sentry's wire protocol, so the official Sentry SDK for your language already
works against it. There is no `@thermite/*` package, no fork, no shim — you set the DSN and stop.

> **Tip:** This is a tested guarantee, not an intention: `an_unmodified_sentry_sdk_reports_into_thermite`
sends through a stock Sentry client on every CI run and asserts the event lands and groups.

## Get a DSN

Open **Project settings → DSN keys**. The default DSN looks like this:

```
https://<public_key>@thermite.example.com/<project_id>
```

The same card mints **component DSNs** — labeled keys for the parts of one product (`worker`,
`saas`, `cli`). They report into the same issue stream and stay filterable by component, so you
do not have to split a product into separate projects to know which half broke.

> **Note:** The public key is not a secret in the usual sense. It grants exactly one capability: sending
events to one project.

## Python

```bash
pip install sentry-sdk
```

```python
import sentry_sdk

sentry_sdk.init(
    dsn="https://<public_key>@thermite.example.com/1",
    release="myapp@1.4.2",          # or the git SHA — see Recommended settings
    environment="production",
    traces_sample_rate=0.0,          # Thermite stores no transactions
)
```

Framework integrations (Django, Flask, FastAPI, Celery, …) are auto-enabled by `sentry-sdk` and
need nothing from Thermite.

### Cron check-ins

Scheduled jobs report through the same DSN. The monitor is created on first sighting and carries
its own schedule, so nothing is configured twice:

```python
from sentry_sdk.crons import monitor

@monitor(
    monitor_slug="nightly-import",
    monitor_config={
        "schedule": {"type": "crontab", "value": "0 3 * * *"},
        "timezone": "Europe/Berlin",
        "checkin_margin": 5,   # minutes late before the run counts as missed
        "max_runtime": 30,     # minutes running before it counts as overrunning
    },
)
def nightly_import():
    ...
```

`{"type": "interval", "value": 15, "unit": "minute"}` works in place of a crontab expression.

A missed or overrunning run becomes an ordinary error event — same grouping, same alerts, same
triage queue as an exception. Cron monitoring is a new source of events, not a second pipeline.
See [Cron monitoring](/docs/guides/cron) for the schedule options, the failure modes, and how to
check in from a job with no SDK.

## JavaScript and TypeScript

```bash
bun add @sentry/browser   # or @sentry/node
```

```ts
import * as Sentry from "@sentry/browser";

Sentry.init({
  dsn: "https://<public_key>@thermite.example.com/1",
  release: "myapp@1.4.2",
  environment: "production",
  tracesSampleRate: 0,
});
```

> **Warning:** On the server, `@sentry/node` v8+ must be initialised **before** any instrumented module is
imported — put `Sentry.init()` in its own `instrument.ts` and import that first. Initialising it
halfway down `index.ts` silently loses most auto-instrumentation.

## Rust

Rust is the one language with a first-party SDK, because the Sentry Rust client is seventeen
crates and a hub-and-scope stack to fill in about fourteen fields. `thermite-sdk` models those
fields and nothing else, and builds for `wasm32-unknown-unknown`.

```rust
let mut options = thermite_sdk::Options::new(std::env::var("THERMITE_DSN")?);
options.release = Some(env!("CARGO_PKG_VERSION").to_string());
options.environment = Some("production".into());

// Held for the life of `main`: dropping it flushes whatever the sender thread still has queued.
let _guard = thermite_sdk::init(options)?;
```

Panic reporting and session tracking are both on by default. The `web` feature swaps the sender
thread for `fetch`; `tracing-layer` turns `ERROR` records into events and everything else into
breadcrumbs.

## What Thermite does with each envelope item

Every SDK sends more than Thermite reads. Nothing is rejected over the extras — an envelope
carrying a transaction still delivers its events — but it helps to know what survives:

| Item | Handling | Quota |
| --- | --- | --- |
| `event` | Stored, grouped into an issue, alerted, queued for triage | 1 per event |
| `session` | Folded into release-health rollups (crash-free rate) | none |
| `check_in` | Opens or closes a cron monitor run | none |
| `client_report` | The SDK's own drop counters, surfaced as outcomes | none |
| `transaction`, `log`, `attachment` | Dropped and counted under `unsupported:<type>` | none |

Quota is charged per **event item**, never per request — one envelope carrying fifty events costs
fifty.

### Ingest endpoints

| Endpoint | Purpose |
| --- | --- |
| `POST /api/{project_id}/envelope/` | The modern endpoint. Everything in the table above. |
| `POST /api/{project_id}/store/` | A bare event payload, for older SDKs. |
| `POST /api/{project_id}/otlp/v1/logs` | OTLP log records. Error-severity records become events; the rest are counted and dropped. |

Credentials are resolved from `?sentry_key=`, then `X-Sentry-Auth`, then the envelope's own `dsn`
header — whichever your SDK happens to use.

## Recommended settings

### Always set release
Release health and regression detection are both release-scoped: without it Thermite can group
your errors but cannot tell you what broke. Use the git SHA if you can — a triage item carries
the release that crashed, and an agent that receives a SHA can check out the revision that
actually broke instead of diagnosing against `main`.

### Always set environment
Staging noise and production incidents share an issue stream otherwise, and the dashboard's
environment filter has nothing to filter on.

### Turn tracing off
`traces_sample_rate=0` / `tracesSampleRate: 0`. Transactions cost no quota — they are dropped
on arrival — but sampling them still spends CPU and bandwidth on both ends producing something
nothing reads.

### Leave session tracking on
Sessions are the denominator of the crash-free rate and cost no quota. Off, release health
reads "not enough data" forever. It is on by default in the current SDKs; if your version
exposes a flag for it, leave it alone.

## Rate limits

An over-quota project gets `429` with both `Retry-After` and the Sentry-standard
`X-Sentry-Rate-Limits: <seconds>:error:project:quota_exceeded`. Official SDKs read that header
and back off on their own — there is nothing to configure, and a well-behaved SDK will stop
sending rather than hammer a project that is already out of budget.

Envelopes that hit the limit partway through keep the events already accepted. The SDK retries
the whole envelope, and the event ids it already delivered deduplicate on the way back in.

## Verify it works

1. **Send something on purpose**
```python
sentry_sdk.capture_message("hello from thermite")
```

2. **Check the project**
The issue appears on the project's issue list within a second or two. If it does not, the
project's **Outcomes** tell you whether the event was rejected, over quota, or never arrived.

## Next steps

**Introduction**
How the triage loop hands work to your coding agent.

**Connect an agent**
Hand the issues your SDK reports to a coding agent.

