Monitoring Applications in Rust: A Complete Overview of Libraries and Tools
Rust is a systems programming language increasingly used for building high-load web services, network daemons, and infrastructure components. However, even the fastest code requires observation. In this article, we will cover the key libraries for monitoring applications in Rust: tracing, metrics, and integration with OpenTelemetry. You will learn how to collect logs, metrics, and traces to keep your application under control.
1. Why is monitoring needed in Rust?
Without monitoring, you won't know about problems until users start complaining. Rust applications typically run in production 24/7, so it's important to track:
- memory and CPU consumption;
- request response time;
- number of errors and panics;
- connection status with databases and external APIs.
The good news: the Rust ecosystem offers mature solutions for observability.
2. The tracing library — structured logging and tracing
tracing is a framework for instrumenting Rust programs. It allows you to create spans — units of work that can be nested within each other, and events — points with information.
Installation
[dependencies]tracing = "0.1"tracing-subscriber = "0.3"Example: basic HTTP request tracing
use tracing::{info, span, Level};use tracing_subscriber;
fn handle_request(user_id: u64) { let span = span!(Level::INFO, "handle_request", user_id); let _guard = span.enter(); info!("Request processing started"); // ... processing logic ... info!("Request completed");}
fn main() { tracing_subscriber::fmt::init(); handle_request(42);}The console output will contain structured fields that are easy to parse with grep or send to Jaeger.
3. The metrics library — collecting numeric metrics
metrics is a lightweight library for collecting counters, histograms, and gauges. It is ideal for real-time monitoring.
Installation
[dependencies]metrics = "0.22"metrics-exporter-prometheus = "0.14"Example: request counter and time histogram
use metrics::{counter, histogram};use std::time::Instant;
fn process_request() { let start = Instant::now(); counter!("requests_total", 1); // ... work emulation ... std::thread::sleep(std::time::Duration::from_millis(50)); let duration = start.elapsed().as_secs_f64(); histogram!("request_duration_seconds", duration);}To make metrics available via HTTP (for Prometheus), add an exporter:
use metrics_exporter_prometheus::PrometheusBuilder;
fn setup_metrics() { let builder = PrometheusBuilder::new(); builder.install().expect("Failed to install exporter"); // Metrics will be available at http://localhost:9000/metrics}4. OpenTelemetry — universal observability standard
OpenTelemetry (OTel) is a vendor-neutral framework for collecting traces, metrics, and logs. For Rust, there is the opentelemetry crate with support for OTLP (OpenTelemetry Protocol).
Installation
[dependencies]opentelemetry = { version = "0.22", features = ["rt-tokio"] }opentelemetry-otlp = "0.15"tracing-opentelemetry = "0.23"Example: integrating tracing with OpenTelemetry
use opentelemetry::global;use tracing_subscriber::layer::SubscriberExt;use tracing_subscriber::Registry;
fn init_otel() { let tracer = opentelemetry_otlp::new_pipeline() .install_simple()