---
title: "Logs"
description: "Structured logs allow you to send, view and query logs sent from your applications within Sentry."
url: https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs/
---

# Set Up Logs | Sentry for Kotlin Multiplatform

Stack traces tell you *what* broke. Logs tell you *why*. When an error fires, you get a snapshot of the failure, but the context leading up to it is often missing. Logs capture the journey — what the data looked like, which code paths executed, and what state the system was in.

Sentry Logs are **high-cardinality** — you can pass any attributes you want and search or filter by them later. No need to decide upfront which fields are important. Just log what might be useful and query it when you need it.

## [Requirements](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#requirements)

Logs for Kotlin Multiplatform are supported in Sentry Kotlin Multiplatform SDK version `0.24.0` and above.

Logs are supported on all platforms listed in [Supported Platforms](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/features.md#supported-platforms).

## [Setup](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#setup)

Enable logging by adding `logs.enabled = true` to your Sentry configuration.

Using native platform options? See [Using Native Platform Options](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#using-native-platform-options) below.

`SentrySetup.kt`

```kotlin
import io.sentry.kotlin.multiplatform.Sentry

fun initializeSentry() {
  Sentry.init {
    it.dsn = "___PUBLIC_DSN___"
    it.logs.enabled = true
  }
}
```

## [Send Logs](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#send-logs)

Use `Sentry.logger` to send logs at different levels. A log message is required for Sentry to send the log.

| Level   | When to Use                      |
| ------- | -------------------------------- |
| `trace` | Fine-grained debugging           |
| `debug` | Development diagnostics          |
| `info`  | Normal operations, milestones    |
| `warn`  | Potential issues, degraded state |
| `error` | Failures that need attention     |
| `fatal` | Critical failures, system down   |

```kotlin
import io.sentry.kotlin.multiplatform.Sentry

Sentry.logger.trace("Entering function") { this["fn"] = "processOrder" }
Sentry.logger.debug("Cache lookup") { this["key"] = "user:123" }
Sentry.logger.info("Order created") { this["orderId"] = "order_456" }
Sentry.logger.warn("Rate limit approaching") { this["current"] = 95; this["max"] = 100 }
Sentry.logger.error("Payment failed") { this["reason"] = "card_declined" }
Sentry.logger.fatal("Database unavailable") { this["host"] = "primary" }
```

## [Add Context](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#add-context)

Pass structured data as attributes — these become searchable columns in Sentry.

Use the trailing lambda to attach attributes, or the full DSL with `message()` and `attributes {}` blocks for more complex logs.

You can use `%s` placeholders to create parameterized log messages. These will be automatically extracted as attributes.

```kotlin
import io.sentry.kotlin.multiplatform.Sentry

// Trailing lambda
Sentry.logger.info("User purchased product %s", productName) {
    this["userId"] = user.id
    this["referrer"] = "google"
}

// Full DSL
Sentry.logger.info {
    message("User purchased product %s", productName)
    attributes {
        this["userId"] = user.id
        this["referrer"] = "google"
    }
}
```

## [Filter Logs](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#filter-logs)

Use `logs.beforeSend` to filter or modify logs before they're sent. Return `null` to drop a log.

`SentrySetup.kt`

```kotlin
import io.sentry.kotlin.multiplatform.Sentry
import io.sentry.kotlin.multiplatform.log.SentryLogLevel

fun initializeSentry() {
  Sentry.init {
    it.dsn = "___PUBLIC_DSN___"
    it.logs.enabled = true
    it.logs.beforeSend = { log ->
      if (log.level == SentryLogLevel.DEBUG) {
        null
      } else {
        if (log.attributes.contains("password")) {
          log.attributes.remove("password")
        }
        log
      }
    }
  }
}
```

The `beforeSend` function receives a log object, and should return the log object if you want it to be sent to Sentry, or `null` if you want to discard it.

## [Best Practices](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#best-practices)

### [Wide Events Over Scattered Logs](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#wide-events-over-scattered-logs)

Instead of many small logs that are hard to correlate, emit one comprehensive log per operation with all relevant context.

This makes debugging dramatically faster — one query returns everything about a specific order, user, or request.

```kotlin
import io.sentry.kotlin.multiplatform.Sentry

// ❌ Scattered thin logs
Sentry.logger.info("Starting checkout")
Sentry.logger.info("Validating cart")
Sentry.logger.info("Processing payment")
Sentry.logger.info("Checkout complete")

// ✅ One wide event with full context
Sentry.logger.info("Checkout completed") {
    this["orderId"] = order.id
    this["userId"] = user.id
    this["cartValue"] = cart.total
    this["itemCount"] = cart.items.size
    this["paymentMethod"] = "stripe"
    this["duration"] = System.currentTimeMillis() - startTime
}
```

### [Include Business Context](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#include-business-context)

Add attributes that help you prioritize and debug:

* **User context** — tier, account age, lifetime value
* **Transaction data** — order value, item count
* **Feature state** — active feature flags
* **Request metadata** — endpoint, method, duration

This lets you filter logs by high-value customers or specific features.

```kotlin
import io.sentry.kotlin.multiplatform.Sentry

Sentry.logger.info("API request completed") {
    // User context
    this["userId"] = user.id
    this["userTier"] = user.plan // "free" | "pro" | "enterprise"

    // Request data
    this["endpoint"] = "/api/orders"
    this["method"] = "POST"
    this["duration"] = 234

    // Business context
    this["orderValue"] = 149.99
}
```

## [Default Attributes](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#default-attributes)

Sentry automatically attaches these attributes to every log:

| Attribute                    | Description                                                                                | Context                |
| ---------------------------- | ------------------------------------------------------------------------------------------ | ---------------------- |
| `sentry.environment`         | Environment from SDK config                                                                | Always                 |
| `sentry.release`             | Release version from SDK config                                                            | Always                 |
| `sentry.sdk.name`            | SDK name                                                                                   | Always                 |
| `sentry.sdk.version`         | SDK version                                                                                | Always                 |
| `sentry.message.template`    | The original parameterized template string                                                 | If parameterized       |
| `sentry.message.parameter.X` | The parameters used to fill the template, where X is the positional index (`0`, `1`, etc.) | If parameterized       |
| `sentry.origin`              | Origin of the log                                                                          | If from an integration |
| `sentry.replay_id`           | Session replay ID                                                                          | If available           |
| `os.name`                    | Operating system name                                                                      | If available           |
| `os.version`                 | Operating system version                                                                   | If available           |
| `device.brand`               | Device manufacturer                                                                        | If available           |
| `device.model`               | Device model name                                                                          | If available           |
| `device.family`              | Device family                                                                              | If available           |

### [Message Template Example](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#message-template-example)

```kotlin
Sentry.logger.error("User %s failed to purchase %s", userId, productName)
```

This sets `sentry.message.template` to `"User %s failed to purchase %s"`, `sentry.message.parameter.0` to the value of `userId`, and `sentry.message.parameter.1` to the value of `productName`.

## [Using Native Platform Options](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#using-native-platform-options)

If you initialize the SDK with [Native Platform Options](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/initialization-strategies.md#native-platform-options), enable logs through the native SDK's configuration:

`SentrySetup.android.kt`

```kotlin
import io.sentry.kotlin.multiplatform.PlatformOptionsConfiguration

actual fun platformOptionsConfiguration(): PlatformOptionsConfiguration = {
    it.dsn = "___PUBLIC_DSN___"
    // Enable logs to be sent to Sentry
    it.logs.isEnabled = true
}
```

After initializing the SDK with the native platform options, you can use the common `Sentry.logger` API to send logs to Sentry.

## [Troubleshooting](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#troubleshooting)

### [Missing Logs for Crashes](https://docs.sentry.io/platforms/kotlin/guides/kotlin-multiplatform/logs.md#missing-logs-for-crashes)

Logs can get lost in certain crash scenarios, if the SDK can not send the logs before the app terminates. We are currently working on improving ([#1](https://github.com/getsentry/sentry-java/issues/4690), [#2](https://github.com/getsentry/sentry-cocoa/issues/5660)) this to ensure that all logs are sent, at the latest on the next app restart.
