> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/open-telemetry/opentelemetry-rust/llms.txt
> Use this file to discover all available pages before exploring further.

# Instruments

> Understanding the different types of metric instruments in OpenTelemetry Rust

Instruments are objects that record measurements in OpenTelemetry. The Metrics API provides several instrument types, each designed for specific measurement patterns.

## Instrument Categories

Instruments fall into two main categories:

### Synchronous Instruments

Synchronous instruments record measurements inline with your application code. They implement the `SyncInstrument` trait:

```rust theme={null}
pub trait SyncInstrument<T>: Send + Sync {
    fn measure(&self, measurement: T, attributes: &[KeyValue]);
}
```

Synchronous instruments include:

* **Counter**: Monotonically increasing values
* **UpDownCounter**: Values that can increase or decrease
* **Histogram**: Distribution of values
* **Gauge**: Independent point-in-time values

### Asynchronous Instruments

Asynchronous instruments use callbacks that are invoked during metric collection. They implement the `AsyncInstrument` trait:

```rust theme={null}
pub trait AsyncInstrument<T>: Send + Sync {
    fn observe(&self, measurement: T, attributes: &[KeyValue]);
}
```

Asynchronous instruments include:

* **ObservableCounter**: Observes monotonically increasing values
* **ObservableUpDownCounter**: Observes values that can increase or decrease
* **ObservableGauge**: Observes current values

## Instrument Types Overview

<CardGroup cols={2}>
  <Card title="Counter" icon="arrow-up" href="/metrics/counter">
    Records monotonically increasing values like request counts or bytes sent
  </Card>

  <Card title="UpDownCounter" icon="arrow-up-arrow-down">
    Records values that go up and down like active connections or queue depth
  </Card>

  <Card title="Histogram" icon="chart-histogram" href="/metrics/histogram">
    Records distributions of values like request duration or response size
  </Card>

  <Card title="Gauge" icon="gauge" href="/metrics/gauge">
    Records independent measurements like CPU usage or temperature
  </Card>
</CardGroup>

## Choosing the Right Instrument

Use this decision tree to select the appropriate instrument:

```mermaid theme={null}
graph TD
    A[Need to record a measurement?] --> B{Callback or inline?}
    B -->|Inline| C{Type of value?}
    B -->|Callback| D{Type of value?}
    
    C -->|Only increases| E[Counter]
    C -->|Increases or decreases| F[UpDownCounter]
    C -->|Distribution| G[Histogram]
    C -->|Current state| H[Gauge]
    
    D -->|Only increases| I[ObservableCounter]
    D -->|Increases or decreases| J[ObservableUpDownCounter]
    D -->|Current state| K[ObservableGauge]
```

### Counter vs. UpDownCounter

**Use Counter when:**

* Values only increase (e.g., requests served, errors, bytes sent)
* You're counting discrete events
* Resets should only happen on restart

**Use UpDownCounter when:**

* Values can increase or decrease (e.g., active connections, items in queue)
* You're tracking a resource that changes bidirectionally
* Current total is meaningful

### Histogram vs. Gauge

**Use Histogram when:**

* You need to understand the distribution (percentiles, min, max)
* Values represent durations, sizes, or other measurements
* Examples: latency, request size, temperature readings

**Use Gauge when:**

* You only care about the current value
* The last value is sufficient
* Examples: current CPU usage, current memory, cache size

### Synchronous vs. Asynchronous

**Use Synchronous when:**

* Recording measurements in request handlers
* Events happen as part of application logic
* You control when measurements occur

**Use Asynchronous (Observable) when:**

* Reading from system APIs or sensors
* Values are expensive to compute
* Measurements should happen on a schedule
* Multiple instruments need the same source data

## Instrument Builders

All instruments are created using a builder pattern:

### InstrumentBuilder (Synchronous)

```rust theme={null}
pub struct InstrumentBuilder<'a, T> {
    pub instrument_provider: &'a dyn InstrumentProvider,
    pub name: Cow<'static, str>,
    pub description: Option<Cow<'static, str>>,
    pub unit: Option<Cow<'static, str>>,
}
```

Example:

```rust theme={null}
let counter = meter.u64_counter("http_requests")
    .with_description("Total HTTP requests received")
    .with_unit("requests")
    .build();
```

### HistogramBuilder

Histograms have additional configuration for bucket boundaries:

```rust theme={null}
pub struct HistogramBuilder<'a, T> {
    pub instrument_provider: &'a dyn InstrumentProvider,
    pub name: Cow<'static, str>,
    pub description: Option<Cow<'static, str>>,
    pub unit: Option<Cow<'static, str>>,
    pub boundaries: Option<Vec<f64>>,
}
```

Example:

```rust theme={null}
let histogram = meter.f64_histogram("http_request_duration")
    .with_description("HTTP request duration in seconds")
    .with_unit("s")
    .with_boundaries(vec![0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0])
    .build();
```

<Note>
  Default boundaries: `[0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 7500.0, 10000.0]`
</Note>

### AsyncInstrumentBuilder (Observable)

Asynchronous instruments require callbacks:

```rust theme={null}
pub struct AsyncInstrumentBuilder<'a, I, M> {
    pub instrument_provider: &'a dyn InstrumentProvider,
    pub name: Cow<'static, str>,
    pub description: Option<Cow<'static, str>>,
    pub unit: Option<Cow<'static, str>>,
    pub callbacks: Vec<Callback<M>>,
}
```

Example:

```rust theme={null}
let _observable_counter = meter
    .u64_observable_counter("cpu_time")
    .with_description("CPU time used by the process")
    .with_unit("ms")
    .with_callback(|observer| {
        let cpu_time = get_cpu_time(); // Your function
        observer.observe(cpu_time, &[KeyValue::new("core", "0")]);
    })
    .build();
```

## Instrument Naming

Follow these conventions when naming instruments:

* Use lowercase letters
* Use underscores to separate words
* Choose descriptive, meaningful names
* Include the unit in the name when appropriate (e.g., `duration_seconds`, `size_bytes`)
* Use plural for counters (e.g., `requests_total`, `errors_count`)

<Warning>
  Instrument names must:

  * Not be empty
  * Start with an alphabetic character
  * Contain only alphanumeric characters, underscores, dots, and hyphens
  * Be no longer than 255 characters
</Warning>

## Units

Specify units using standard abbreviations:

* Time: `ms`, `s`, `min`, `h`, `d`
* Bytes: `By`, `KiBy`, `MiBy`
* Percentages: `%`
* Counts: `{items}`, `{requests}`, `{errors}`

```rust theme={null}
let duration = meter.f64_histogram("request_duration").with_unit("s").build();
let size = meter.u64_counter("bytes_sent").with_unit("By").build();
let usage = meter.f64_gauge("cpu_usage").with_unit("%").build();
```

<Warning>
  Units are case-sensitive: `kb` (kilobit) is different from `kB` (kilobyte).
</Warning>

## Cloning Instruments

All synchronous instruments can be cloned:

```rust theme={null}
let counter = meter.u64_counter("requests").build();
let counter_clone = counter.clone();

// Both record to the same underlying metric
counter.add(1, &[]);
counter_clone.add(1, &[]);
```

<Tip>
  Clone instruments when you need to share them across threads or modules. Avoid creating duplicate instruments with the same name, as this can impact performance.
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Counter" href="/metrics/counter">
    Learn about Counter instruments in detail
  </Card>

  <Card title="Histogram" href="/metrics/histogram">
    Understand how to use Histograms
  </Card>

  <Card title="Gauge" href="/metrics/gauge">
    Record independent measurements with Gauges
  </Card>

  <Card title="Observable Instruments" href="/metrics/observable-instruments">
    Use callbacks for asynchronous measurements
  </Card>
</CardGroup>
