Skip to main content
A Meter is the entry point for creating instruments that record measurements in your application. Meters should be scoped to a single library or application component.

MeterProvider

The MeterProvider trait provides access to named Meter instances:
pub trait MeterProvider {
    fn meter(&self, name: &'static str) -> Meter;
    fn meter_with_scope(&self, scope: InstrumentationScope) -> Meter;
}

Creating a Meter

There are two ways to create a meter:

Simple Meter Creation

The simplest way is to use a static name:
use opentelemetry::{global, metrics::MeterProvider};

let provider = global::meter_provider();
let meter = provider.meter("my_app");

Meter with Full Scope

For libraries and crates, you should include version and schema information:
use opentelemetry::InstrumentationScope;
use opentelemetry::metrics::MeterProvider;
use opentelemetry_sdk::metrics::SdkMeterProvider;

let provider = SdkMeterProvider::default();

let scope = InstrumentationScope::builder(env!("CARGO_PKG_NAME"))
    .with_version(env!("CARGO_PKG_VERSION"))
    .with_schema_url("https://opentelemetry.io/schemas/1.0.0")
    .build();

let meter = provider.meter_with_scope(scope);

Meter Naming Guidelines

The meter name should:
  • Be unique within your application
  • Represent the instrumentation scope (typically the library or module name)
  • Not collide with other applications or libraries
  • Be stable across versions
Use your crate name as the meter name. For applications, use the application name. For libraries, use env!("CARGO_PKG_NAME") to automatically use your crate name.

Global Meter Provider

OpenTelemetry provides a global meter provider that can be accessed from anywhere in your application:
use opentelemetry::global;
use opentelemetry_sdk::metrics::SdkMeterProvider;
use opentelemetry_sdk::Resource;

// Initialize and set global provider
let exporter = opentelemetry_stdout::MetricExporterBuilder::default().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());

// Access the global provider from anywhere
let meter = global::meter("mylibraryname");

Creating Instruments

Once you have a Meter, you can create instruments to record measurements. All instruments are created using a builder pattern:
use opentelemetry::KeyValue;

let meter = global::meter("my-meter");

// Counter
let counter = meter.u64_counter("requests_total")
    .with_description("Total number of requests")
    .with_unit("requests")
    .build();

counter.add(1, &[KeyValue::new("method", "GET")]);

// Histogram
let histogram = meter.f64_histogram("request_duration")
    .with_description("Request duration in seconds")
    .with_unit("s")
    .with_boundaries(vec![0.0, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0])
    .build();

histogram.record(0.123, &[KeyValue::new("endpoint", "/api/users")]);

// Gauge
let gauge = meter.f64_gauge("cpu_usage")
    .with_description("Current CPU usage percentage")
    .with_unit("%")
    .build();

gauge.record(45.2, &[KeyValue::new("core", "0")]);

Available Instrument Builders

The Meter provides builders for all instrument types:

Synchronous Instruments

// Counters (monotonically increasing)
pub fn u64_counter(&self, name: impl Into<Cow<'static, str>>) -> InstrumentBuilder<'_, Counter<u64>>
pub fn f64_counter(&self, name: impl Into<Cow<'static, str>>) -> InstrumentBuilder<'_, Counter<f64>>

// UpDownCounters (can increase or decrease)
pub fn i64_up_down_counter(&self, name: impl Into<Cow<'static, str>>) -> InstrumentBuilder<'_, UpDownCounter<i64>>
pub fn f64_up_down_counter(&self, name: impl Into<Cow<'static, str>>) -> InstrumentBuilder<'_, UpDownCounter<f64>>

// Gauges (independent values)
pub fn u64_gauge(&self, name: impl Into<Cow<'static, str>>) -> InstrumentBuilder<'_, Gauge<u64>>
pub fn i64_gauge(&self, name: impl Into<Cow<'static, str>>) -> InstrumentBuilder<'_, Gauge<i64>>
pub fn f64_gauge(&self, name: impl Into<Cow<'static, str>>) -> InstrumentBuilder<'_, Gauge<f64>>

// Histograms (distributions)
pub fn f64_histogram(&self, name: impl Into<Cow<'static, str>>) -> HistogramBuilder<'_, Histogram<f64>>
pub fn u64_histogram(&self, name: impl Into<Cow<'static, str>>) -> HistogramBuilder<'_, Histogram<u64>>

Asynchronous Instruments

// Observable Counters
pub fn u64_observable_counter(&self, name: impl Into<Cow<'static, str>>) -> AsyncInstrumentBuilder<'_, ObservableCounter<u64>, u64>
pub fn f64_observable_counter(&self, name: impl Into<Cow<'static, str>>) -> AsyncInstrumentBuilder<'_, ObservableCounter<f64>, f64>

// Observable UpDownCounters
pub fn i64_observable_up_down_counter(&self, name: impl Into<Cow<'static, str>>) -> AsyncInstrumentBuilder<'_, ObservableUpDownCounter<i64>, i64>
pub fn f64_observable_up_down_counter(&self, name: impl Into<Cow<'static, str>>) -> AsyncInstrumentBuilder<'_, ObservableUpDownCounter<f64>, f64>

// Observable Gauges
pub fn u64_observable_gauge(&self, name: impl Into<Cow<'static, str>>) -> AsyncInstrumentBuilder<'_, ObservableGauge<u64>, u64>
pub fn i64_observable_gauge(&self, name: impl Into<Cow<'static, str>>) -> AsyncInstrumentBuilder<'_, ObservableGauge<i64>, i64>
pub fn f64_observable_gauge(&self, name: impl Into<Cow<'static, str>>) -> AsyncInstrumentBuilder<'_, ObservableGauge<f64>, f64>

Instrument Configuration

All instrument builders support common configuration options:
let instrument = meter.u64_counter("my_counter")
    .with_description("A detailed description of what this measures")
    .with_unit("requests")  // Unit is case-sensitive: "kb" != "kB"
    .build();
Unit names are case-sensitive. Use standard units like “ms” for milliseconds, “s” for seconds, “By” for bytes, etc.

Instrument Reuse

Instruments can be cloned to create multiple handles to the same underlying metric:
let counter = meter.u64_counter("requests").build();
let counter_clone = counter.clone();

// Both record to the same metric
counter.add(1, &[]);
counter_clone.add(1, &[]);
Clone instruments rather than creating duplicates. Creating multiple instruments with the same name can lower SDK performance.

Shutting Down

When your application terminates, shut down the meter provider to flush any pending metrics:
meter_provider.shutdown()?;
This ensures all metrics are exported before the application exits.

Next Steps

Instruments

Learn about the different instrument types

Counter

Record monotonically increasing values

Histogram

Record value distributions

Observable Instruments

Use callbacks to report measurements

Build docs developers (and LLMs) love