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