> ## 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.

# Basic Metrics

> Learn how to collect and export metrics using OpenTelemetry Rust SDK with counters, histograms, and gauges

## Overview

Metrics allow you to measure and track numerical data about your application's performance and behavior. This guide demonstrates all the core metric instruments available in OpenTelemetry Rust.

## Dependencies

Add these dependencies to your `Cargo.toml`:

```toml Cargo.toml theme={null}
[dependencies]
opentelemetry = { version = "*", features = ["metrics"] }
opentelemetry_sdk = { version = "*", features = ["metrics"] }
opentelemetry-stdout = { version = "*", features = ["metrics"] }
tokio = { version = "1", features = ["full"] }
```

## Complete Example

<Steps>
  <Step title="Initialize the Meter Provider">
    Set up the meter provider with a stdout exporter and resource attributes.

    ```rust theme={null}
    use opentelemetry::{global, KeyValue};
    use opentelemetry_sdk::metrics::SdkMeterProvider;
    use opentelemetry_sdk::Resource;

    fn init_meter_provider() -> SdkMeterProvider {
        let exporter = opentelemetry_stdout::MetricExporterBuilder::default()
            // Build exporter using Delta Temporality (Defaults to Temporality::Cumulative)
            // .with_temporality(opentelemetry_sdk::metrics::Temporality::Delta)
            .build();
        
        let provider = SdkMeterProvider::builder()
            .with_periodic_exporter(exporter)
            .with_resource(
                Resource::builder()
                    .with_service_name("metrics-basic-example")
                    .build(),
            )
            .build();
        
        global::set_meter_provider(provider.clone());
        provider
    }
    ```
  </Step>

  <Step title="Create and Use Counters">
    Counters are used for monotonically increasing values.

    ```rust theme={null}
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let meter_provider = init_meter_provider();
        let meter = global::meter("mylibraryname");

        // Create a Counter Instrument
        let counter = meter.u64_counter("my_counter").build();

        // Record measurements using the Counter instrument
        counter.add(
            10,
            &[
                KeyValue::new("mykey1", "myvalue1"),
                KeyValue::new("mykey2", "myvalue2"),
            ],
        );

        meter_provider.shutdown()?;
        Ok(())
    }
    ```
  </Step>

  <Step title="Create Observable Counters">
    Observable counters allow you to register a callback that reports measurements asynchronously.

    ```rust theme={null}
    let _observable_counter = meter
        .u64_observable_counter("my_observable_counter")
        .with_description("My observable counter example description")
        .with_unit("myunit")
        .with_callback(|observer| {
            observer.observe(
                100,
                &[
                    KeyValue::new("mykey1", "myvalue1"),
                    KeyValue::new("mykey2", "myvalue2"),
                ],
            )
        })
        .build();
    ```
  </Step>

  <Step title="Use UpDownCounters">
    UpDownCounters can increase or decrease, useful for tracking values like queue sizes.

    ```rust theme={null}
    // Create an UpDownCounter Instrument
    let updown_counter = meter.i64_up_down_counter("my_updown_counter").build();

    // Record measurements (can be negative)
    updown_counter.add(
        -10,
        &[
            KeyValue::new("mykey1", "myvalue1"),
            KeyValue::new("mykey2", "myvalue2"),
        ],
    );

    // Observable version
    let _observable_up_down_counter = meter
        .i64_observable_up_down_counter("my_observable_updown_counter")
        .with_description("My observable updown counter example description")
        .with_unit("myunit")
        .with_callback(|observer| {
            observer.observe(
                100,
                &[
                    KeyValue::new("mykey1", "myvalue1"),
                    KeyValue::new("mykey2", "myvalue2"),
                ],
            )
        })
        .build();
    ```
  </Step>

  <Step title="Create Histograms">
    Histograms measure the distribution of values, perfect for latencies and sizes.

    ```rust theme={null}
    use std::vec;

    // Create a Histogram Instrument
    let histogram = meter
        .f64_histogram("my_histogram")
        .with_description("My histogram example description")
        // Setting boundaries is optional. By default, the boundaries are set to
        // [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]
        .with_boundaries(vec![0.0, 5.0, 10.0, 15.0, 20.0, 25.0])
        .build();

    // Record measurements using the histogram instrument
    histogram.record(
        10.5,
        &[
            KeyValue::new("mykey1", "myvalue1"),
            KeyValue::new("mykey2", "myvalue2"),
        ],
    );
    ```

    <Note>
      There is no ObservableHistogram instrument in OpenTelemetry.
    </Note>
  </Step>

  <Step title="Use Gauges">
    Gauges represent a value that can arbitrarily go up and down.

    ```rust theme={null}
    // Create a Gauge Instrument
    let gauge = meter
        .f64_gauge("my_gauge")
        .with_description("A gauge set to 1.0")
        .with_unit("myunit")
        .build();

    gauge.record(
        1.0,
        &[
            KeyValue::new("mykey1", "myvalue1"),
            KeyValue::new("mykey2", "myvalue2"),
        ],
    );

    // Create an ObservableGauge instrument
    let _observable_gauge = meter
        .f64_observable_gauge("my_observable_gauge")
        .with_description("An observable gauge set to 1.0")
        .with_unit("myunit")
        .with_callback(|observer| {
            observer.observe(
                1.0,
                &[
                    KeyValue::new("mykey1", "myvalue1"),
                    KeyValue::new("mykey2", "myvalue2"),
                ],
            )
        })
        .build();
    ```
  </Step>
</Steps>

## Metric Instruments Summary

| Instrument                  | Type         | Use Case                                            |
| --------------------------- | ------------ | --------------------------------------------------- |
| **Counter**                 | Synchronous  | Monotonically increasing values (requests, errors)  |
| **UpDownCounter**           | Synchronous  | Values that go up and down (active connections)     |
| **Histogram**               | Synchronous  | Distribution of values (latencies, response sizes)  |
| **Gauge**                   | Synchronous  | Current value snapshots (temperature, memory usage) |
| **ObservableCounter**       | Asynchronous | Callback-based monotonic values                     |
| **ObservableUpDownCounter** | Asynchronous | Callback-based up/down values                       |
| **ObservableGauge**         | Asynchronous | Callback-based current values                       |

<Tip>
  Metrics are exported by default every 60 seconds when using the stdout exporter. Shutting down the MeterProvider instantly flushes the metrics instead of waiting for the interval.
</Tip>

## Advanced Metrics

For advanced use cases like custom aggregations, views, and exponential histograms, check out the metrics-advanced example in the source repository which covers:

* Renaming metrics and changing units with Views
* Controlling cardinality limits
* Using exponential histograms for unpredictable value ranges
* Delta vs. Cumulative temporality

<Note>
  Always call `shutdown()` on the meter provider before your application exits to ensure all metrics are properly flushed to the exporter.
</Note>
