---
url: https://simpledatalogs.com/docs/integrations/sentry.md
description: >-
  Change only the Sentry DSN, and errors, messages and structured logs from any
  Sentry SDK arrive as countable log lines, with errors grouped into Issues.
---

# Sentry

Every Sentry SDK can send to simpledatalogs. Change only the **DSN**: its public key is your ingest key, its host is ingest, and the project id is any number.

```text
https://sdl_pub_…@edge.simpledatalogs.com/1
```

::: code-group

```python [Python]
import sentry_sdk

sentry_sdk.init(
    dsn="https://sdl_sec_…@edge.simpledatalogs.com/1",
    enable_logs=True,
    traces_sample_rate=0,
)
```

```js [Browser]
import * as Sentry from '@sentry/browser'

Sentry.init({
  dsn: 'https://sdl_pub_…@edge.simpledatalogs.com/1',
  tracesSampleRate: 0,
})
```

```js [Node]
import * as Sentry from '@sentry/node'

Sentry.init({
  dsn: 'https://sdl_pub_…@edge.simpledatalogs.com/1',
  tracesSampleRate: 0,
})
```

```sh [Laravel .env]
SENTRY_LARAVEL_DSN=https://sdl_sec_…@edge.simpledatalogs.com/1
SENTRY_TRACES_SAMPLE_RATE=0
```

:::

It works the same in every Sentry SDK (JavaScript, Python, PHP, Ruby, Go, Cocoa, Android …): they all post envelopes to `/api/<project>/envelope/`, with the key in `X-Sentry-Auth` or the `sentry_key` query parameter. The JavaScript SDKs, Node included, put the key in the query, and a URL only takes a **public** key (`sdl_pub_…`): a secret key there is refused with `401 secret_key_in_url`. Tested with `sentry-sdk` 2.35.0 and `@sentry/node` and `@sentry/browser` 8.47.0.

## What you get

Errors and messages become **log lines**, so you can count, filter and alert on them. Errors with an exception also group into [Issues](/guide/observability#issues), by type, message and release (without stack frames). Sentry's performance data and replays aren't stored.

| Field | From a Sentry event |
|---|---|
| `level` | `fatal` → critical, `error`, `warning`, `info`, `debug`; anything else → error |
| `message` | The formatted message, else the last exception's `Type: value` |
| `ts` | `timestamp` |
| `event_id` | Sentry's `event_id`, so a resend never counts twice |
| `user_id` | `user.id` |
| `props` | `exception.type`, `exception.value`, `exception.mechanism`, `stacktrace` (the last exception's frames as text, up to 50 frames), `platform`, `environment`, `release`, `server_name`, `transaction`, `request.method`, `request.url` (without its query), `os.*`, `browser.name`, `device.model`, `trace_id`, and up to 30 tags as `tag.<name>` |

Sentry's structured logs (`enable_logs`) map one to one: each record becomes a log line with its level, body and attributes.

## What isn't stored

* Transactions, spans, sessions, replays, attachments and profiles are skipped. Every answer names them in `X-Sentry-Rate-Limits`, so the SDK stops sending them. Set the traces sample rate to 0 anyway.
* The user's IP address, email and username, request headers, cookies, query strings, breadcrumbs and `extra` are never stored.

## Tips

::: warning Give Sentry its own key
Sentry SDKs never retry a `429` or `503`. Give Sentry its own deployment and key, so another sender's burst can't rate-limit it, and keep it under 200 requests a second.
:::

::: warning Keep compression at gzip
sentry-python uses brotli when the `brotli` package is installed, and ingest refuses brotli with `415`. In that case pass `_experiments={"transport_compression_algo": "gzip"}` to `sentry_sdk.init`.
:::

## Next steps

* [Core concepts](/guide/concepts#deployments): one deployment per source.
* [Responses](/api/responses#sentry-datadog-loki-and-splunk): Sentry's answers.
