A flexible and performant metrics collection and export library for Rust applications in the Ruskit ecosystem.
Connect your Rust applications to modern observability platforms.
The metrics crate provides a simple yet powerful interface for collecting and exporting metrics from Rust applications. Built on top of the OpenTelemetry SDK, it supports multiple export formats and integrates seamlessly with the Ruskit configuration system.
- Measure what matters: Gain insights into application performance and behavior
- Make data-driven decisions: Track KPIs and operational metrics
- Detect issues early: Monitor trends to identify potential problems
- Understand user patterns: Capture business-relevant metrics
- π Multiple Exporters:
- OTLP: Export metrics using OpenTelemetry Protocol over gRPC
- Prometheus: Expose metrics in Prometheus format via HTTP endpoint
- Stdout: Write metrics to standard output for development and debugging
- π§© Feature-based Configuration: Use Cargo features to include only what you need
- βοΈ Integration with Ruskit Config: Seamless configuration through the ecosystem
- π·οΈ Resource Attribution: Automatic addition of service name, environment, and other attributes
- β±οΈ Intelligent Temporality: Optimal selection of delta or cumulative temporality based on instrument type
- π Comprehensive Documentation: Well-documented API with examples
Add metrics to your Cargo.toml:
[dependencies]
metrics = { version = "0.1", default-features = false }
opentelemetry = { version = "0.19", features = ["metrics"] }
configs = { version = "0.1" }
# Enable the exporters you need
[features]
default = ["stdout"]
prometheus = ["metrics/prometheus"]
otlp = ["metrics/otlp"]
stdout = ["metrics/stdout"]For development directly from the repository:
[dependencies]
metrics = { git = "https://github.com/ruskit/metrics.git", tag = "v0.1.0" }
configs = { git = "https://github.com/ruskit/configs.git", tag = "v0.1.0" }use opentelemetry::metrics::MeterProvider;
use metrics::provider;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize metrics provider
let provider = provider::install()?;
// Get a meter for your component
let meter = provider.meter("my_component");
// Create instruments
let counter = meter
.u64_counter("requests")
.with_description("Number of requests processed")
.init();
// Record a measurement
counter.add(1, &[]);
// Your application code...
Ok(())
}use configs::{Configs, Empty, MetricExporterKind};
use metrics::provider;
use warp::Filter;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a default configuration
let mut configs = Configs::<Empty>::default();
// Enable metrics collection with the Prometheus exporter
configs.metric.enable = true;
configs.metric.exporter = MetricExporterKind::Prometheus;
// Initialize metrics and get the Prometheus registry
let registry = provider::init(&configs)?;
// Create an HTTP endpoint to expose metrics
if let Some(registry) = registry {
let metrics_route = warp::path("metrics").map(move || {
let encoder = prometheus::TextEncoder::new();
let mut buffer = Vec::new();
encoder.encode(®istry.gather(), &mut buffer).unwrap();
String::from_utf8(buffer).unwrap()
});
// Start the HTTP server
tokio::spawn(warp::serve(metrics_route).run(([0, 0, 0, 0], 9100)));
}
// Rest of your application...
Ok(())
}use configs::{Configs, Empty, MetricExporterKind};
use metrics::provider;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a default configuration
let mut configs = Configs::<Empty>::default();
// Enable metrics collection with the OTLP exporter
configs.metric.enable = true;
configs.metric.exporter = MetricExporterKind::OtlpGrpc;
configs.metric.host = "http://localhost:4317".to_string();
configs.metric.header_access_key = "api-key".to_string();
configs.metric.access_key = "YOUR_API_KEY".to_string();
// Initialize metrics
provider::init(&configs)?;
// Now you can use OpenTelemetry API to record metrics
// ...
Ok(())
}use opentelemetry::{KeyValue, metrics::MeterProvider};
use metrics::provider;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = provider::install()?;
let meter = provider.meter("payment_service");
// Counter - for values that only go up
let counter = meter.u64_counter("processed_payments").init();
counter.add(1, &[KeyValue::new("status", "success")]);
// UpDownCounter - for values that can increase or decrease
let updown = meter.i64_up_down_counter("active_connections").init();
updown.add(1, &[]); // Connection opened
updown.add(-1, &[]); // Connection closed
// Histogram - for recording distributions of values
let histogram = meter.f64_histogram("response_time_seconds").init();
histogram.record(0.25, &[KeyValue::new("endpoint", "/api/users")]);
// Observable Gauge - for current value observations
let gauge = meter.f64_observable_gauge("memory_usage_bytes").init();
meter.register_callback(&[gauge.as_any()], move |observer| {
// Get current memory usage
let memory_usage = get_memory_usage();
observer.observe_f64(&gauge, memory_usage, &[]);
})?;
Ok(())
}
fn get_memory_usage() -> f64 {
// Implementation to get memory usage
1024.0 * 1024.0 // Example: 1MB
}Select the appropriate exporter through feature flags:
# Build with OTLP exporter
cargo build --features otlp
# Build with stdout exporter (default)
cargo build --features stdout| Feature | Description | Default |
|---|---|---|
otlp |
Enables the OpenTelemetry Protocol (OTLP) exporter over gRPC | No |
stdout |
Enables the standard output exporter for development | Yes |
prometheus |
Coming soon: Enables the Prometheus exporter | No |
The metrics system can be configured through environment variables or the configs crate:
| Config Field | Environment Variable | Description | Default |
|---|---|---|---|
metric.enable |
METRIC_ENABLE |
Whether metrics collection is enabled | false |
metric.exporter |
METRIC_EXPORTER |
Exporter type (Stdout, OtlpGrpc, Prometheus) |
Stdout |
metric.host |
METRIC_HOST |
Host address for the OTLP exporter | "" |
metric.header_access_key |
METRIC_HEADER_ACCESS_KEY |
Header name for authentication | "" |
metric.access_key |
METRIC_ACCESS_KEY |
Access key value for authentication | "" |
metric.service_type |
METRIC_SERVICE_TYPE |
Service type identifier | "" |
metric.export_timeout |
METRIC_EXPORT_TIMEOUT |
Export timeout in seconds | 30 |
metric.export_interval |
METRIC_EXPORT_INTERVAL |
Export interval in seconds | 60 |
metric.export_rate_base |
METRIC_EXPORT_RATE_BASE |
Base rate for export sampling | 0.8 |
# Build with default features
cargo build
# Run tests
cargo test
# Build with specific exporters
cargo build --features otlp
cargo build --no-default-features --features stdoutFor local development with OTLP, you can use the OpenTelemetry Collector:
- Install the OpenTelemetry Collector
- Configure your collector to receive OTLP and export to your desired backend:
# collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: localhost:4317
processors:
batch:
exporters:
logging:
verbosity: detailed
service:
pipelines:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [logging]- Run the collector and your application with the OTLP exporter enabled.
This project is licensed under the MIT License - see the LICENSE file for details.
This crate is part of the Ruskit ecosystem, which provides a modular toolkit for building robust Rust applications:
| Crate | Description |
|---|---|
configs |
Configuration management with environment variables and files |
logging |
Structured logging with different output formats |
traces |
Distributed tracing with OpenTelemetry |
metrics |
This crate: Metrics collection and export |
secrets_manager |
Secure secrets management |
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request