---
title: "Logs"
description: "Structured logging protocol with severity levels, trace context, and batched envelope delivery."
url: https://develop.sentry.dev/sdk/telemetry/logs/
---

# Logs

This document uses key words such as "MUST", "SHOULD", and "MAY" as defined in

<!-- -->

[RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) to indicate requirement levels.

Statusstable

Version`2.0.0`[(changelog)](https://develop.sentry.dev/sdk/telemetry/logs.md#changelog)

## [Overview](https://develop.sentry.dev/sdk/telemetry/logs.md#overview)

Logs allow Sentry to ingest structured log data from SDKs. SDKs send log envelopes containing structured log payloads with severity levels, trace context, and arbitrary attributes. Sentry uses this data to provide searchable, correlated log views alongside errors and traces.

There are two wire protocols: the `log` envelope with the Sentry Log protocol (preferred), and the `otel_log` envelope with the OpenTelemetry Log protocol. All SDKs **MUST** send logs via the `log` envelope and Sentry Log protocol. The `otel_log` format is documented in [Appendix: `otel_log` Format](https://develop.sentry.dev/sdk/telemetry/logs.md#otel_log-envelope-item-payload) for completeness.

Related specs:

* [Envelopes](https://develop.sentry.dev/sdk/foundations/transport/envelopes.md) — transport format
* [Attributes](https://develop.sentry.dev/sdk/foundations/state-management/scopes/attributes.md) — attribute type system
* [Tracing without Performance](https://develop.sentry.dev/sdk/foundations/trace-propagation.md#default-propagation) — required for trace context
* [Trace Origin](https://develop.sentry.dev/sdk/telemetry/traces/trace-origin.md) — origin attribute format

***

## [Concepts](https://develop.sentry.dev/sdk/telemetry/logs.md#concepts)

### [Structured Logging](https://develop.sentry.dev/sdk/telemetry/logs.md#structured-logging)

Logs support parameterized message templates for structured logging. Instead of interpolating values into the message body directly, SDKs send the template and parameters separately. This enables Sentry to group similar log messages and perform efficient searching.

```bash
Template:    "User %s has logged in!"
Parameter 0: "John"
Body:        "User John has logged in!"
```

The SDK sends the interpolated `body`, the `sentry.message.template`, and `sentry.message.parameter.X` attributes.

### [Severity Levels](https://develop.sentry.dev/sdk/telemetry/logs.md#severity-levels)

Logs use a severity model with six levels (lowest to highest): `trace`, `debug`, `info`, `warn`, `error`, `fatal`. These map exactly to [OpenTelemetry's Severity text field](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitytext).

Each level maps to a numeric severity range following the [OpenTelemetry Severity Number](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitynumber) specification:

| SeverityNumber range | Range name | Meaning                                                                                 |
| -------------------- | ---------- | --------------------------------------------------------------------------------------- |
| 1-4                  | Trace      | A fine-grained debugging event. Typically disabled in default configurations.           |
| 5-8                  | Debug      | A debugging event.                                                                      |
| 9-12                 | Info       | An informational event. Indicates that an event happened.                               |
| 13-16                | Warn       | A warning event. Not an error but is likely more important than an informational event. |
| 17-20                | Error      | An error event. Something went wrong.                                                   |
| 21-24                | Fatal      | A fatal error such as application or system crash.                                      |

SDKs **SHOULD** set the lowest severity number for a given severity level (e.g., `warn` uses severity number `13`).

### [Log Buffering](https://develop.sentry.dev/sdk/telemetry/logs.md#log-buffering)

Logs are buffered before sending. SDKs collect logs into a buffer and flush them as a batch in a single `log` envelope item, rather than sending each log individually. This reduces network overhead and aligns with Relay, which is optimized for up to 100 logs per envelope.

***

## [Behavior](https://develop.sentry.dev/sdk/telemetry/logs.md#behavior)

### [Log Processing Pipeline](https://develop.sentry.dev/sdk/telemetry/logs.md#log-processing-pipeline)

Candidatespecified since

<!-- -->

1.3.0

Log processing **MUST** follow this order:

1. Capture log via [Public APIs](https://develop.sentry.dev/sdk/telemetry/logs.md#logger-module) (e.g. `Sentry.logger.info`) or via [SDK integrations](https://develop.sentry.dev/sdk/telemetry/logs.md#sdk-integrations).
2. Check if logging is enabled via `enableLogs`/`enable_logs` — if not, skip remaining steps.
3. Pass the log to Hub/Scope via a generic method (e.g., `captureLog`).
4. Pass the log to the Client via a generic method (e.g., `captureLog`).
5. Process captured log (attach attributes per [Default Attributes](https://develop.sentry.dev/sdk/telemetry/logs.md#default-attributes)).
6. Run `beforeSendLog`/`before_send_log` to filter or modify the log.
7. Add log to buffer/batch processor per [Buffering](https://develop.sentry.dev/sdk/telemetry/logs.md#buffering).
8. At flush time, send array of logs to Sentry via `log` envelope, applying rate limiting per [Data Category and Rate Limiting](https://develop.sentry.dev/sdk/telemetry/logs.md#data-category-and-rate-limiting).

##### Note

An SDK **SHOULD** implement [Tracing without Performance](https://develop.sentry.dev/sdk/foundations/trace-propagation.md#default-propagation) before adding support for logs. This is required to ensure logs are associated with traces and that the correct trace context is sent to Sentry.

### [Default Attributes](https://develop.sentry.dev/sdk/telemetry/logs.md#default-attributes)

Candidatespecified since

<!-- -->

1.0.0

SDKs **MUST** attach the following attributes to every log:

| Attribute            | Since | Description                                                                                                |
| -------------------- | ----- | ---------------------------------------------------------------------------------------------------------- |
| `sentry.environment` | 1.0.0 | The environment set in the SDK, if defined.                                                                |
| `sentry.release`     | 1.0.0 | The release set in the SDK, if defined.                                                                    |
| `sentry.sdk.name`    | 1.0.0 | The name of the SDK that sent the log.                                                                     |
| `sentry.sdk.version` | 1.0.0 | The version of the SDK that sent the log.                                                                  |
| `sentry.replay_id`   | 1.8.0 | The replay ID of the active replay when the log was collected. **MUST NOT** be set if no replay is active. |

For parameterized logs, SDKs **MUST** also attach:

| Attribute                    | Since | Description                                                                                                                         |
| ---------------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `sentry.message.template`    | 1.0.0 | The parameterized template string.                                                                                                  |
| `sentry.message.parameter.X` | 1.0.0 | Parameters to the template. `X` is either the positional index (`0`, `1`, etc.) or the parameter name (`item_id`, `user_id`, etc.). |

If there are no `sentry.message.parameter.X` attributes, SDKs **MUST NOT** attach `sentry.message.template` (since 1.7.0). This reduces duplicate content and simplifies PII processing.

SDKs **SHOULD** minimize default attributes. Logs are charged per byte size. New default attributes **SHOULD** only be added after significant user feedback and discussion with the SDK and ingest teams.

### [SDK Integration Origin](https://develop.sentry.dev/sdk/telemetry/logs.md#sdk-integration-origin)

Candidatespecified since

<!-- -->

1.0.0

If a log is generated by an SDK integration, the SDK **SHOULD** set the `sentry.origin` attribute per the [Trace Origin](https://develop.sentry.dev/sdk/telemetry/traces/trace-origin.md) documentation.

Since 1.9.0, logs follow these rules:

1. **User calls Sentry's Logging API directly:** SDKs **MUST NOT** send `sentry.origin`. This intentionally deviates from the Trace Origin spec to minimize log size.
2. **Captured from a logging library:** Use `auto.log.<name>` format (e.g., `"auto.log.serilog"`).
3. **Auto-emitted from other instrumented systems:** Use `auto.<category>.<integration-name>` format (e.g., `"auto.db.prisma"`).

### [User Attributes](https://develop.sentry.dev/sdk/telemetry/logs.md#user-attributes)

Candidatespecified since

<!-- -->

1.5.0

SDKs **MAY** attach user information as attributes, guarded by `sendDefaultPii` (since 1.14.0):

| Attribute    | Description                                                                                                                            |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `user.id`    | The user ID. Maps to `id` in the [User](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/user.md) payload.          |
| `user.name`  | The username. Maps to `username` in the [User](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/user.md) payload.   |
| `user.email` | The email address. Maps to `email` in the [User](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/user.md) payload. |

### [User Agent Parsing](https://develop.sentry.dev/sdk/telemetry/logs.md#user-agent-parsing)

Candidatespecified since

<!-- -->

1.5.0

By default, Relay parses the user agent attached to an incoming log envelope to extract `browser` and `os` information. SDKs **MAY** attach these attributes if they do not forward a user agent:

| Attribute         | Description                                                                                                                                                             |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `browser.name`    | Display name of the browser. Maps to `name` in [Browser Context](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/contexts.md#browser-context).      |
| `browser.version` | Version string of the browser. Maps to `version` in [Browser Context](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/contexts.md#browser-context). |

### [Backend SDK Attributes](https://develop.sentry.dev/sdk/telemetry/logs.md#backend-sdk-attributes)

Candidatespecified since

<!-- -->

1.0.0

Backend SDKs (Node.js, Python, PHP, etc.) **SHOULD** attach:

| Attribute        | Description                                                                                                                                                               |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `server.address` | The server address. Equivalent to [`server_name`](https://develop.sentry.dev/sdk/foundations/transport/event-payloads.md#optional-attributes) on errors and transactions. |

### [Mobile, Desktop, and Native SDK Attributes](https://develop.sentry.dev/sdk/telemetry/logs.md#mobile-desktop-and-native-sdk-attributes)

Candidatespecified since

<!-- -->

1.5.0

Mobile, desktop, and native SDKs (Android, Apple, Electron, etc.) **SHOULD** attach:

| Attribute       | Description                                                                                                                                          |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `os.name`       | OS name. Maps to `name` in [OS Context](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/contexts.md#os-context).                 |
| `os.version`    | OS version. Maps to `version` in [OS Context](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/contexts.md#os-context).           |
| `device.brand`  | Device brand. Maps to `brand` in [Device Context](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/contexts.md#device-context).   |
| `device.model`  | Device model. Maps to `model` in [Device Context](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/contexts.md#device-context).   |
| `device.family` | Device family. Maps to `family` in [Device Context](https://develop.sentry.dev/sdk/foundations/transport/event-payloads/contexts.md#device-context). |

### [Buffering](https://develop.sentry.dev/sdk/telemetry/logs.md#buffering)

Candidatespecified since

<!-- -->

1.0.0

SDKs **MUST** buffer logs before sending. A simple initial strategy is flushing when the buffer exceeds 100 items or 5 seconds have passed. The buffer **SHOULD** forward logs to the transport in the scenarios outlined in the [telemetry buffer data forwarding scenarios](https://develop.sentry.dev/sdk/foundations/processing/telemetry-processor.md#data-forwarding-scenarios).

SDKs **MUST NOT** send more than 100 logs per envelope (since 1.15.0). Relay is optimized for this limit.

SDKs **MUST** enforce a hard limit of 1000 queued log events to prevent out-of-memory issues (since 1.12.0). Logs added beyond this limit are dropped. SDKs **MAY** use a lower limit but **MUST NOT** exceed 1000.

SDKs **MUST NOT** release logging capabilities to users without a buffering implementation.

### [Data Category and Rate Limiting](https://develop.sentry.dev/sdk/telemetry/logs.md#data-category-and-rate-limiting)

Candidatespecified since

<!-- -->

1.0.0

Logs use the `log_item` data category for rate limiting in Relay. Both `log` and `otel_log` envelopes are covered by this data category. SDKs **MUST** implement this data category. Rate limiting applies as usual with no special behavior for logs.

SDKs **MUST** track client outcomes for this data category to report how often logs are dropped.

### [SDK Integrations](https://develop.sentry.dev/sdk/telemetry/logs.md#sdk-integrations)

Candidatespecified since

<!-- -->

1.0.0

SDKs **SHOULD** provide integrations that capture logs from platform logging libraries (e.g., JavaScript's `console`, Python's `logging`, Java's `Log4j`) when `enableLogs`/`enable_logs` is set to `true`.

SDKs **MAY** introduce additional options beyond `enableLogs`/`enable_logs` to gate integration-specific functionality (e.g., controlling log appenders added via external config).

### [Auto-Emitted Logs](https://develop.sentry.dev/sdk/telemetry/logs.md#auto-emitted-logs)

Candidatespecified since

<!-- -->

2.0.0

Logs emitted via the [public API](https://develop.sentry.dev/sdk/telemetry/logs.md#logger-module) are opt-out. The `enableLogs`/`enable_logs` option **MUST** act as a general kill switch for all logs sent to Sentry. When set to `false`, no logs **MUST** be sent, regardless of whether they originate from the public API, auto-emitting integrations, or third-party bindings.

However, logs that are **automatically emitted by integrations or libraries** without an explicit user call follow different rules because they can generate unexpected volume and cost.

**Integrations that auto-emit logs** - An SDK integration that automatically captures logs (e.g., forwarding `console.log` calls, capturing framework-level diagnostic output) **MUST** be opt-in. The integration **MUST NOT** emit any logs unless the user explicitly enables it. The opt-in mechanism **MAY** be a dedicated integration-level option or requiring the user to explicitly add the integration.

**Third-party log bindings** - An SDK feature that binds to an external library's logging API and mirrors those logs as Sentry logs in the background (e.g., syncing from Python's `logging` module or a framework's built-in logger) **MUST** also be opt-in. Users **MUST** explicitly enable the binding before any logs are forwarded to Sentry.

These rules exist because auto-emitted logs can cause a high volume of telemetry that directly impacts a user's quota. Unlike errors, where users have prior intuition about volume, silently emitting logs on their behalf could lead to unexpected costs. Requiring opt-in ensures users remain in control of their log volume.

### [Tracing Association](https://develop.sentry.dev/sdk/telemetry/logs.md#tracing-association)

Candidatespecified since

<!-- -->

1.0.0

Logs **SHOULD** be associated with traces. If a log is recorded during an active span, SDKs **SHOULD** set the `span_id` property to the active span's ID.

### [Replay Association](https://develop.sentry.dev/sdk/telemetry/logs.md#replay-association)

Candidatespecified since

<!-- -->

1.8.0

Logs **SHOULD** be associated with replays. If a log is recorded during an active replay, SDKs **SHOULD** set the `sentry.replay_id` attribute to the active replay's ID.

### [Log Ordering](https://develop.sentry.dev/sdk/telemetry/logs.md#log-ordering)

Some runtimes (notably Cloudflare Workers) freeze timer APIs (`Date.now()`, `performance.now()`) during synchronous execution, causing multiple logs to share identical timestamps. SDKs that target runtimes where timestamps may be frozen or lack sub-millisecond precision **MUST** attach a `sentry.timestamp.sequence` integer attribute to every log. SDKs that only target runtimes with reliable sub-millisecond timestamps **MAY** omit it.

Candidatespecified since

<!-- -->

1.16.0

When sent, the sequence integer **MUST**:

* Start at `0` when the SDK initializes.

* Increment by `1` for each log that is captured.

* Reset to `0` when:

  * The SDK is re-initialized.
  * The current log's integer millisecond differs from the previous log's integer millisecond (i.e., `floor(timestamp_seconds * 1000)` changes).

The sequence provides deterministic ordering within a single SDK instance. It does not guarantee ordering across independent processes or workers, which have separate counters. The reset behavior ensures the sequence only increments for consecutive logs that share the same timestamp.

### [Debug Mode](https://develop.sentry.dev/sdk/telemetry/logs.md#debug-mode)

### [Debug Mode](https://develop.sentry.dev/sdk/telemetry/logs.md#debug-mode-1)

Candidatespecified since

<!-- -->

1.0.0

If `debug` is set to `true` in SDK init, calls to the Sentry logger API **SHOULD** also print to the console with the appropriate log level. This aids debugging of logging setups.

### [Client Reports](https://develop.sentry.dev/sdk/telemetry/logs.md#client-reports)

Candidatespecified since

<!-- -->

1.13.0

SDKs **MUST** report count (`log_item`) and size in bytes (`log_byte`) of discarded log messages. An approximation of log size is sufficient (e.g., by counting as if serialized).

***

## [Wire Format](https://develop.sentry.dev/sdk/telemetry/logs.md#wire-format)

### [`log` Envelope Item](https://develop.sentry.dev/sdk/telemetry/logs.md#log-envelope-item)

Candidatespecified since

<!-- -->

1.1.0

The `log` envelope item payload is a JSON object that **MUST** include an `items` array of log entries, allowing multiple logs per envelope item. The payload **MAY** also include top-level `version` and `ingest_settings` fields as specified in the next section.

An envelope **MUST** contain at most one `log` envelope item — all log entries for a flush are batched into a single item's `items` array. Logs from different traces **MAY** be mixed into the same `log` item, but if they are, the envelope **MUST NOT** include a DSC (dynamic sampling context) header.

**Item Headers:**

| Field          | Type    | Required     | Description                                                                      |
| -------------- | ------- | ------------ | -------------------------------------------------------------------------------- |
| `type`         | String  | **REQUIRED** | **MUST** be `"log"`.                                                             |
| `item_count`   | Integer | **REQUIRED** | The number of log entries in the `items` array. **MUST** match the actual count. |
| `content_type` | String  | **REQUIRED** | **MUST** be `"application/vnd.sentry.items.log+json"`.                           |

```json
{
  "type": "log",
  "item_count": 5,
  "content_type": "application/vnd.sentry.items.log+json"
}
{
  "version": 2,
  "ingest_settings": {
    "infer_ip": "auto",
    "infer_useragent": "auto"
  },
  "items": [{..log..}, {..log..}, {..log..}, {..log..}, {..log..}]
}
```

### [`version` and `ingest_settings` properties](https://develop.sentry.dev/sdk/telemetry/logs.md#version-and-ingest_settings-properties)

Candidatespecified since

<!-- -->

1.17.0

The `log` envelope item `ingest_settings` property is an optional JSON object that contains ingestion settings for Relay, for example, to infer certain data from the incoming request.

| Field             | Type   | Required     | Description                                                                                        |
| ----------------- | ------ | ------------ | -------------------------------------------------------------------------------------------------- |
| `infer_ip`        | String | **OPTIONAL** | The setting to infer the IP address from the incoming request. One of `auto` or `never` (default). |
| `infer_useragent` | String | **OPTIONAL** | The setting to infer the user agent from the incoming request. One of `auto` or `never` (default). |

SDKs like Browser or React Native **MAY** set these to `"auto"` to instruct Relay to infer the IP address or user agent from the incoming request and put it onto the log as an attribute.

For ingestion settings to take effect, the SDK **MUST** also set the `version` property to `2` (`number`) or higher. If `version` is omitted, Relay treats the payload as version `1` and doesn't apply `ingest_settings`.

### [`log` Envelope Item Payload](https://develop.sentry.dev/sdk/telemetry/logs.md#log-envelope-item-payload)

Candidatespecified since

<!-- -->

1.0.0

Each log in the `items` array is a JSON object:

```json
{
  "timestamp": 1544719860.0,
  "trace_id": "5b8efff798038103d269b633813fc60c",
  "span_id": "b0e6f15b45c36b12",
  "level": "info",
  "body": "User John has logged in!",
  "severity_number": 9,
  "attributes": {
    "sentry.message.template": {
      "value": "User %s has logged in!",
      "type": "string"
    },
    "sentry.message.parameter.0": {
      "value": "John",
      "type": "string"
    }
  }
}
```

| Field             | Type    | Required     | Since  | Description                                                                                                                                                                |
| ----------------- | ------- | ------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `timestamp`       | Number  | **REQUIRED** | 1.0.0  | Timestamp of the log in seconds since the Unix epoch.                                                                                                                      |
| `trace_id`        | String  | **REQUIRED** | 1.0.0  | Trace ID as 16 random bytes encoded as a hex string (32 characters). **MUST** be grabbed from the current propagation context.                                             |
| `level`           | String  | **REQUIRED** | 1.0.0  | Severity level. One of `trace`, `debug`, `info`, `warn`, `error`, `fatal`.                                                                                                 |
| `body`            | String  | **REQUIRED** | 1.0.0  | The log body/message.                                                                                                                                                      |
| `span_id`         | String  | **OPTIONAL** | 1.11.0 | Span ID of the active span when the log was collected, as 8 random bytes encoded as a hex string (16 characters).                                                          |
| `severity_number` | Integer | **OPTIONAL** | 1.0.0  | Severity number per [Severity Levels](https://develop.sentry.dev/sdk/telemetry/logs.md#severity-levels). Inferred from `level` unless explicitly set.                      |
| `attributes`      | Object  | **OPTIONAL** | 1.0.0  | Key-value pairs of arbitrary data. Values **MUST** declare their type. See [Attributes](https://develop.sentry.dev/sdk/foundations/state-management/scopes/attributes.md). |

### [`otel_log` Envelope Item Payload](https://develop.sentry.dev/sdk/telemetry/logs.md#otel_log-envelope-item-payload)

Candidatespecified since

<!-- -->

1.0.0

Click to expand/collapse details about the \`otel\_log\` envelope item payload.

The `otel_log` envelope item payload is a JSON object implementing the [OpenTelemetry Log Data Model](https://opentelemetry.io/docs/specs/otel/logs/data-model/). Multiple `otel_log` items **MAY** be sent per envelope.

```json
{
  "severity_text": "info",
  "body": {
    "string_value": "User John has logged in!"
  },
  "attributes": [
    {
      "key": "sentry.message.template",
      "value": { "string_value": "User %s has logged in!" }
    },
    {
      "key": "sentry.message.parameters.0",
      "value": { "string_value": "John" }
    }
  ],
  "time_unix_nano": "1741191250694000000",
  "trace_id": "edec519707974fc8bfccb5a017e17394",
  "severity_number": 9
}
```

| Field             | Type           | Required     | Description                                                                                                                                                                           |
| ----------------- | -------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `severity_text`   | String         | **REQUIRED** | Severity level. One of `trace`, `debug`, `info`, `warn`, `error`, `fatal`.                                                                                                            |
| `body`            | Object         | **REQUIRED** | The log body. Contains `string_value` with the message text.                                                                                                                          |
| `trace_id`        | String         | **OPTIONAL** | Trace ID for linking logs to traces and errors. Heavily recommended.                                                                                                                  |
| `severity_number` | Integer        | **OPTIONAL** | Severity number per [Severity Levels](https://develop.sentry.dev/sdk/telemetry/logs.md#severity-levels).                                                                              |
| `attributes`      | Array\<Object> | **OPTIONAL** | Key-value pairs. Each entry has `key` (string) and `value` (object with typed value). Supported value fields: `stringValue`, `intValue` (string-encoded), `boolValue`, `doubleValue`. |
| `time_unix_nano`  | String         | **OPTIONAL** | Creation time in Unix nanoseconds. SDKs **SHOULD** set this to the current time if not provided.                                                                                      |

***

## [Public API](https://develop.sentry.dev/sdk/telemetry/logs.md#public-api)

### [Initialization Options](https://develop.sentry.dev/sdk/telemetry/logs.md#initialization-options)

Candidatespecified since

<!-- -->

1.0.0

SDKs **MUST** expose the following configuration options:

| Option                              | Type     | Default | Since | Description                                                                                        |
| ----------------------------------- | -------- | ------- | ----- | -------------------------------------------------------------------------------------------------- |
| `enableLogs` / `enable_logs`        | Boolean  | `true`  | 1.0.0 | Controls whether log envelopes are generated and sent. If `false`, the SDK **MUST NOT** send logs. |
| `beforeSendLog` / `before_send_log` | Function | —       | 1.0.0 | **OPTIONAL** callback receiving a log object. Returns a modified log or `null` to drop it.         |

The default for `enableLogs`/`enable_logs` was changed from `false` to `true` in version 2.0.0. The previous default required users to explicitly opt in before they could use the logging primitives. By defaulting to `true`, adding a `Sentry.logger.*` statement is itself the opt-in. Users can start logging without additional configuration. This aligns the behavior with [`enableMetrics`/`enable_metrics`](https://develop.sentry.dev/sdk/telemetry/metrics.md#initialization-options), which also defaults to `true`.

While logs functionality is in an experimental state, SDKs **SHOULD** put these options in an experimental namespace to avoid breaking changes:

```js
Sentry.init({
  // stable
  enableLogs: true,

  // experimental
  _experiments: { enableLogs: true },
});
```

### [Logger Module](https://develop.sentry.dev/sdk/telemetry/logs.md#logger-module)

Candidatespecified since

<!-- -->

1.0.0

SDKs **MUST** expose logging methods in a `logger` module or namespace, with one method per [severity level](https://develop.sentry.dev/sdk/telemetry/logs.md#severity-levels):

* `Sentry.logger.trace`
* `Sentry.logger.debug`
* `Sentry.logger.info`
* `Sentry.logger.warn`
* `Sentry.logger.error`
* `Sentry.logger.fatal`

These methods accept a string template and parameters for structured logging. They **MAY** also accept arbitrary attributes.

The Hub/Scope and Client **MUST** exclusively provide a generic logging method (e.g., `captureLog`). They **MUST NOT** replicate the static `Sentry.logger.X` API methods to avoid increasing our API surface. Users utilizing multiple Hub/Scope or Clients will need to rely on the generic method for logging.

### [Threading and Concurrency](https://develop.sentry.dev/sdk/telemetry/logs.md#threading-and-concurrency)

Candidatespecified since

<!-- -->

1.0.0

The `Sentry.logger.X` methods are fire-and-forget (no return value). SDKs **MAY** run these methods on a separate thread or queue them for later processing, including evaluating the string template and running internal hooks like `beforeSendLog`.

SDKs **MUST** ensure logs are sent in the order they are received.

##### Note

Putting everything on a background thread risks losing logs that occur directly before a crash. Mobile SDKs will need a more robust mechanism. The individual SDK will need to determine the best approach for their platform.

***

## [Examples](https://develop.sentry.dev/sdk/telemetry/logs.md#examples)

### [SDK API Usage](https://develop.sentry.dev/sdk/telemetry/logs.md#sdk-api-usage)

These examples are illustrative, not normative. SDK authors **SHOULD** ensure the API best fits their platform.

```jsx
// Browser - tagged template literals
Sentry.logger.info(
  Sentry.logger.fmt`Adding item ${itemId} for user ${userId}`,
);

// Server-side - printf-like syntax
Sentry.logger.info("Adding item %s for user %s", [itemId, userId], {
  extra: 123,
});
```

### [Full `log` Envelope](https://develop.sentry.dev/sdk/telemetry/logs.md#full-log-envelope)

A complete `log` envelope with six log entries at different severity levels:

```json
{ "sdk": { "name": "sentry.javascript.browser", "version": "9.15.0" } }
{
  "type": "log",
  "item_count": 6,
  "content_type": "application/vnd.sentry.items.log+json"
}
{
  "items": [
    {
      "timestamp": 1746456149.0191,
      "level": "trace",
      "body": "Modal animation performance: openTime=120ms, closeTime=85ms, fps=60",
      "trace_id": "624f66e93a04469f9992c7e9f1485056",
      "severity_number": 1,
      "attributes": {
        "modalId": { "value": "product_details", "type": "string" },
        "animationType": { "value": "slide-up", "type": "string" },
        "devicePixelRatio": { "value": 2, "type": "integer" },
        "browser": { "value": "Chrome", "type": "string" },
        "memoryUsage": { "value": "45MB", "type": "string" },
        "sentry.sdk.name": {
          "value": "sentry.javascript.browser",
          "type": "string"
        },
        "sentry.sdk.version": { "value": "9.15.0", "type": "string" },
        "sentry.message.template": {
          "value": "Modal animation performance: openTime=%sms, closeTime=%sms, fps=%s",
          "type": "string"
        },
        "sentry.message.parameter.0": { "value": 120, "type": "integer" },
        "sentry.message.parameter.1": { "value": 85, "type": "integer" },
        "sentry.message.parameter.2": { "value": 60, "type": "integer" },
        "sentry.timestamp.sequence": { "value": 0, "type": "integer" }
      }
    },
    {
      "timestamp": 1746456149.0191998,
      "level": "debug",
      "body": "Component ProductCard rendered 3 times",
      "trace_id": "624f66e93a04469f9992c7e9f1485056",
      "severity_number": 5,
      "attributes": {
        "props": { "value": "{\"productId\":\"prod_123\"}", "type": "string" },
        "renderTime": { "value": 45, "type": "integer" },
        "sentry.sdk.name": {
          "value": "sentry.javascript.browser",
          "type": "string"
        },
        "sentry.sdk.version": { "value": "9.15.0", "type": "string" },
        "sentry.message.template": {
          "value": "Component %s rendered %s times",
          "type": "string"
        },
        "sentry.message.parameter.0": {
          "value": "ProductCard",
          "type": "string"
        },
        "sentry.message.parameter.1": { "value": 3, "type": "integer" },
        "sentry.timestamp.sequence": { "value": 1, "type": "integer" }
      }
    },
    {
      "timestamp": 1746456149.0191998,
      "level": "info",
      "body": "Form checkout_form submitted successfully with 8 fields",
      "trace_id": "624f66e93a04469f9992c7e9f1485056",
      "severity_number": 9,
      "attributes": {
        "step": { "value": "payment_details", "type": "string" },
        "timeSpent": { "value": 120, "type": "integer" },
        "sentry.sdk.name": {
          "value": "sentry.javascript.browser",
          "type": "string"
        },
        "sentry.sdk.version": { "value": "9.15.0", "type": "string" },
        "sentry.message.template": {
          "value": "Form %s submitted successfully with %s fields",
          "type": "string"
        },
        "sentry.message.parameter.0": {
          "value": "checkout_form",
          "type": "string"
        },
        "sentry.message.parameter.1": { "value": 8, "type": "integer" },
        "sentry.timestamp.sequence": { "value": 2, "type": "integer" }
      }
    },
    {
      "timestamp": 1746456149.0192997,
      "level": "warn",
      "body": "API endpoint /api/products response time 2500ms exceeds threshold of 1000ms",
      "trace_id": "624f66e93a04469f9992c7e9f1485056",
      "severity_number": 13,
      "attributes": {
        "userAgent": { "value": "Mozilla/5.0...", "type": "string" },
        "connectionType": { "value": "4g", "type": "string" },
        "sentry.sdk.name": {
          "value": "sentry.javascript.browser",
          "type": "string"
        },
        "sentry.sdk.version": { "value": "9.15.0", "type": "string" },
        "sentry.message.template": {
          "value": "API endpoint %s response time %sms exceeds threshold of %sms",
          "type": "string"
        },
        "sentry.message.parameter.0": {
          "value": "/api/products",
          "type": "string"
        },
        "sentry.message.parameter.1": { "value": 2500, "type": "integer" },
        "sentry.message.parameter.2": { "value": 1000, "type": "integer" },
        "sentry.timestamp.sequence": { "value": 3, "type": "integer" }
      }
    },
    {
      "timestamp": 1746456149.0192997,
      "level": "error",
      "body": "Failed to load images for products prod_123, prod_456",
      "trace_id": "624f66e93a04469f9992c7e9f1485056",
      "severity_number": 17,
      "attributes": {
        "error": { "value": "NetworkError", "type": "string" },
        "statusCode": { "value": 404, "type": "integer" },
        "retryAttempts": { "value": 2, "type": "integer" },
        "browser": { "value": "Chrome", "type": "string" },
        "version": { "value": "120.0", "type": "string" },
        "sentry.sdk.name": {
          "value": "sentry.javascript.browser",
          "type": "string"
        },
        "sentry.sdk.version": { "value": "9.15.0", "type": "string" },
        "sentry.message.template": {
          "value": "Failed to load images for products %s",
          "type": "string"
        },
        "sentry.message.parameter.0": {
          "value": "prod_123, prod_456",
          "type": "string"
        },
        "sentry.timestamp.sequence": { "value": 4, "type": "integer" }
      }
    },
    {
      "timestamp": 1746456149.0192997,
      "level": "fatal",
      "body": "State corruption detected in ShoppingCart component during UPDATE_CART action",
      "trace_id": "624f66e93a04469f9992c7e9f1485056",
      "severity_number": 21,
      "attributes": {
        "error": { "value": "ReduxStateError", "type": "string" },
        "previousState": { "value": "valid", "type": "string" },
        "currentState": { "value": "invalid", "type": "string" },
        "sentry.sdk.name": {
          "value": "sentry.javascript.browser",
          "type": "string"
        },
        "sentry.sdk.version": { "value": "9.15.0", "type": "string" },
        "sentry.message.template": {
          "value": "State corruption detected in %s component during %s action",
          "type": "string"
        },
        "sentry.message.parameter.0": {
          "value": "ShoppingCart",
          "type": "string"
        },
        "sentry.message.parameter.1": {
          "value": "UPDATE_CART",
          "type": "string"
        },
        "sentry.timestamp.sequence": { "value": 5, "type": "integer" }
      }
    }
  ]
}
```

***

## [Changelog](https://develop.sentry.dev/sdk/telemetry/logs.md#changelog)

| Version  | Date       | Summary                                                                                                                  |
| -------- | ---------- | ------------------------------------------------------------------------------------------------------------------------ |
| `2.0.0`  | 2026-04-09 | Default enableLogs to true, add auto-emitted logs opt-in requirements for integrations                                   |
| `1.17.0` | 2026-03-05 | Added \`ingest\_settings\` and \`version\` to log envelope item                                                          |
| `1.16.0` | 2026-03-04 | Add sentry.timestamp.sequence attribute for deterministic log ordering                                                   |
| `1.15.0` | 2026-02-03 | Clarified 100 logs per envelope hard limit, SDKs MAY use lower buffer limit                                              |
| `1.14.0` | 2025-12-16 | User attributes now optional, guarded by sendDefaultPii                                                                  |
| `1.13.0` | 2025-11-18 | Added client reports requirement (log\_item count, log\_byte size)                                                       |
| `1.12.0` | 2025-11-10 | Added buffer hard limit of 1000 queued log events                                                                        |
| `1.11.0` | 2025-10-30 | Added span\_id as top-level payload field, replaced sentry.trace.parent\_span\_id attribute                              |
| `1.10.0` | 2025-10-22 | Hub/Scope MUST offer same logger methods as static API, Client SHOULD offer generic captureLog                           |
| `1.9.0`  | 2025-10-09 | Consolidated sentry.origin rules — no origin for manual calls, auto.log.\* for libraries, auto.\*.\* for instrumentation |
| `1.8.0`  | 2025-09-10 | Added sentry.replay\_id as default attribute and replay association behavior                                             |
| `1.7.0`  | 2025-08-28 | Added message template constraint — MUST NOT send sentry.message.template without parameters                             |
| `1.6.0`  | 2025-06-10 | User attributes no longer gated behind sendDefaultPii                                                                    |
| `1.5.0`  | 2025-05-27 | Added platform-specific default attributes for browser, backend, mobile/desktop/native                                   |
| `1.4.0`  | 2025-05-08 | Added Tracing without Performance as prerequisite for logs                                                               |
| `1.3.0`  | 2025-05-07 | Added structured log processing pipeline, removed logsSampleRate init option                                             |
| `1.2.0`  | 2025-05-01 | Refined buffering requirements (100 items or 5 seconds flush)                                                            |
| `1.1.0`  | 2025-04-24 | Documented log envelope item structure (items array wrapper)                                                             |
| `1.0.0`  | 2025-04-22 | Initial spec — log protocol, severity model, logger API, init options, otel\_log format                                  |
