Metrics
Metrics are the aggregate counterpart to traces — reach for them when you need a number over time (signups per minute, job duration percentiles, queue depth) rather than the story of one request.
OpenTelemetryModule provides Arc<OpenTelemetryMeter> — the OTel global
meter, wrapped so it flows through the DI graph. Inject it like any other
dependency.
A first counter
Section titled “A first counter”Inject the meter, then build the instrument from it. Arc<OpenTelemetryMeter>
derefs to the inner Meter; the meter caches instruments by name, so building
the counter at the call site is cheap and needs no extra field.
use std::sync::Arc;
use nest_rs_core::injectable;use nest_rs_opentelemetry::OpenTelemetryMeter;
#[injectable]pub struct SignupMetrics { #[inject] meter: Arc<OpenTelemetryMeter>,}
impl SignupMetrics { /// Call this after a successful signup. pub fn record_signup(&self) { self.meter.u64_counter("users.created").build().add(1, &[]); }}Counters, histograms, gauges — anything the
opentelemetry meter exposes works. Inject
Arc<OpenTelemetryMeter> into the service that owns the event and build the
instrument lazily inside the method, as above.
Attributes
Section titled “Attributes”The second argument to .add(...) / .record(...) is a slice of OTel
attributes — the metric’s labels at the OTel/Prometheus boundary.
use opentelemetry::KeyValue;
self.meter.u64_counter("users.created").build().add(1, &[ KeyValue::new("org_id", org_id.to_string()), KeyValue::new("source", "api"),]);Stick to a small, bounded cardinality on the label set — every distinct attribute combination becomes a separate time series.
Export
Section titled “Export”Metrics batch on a
PeriodicReader and export through the
same OTLP endpoint as the traces (set
NESTRS_OPENTELEMETRY__OTLP_ENDPOINT). Without an endpoint, instrument
construction still works but the readings stay local — useful for tests that
want to assert on counter increments without spinning a collector.
Resource attributes
Section titled “Resource attributes”Every exported metric carries the service-level resource attributes built from
OpenTelemetryConfig:
service.name— argument toOpenTelemetry::initservice.version—NESTRS_OPENTELEMETRY__SERVICE_VERSIONdeployment.environment—NESTRS_OPENTELEMETRY__SERVICE_ENVIRONMENTservice.instance_id—NESTRS_OPENTELEMETRY__SERVICE_INSTANCE_ID(a fresh UUIDv7 per process by default, so restarts get distinct identities in the backend)
These come from the
opentelemetry-semantic-conventions
schema, so any backend that understands OTel semconv (Grafana Cloud, Honeycomb,
Datadog OTLP, …) keys on them out of the box.
Going further
Section titled “Going further”- Traces — the per-request story metrics aggregate.
- Logs — structured events on the same OTLP endpoint.
- OpenTelemetry — the meter provider and OTLP export.
Built by YV17labs