Skip to content

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.

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.

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.

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.

Every exported metric carries the service-level resource attributes built from OpenTelemetryConfig:

  • service.name — argument to OpenTelemetry::init
  • service.versionNESTRS_OPENTELEMETRY__SERVICE_VERSION
  • deployment.environmentNESTRS_OPENTELEMETRY__SERVICE_ENVIRONMENT
  • service.instance_idNESTRS_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.

  • 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