---
title: "Metrics"
description: "Metrics allow you to send, view and query counters, gauges, and distributions from your Sentry-configured apps to track application health and drill down into related traces, logs, and errors."
url: https://docs.sentry.io/platforms/apple/guides/watchos/metrics/
---

# Set Up Metrics | Sentry for watchOS

With Sentry Metrics, you can send counters, gauges, and distributions from your applications to Sentry. Once in Sentry, these metrics can be viewed alongside relevant errors, traces, and logs, and searched using their individual attributes.

This feature is currently in open beta. Please reach out on [GitHub](https://github.com/getsentry/sentry/discussions/102275) if you have feedback or questions. Features in beta are still in-progress and may have bugs. We recognize the irony.

## [Requirements](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#requirements)

Metrics are supported in Sentry Cocoa SDK version `9.2.0` and above.

## [Usage](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#usage)

Once the SDK is initialized, you can send metrics using the `SentrySDK.metrics` APIs. Metrics are enabled by default.

The `metrics` namespace exposes three methods that you can use to capture different types of metric information: `count`, `gauge` and `distribution`.

Objective-C support for metrics is not currently available. If you need Objective-C support, please [open an issue](https://github.com/getsentry/sentry-cocoa/issues) to show demand for this feature.

### [Counter](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#counter)

Counters track discrete occurrence counts. Use this to increment or set a count associated with a metric key, such as the number of events, requests, or errors.

**Key characteristics:**

* Values are typically non-negative integers
* Use descriptive, lowercase, dot-delimited names (e.g., `"network.request.count"`)

```swift
import Sentry

// Simple counter
SentrySDK.metrics.count(key: "button_click", value: 1)

// Counter with unit and attributes
SentrySDK.metrics.count(
    key: "network.request.count",
    value: 1,
    unit: .generic("request"),
    attributes: ["endpoint": "/api/users", "method": "POST"]
)
```

### [Gauge](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#gauge)

Gauges track values that can go up and down over time, representing a current state rather than an incrementing counter. Use this for metrics like current memory usage, queue depth, or active connections.

**Key characteristics:**

* Values can increase or decrease
* Represents the state at the time of recording
* Supports aggregates like min, max, avg, sum, and count
* Cannot be used to calculate percentiles (use distributions for that)

```swift
import Sentry

// Simple gauge
SentrySDK.metrics.gauge(key: "queue_depth", value: 42.0)

// Gauge with unit
SentrySDK.metrics.gauge(
    key: "memory.usage",
    value: 1024.0,
    unit: .megabyte
)
```

### [Distribution](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#distribution)

Distributions track the distribution of a value over time, allowing you to analyze statistical properties like mean, median, and percentiles. Use this for measurable quantities like response times or request durations.

**Key characteristics:**

* Enables percentile calculations (p50, p90, p99, etc.)
* Best for analyzing statistical properties of measurements
* Use for values where you need to understand distribution, not just aggregates

```swift
import Sentry

// Simple distribution
SentrySDK.metrics.distribution(key: "response_time", value: 187.5)

// Distribution with unit and attributes
SentrySDK.metrics.distribution(
    key: "http.request.duration",
    value: 187.5,
    unit: .millisecond,
    attributes: ["endpoint": "/api/data", "cached": false]
)
```

### [Adding Attributes](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#adding-attributes)

You can also pass additional attributes to any of the metric methods via the `attributes` parameter. Attributes allow you to filter and group metrics.

The SDK uses the `SentryAttributeValue` protocol to provide **compile-time type safety** for attribute values. This means you can pass native Swift types directly without wrapping them, and the compiler will ensure only valid types are accepted.

**Supported attribute types:**

* **Scalar types**: `String`, `Bool`, `Int`, `Double`, `Float`
* **Array types**: `[String]`, `[Bool]`, `[Int]`, `[Double]`, `[Float]`

The protocol automatically handles type conversion and validation, so you can use Swift's native types directly in your code. Invalid types will be caught at compile time, preventing runtime errors.

```swift
import Sentry

SentrySDK.metrics.count(
    key: "button_click",
    value: 1,
    unit: nil,
    attributes: [
        "browser": "Firefox",           // String - passed directly
        "app_version": "1.0.0",         // String - passed directly
        "build_number": 123,            // Int - passed directly
        "is_premium": true,             // Bool - passed directly
        "success_rate": 0.95,           // Double - passed directly
        "tags": ["production", "v2"]     // [String] - passed directly
    ]
)
```

The `SentryAttributeValue` protocol ensures that all these types are automatically converted to the correct internal representation, providing both type safety and a clean, idiomatic Swift API.

### [Specifying Units](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#specifying-units)

All metric types (`count`, `gauge`, and `distribution`) support the optional `unit` parameter. Units help Sentry display metric values in a human-readable format.

The SDK provides the `SentryUnit` enum with type-safe unit values:

```swift
import Sentry

// Use enum cases for type safety (recommended)
SentrySDK.metrics.distribution(
    key: "response_time",
    value: 187.5,
    unit: .millisecond
)

SentrySDK.metrics.gauge(
    key: "memory_usage",
    value: 1024.0,
    unit: .byte
)

SentrySDK.metrics.distribution(
    key: "cache_latency",
    value: 42.3,
    unit: .microsecond
)
```

**Available unit categories:**

* **Duration**: `.nanosecond`, `.microsecond`, `.millisecond`, `.second`, `.minute`, `.hour`, `.day`, `.week`
* **Information**: `.bit`, `.byte`, `.kilobyte`, `.kibibyte`, `.megabyte`, `.mebibyte`, `.gigabyte`, `.gibibyte`, `.terabyte`, `.tebibyte`, `.petabyte`, `.pebibyte`, `.exabyte`, `.exbibyte`
* **Fraction**: `.ratio`, `.percent`
* **Custom**: `.generic("custom_unit")` for any other unit

You can also use string literals (e.g., `unit: "millisecond"`), which are automatically converted to the corresponding enum case. However, using enum cases is recommended for compile-time safety.

## [Options](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#options)

The Sentry Cocoa SDK provides several options to configure how metrics are captured and sent to Sentry.

### [Enabling/Disabling Metrics](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#enablingdisabling-metrics)

Metrics are enabled by default, but are not collected automatically. You must manually call the `SentrySDK.metrics` API to record metrics. If you need to disable metrics entirely, set `options.experimental.enableMetrics` to `false` when initializing the SDK:

```swift
import Sentry

SentrySDK.start { options in
    options.dsn = "___PUBLIC_DSN___"
    options.experimental.enableMetrics = false // Metrics are enabled by default
}
```

### [Filtering and Modifying Metrics](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#filtering-and-modifying-metrics)

Use the `beforeSendMetric` callback to filter or modify metrics before they're sent to Sentry. This is useful for:

* Removing sensitive data from metric attributes
* Dropping metrics you don't want to send
* Adding or modifying attributes
* Changing metric names or units

The callback receives a `SentryMetric` struct and must return either a modified metric or `nil` to drop it.

**Available `SentryMetric` properties:**

* `name`: The metric name (e.g., "api.response\_time")
* `value`: The metric value (`SentryMetricValue` - counter, distribution, or gauge)
* `unit`: The unit of measurement (`SentryUnit?`)
* `attributes`: Dictionary of attributes (`[String: SentryAttributeContent]`)
* `timestamp`: When the metric was recorded
* `traceId`: Associated trace ID for distributed tracing correlation

When modifying `attributes`, you can assign values directly using literals thanks to Swift's `ExpressibleBy...Literal` protocols. The SDK supports `String`, `Bool`, `Int`, `Double`, and arrays of these types.

```swift
import Sentry

SentrySDK.start { options in
    options.dsn = "___PUBLIC_DSN___"
    // Metrics are enabled by default, no need to set enableMetrics = true
    options.experimental.beforeSendMetric = { metric in
        // Create a mutable copy (SentryMetric is a struct)
        var metric = metric

        // Drop metrics based on attributes
        if case .boolean(let dropMe) = metric.attributes["dropMe"], dropMe {
            return nil
        }

        // Drop metrics by name
        if metric.name.hasPrefix("internal.") {
            return nil
        }

        // Modify or add attributes using literals (recommended)
        metric.attributes["processed"] = true          // Boolean literal
        metric.attributes["environment"] = "production" // String literal
        metric.attributes["retry_count"] = 3           // Integer literal
        metric.attributes["latency"] = 42.5            // Double literal

        // You can also use enum cases for explicitness
        metric.attributes["explicit"] = .boolean(true)
        metric.attributes["tags"] = .stringArray(["tag1", "tag2"])

        // Change the metric name
        if metric.name == "legacy_metric" {
            metric.name = "new_metric_name"
        }

        return metric
    }
}
```

### [Flushing Metrics](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#flushing-metrics)

By default, metrics are buffered and flushed depending on buffer size and time. If you need to manually flush metrics before the automatic interval, you can use the `flush` method. Note that this is a **blocking** call that will wait until all pending data is sent or the timeout is reached:

```swift
import Sentry

SentrySDK.flush(timeout: 5.0)
```

This will flush all pending metrics and events to Sentry.

## [Default Attributes](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#default-attributes)

By default the SDK will attach the following attributes to a metric:

### [Device and OS Attributes](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#device-and-os-attributes)

* `device.brand`: Always "Apple" for Apple devices.
* `device.model`: The device model (e.g., "iPhone14,2").
* `device.family`: The device family (e.g., "iPhone").
* `os.name`: The operating system name (e.g., "iOS").
* `os.version`: The operating system version.

### [User Attributes](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#user-attributes)

* `user.id`: The user ID from the current scope. Falls back to the installation ID if no user is set.
* `user.name`: The username from the current scope.
* `user.email`: The email address from the current scope.

### [SDK Attributes](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#sdk-attributes)

* `sentry.sdk.name`: The name of the SDK that sent the metric (e.g., "sentry.cocoa").
* `sentry.sdk.version`: The version of the SDK that sent the metric.
* `sentry.environment`: The environment set in the SDK.
* `sentry.release`: The release set in the SDK, if defined.

### [Trace Attributes](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#trace-attributes)

If there is an active span when the metric is recorded, the following attribute is added:

* `span_id`: The span ID of the active span.

The `trace_id` is set as a top-level field on the metric (not as an attribute) to enable distributed tracing correlation. When a span is active, the SDK uses that span's trace ID; otherwise, it falls back to the propagation context's trace ID.

### [Session Replay Attributes](https://docs.sentry.io/platforms/apple/guides/watchos/metrics.md#session-replay-attributes)

If Session Replay is enabled and active (iOS and tvOS only):

* `sentry.replay_id`: The current replay session ID.
