rylv-metrics
A high-performance DogStatsD metrics client for Rust with support for client-side aggregation.
Features
- High Performance: Lock-free data structures and optimized UDP batching
- Client-Side Aggregation: Reduces network overhead by aggregating metrics before sending
- Multiple Writer Backends:
Simple: Standard UDP writer (all platforms)LinuxBatch: Usessendmmsgfor batch UDP writes (Linux only)AppleBatch: Usessendmsg_xfor batch UDP writes (macOS only)Custom: Bring your own writer implementation
- Metric Types: Histograms, Counters, and Gauges
- Flexible Tags: Support for static and owned string tags
- Configurable Histograms: Adjustable significant figures, custom percentile lists, and optional base metrics (
count,min,avg,max) - Shared Collector Mode: Use
SharedCollectorto aggregate and drain metrics without background threads or network I/O
Installation
Add to your Cargo.toml:
[]
= "0.3.0"
Default build enables no transport or collector backend features. Enable the APIs you want explicitly. For example, UDP sending with a inner collector requires:
[]
= { = "0.3.0", = ["udp", "shared-collector"] }
Quick Start
use ;
use SocketAddr;
use Duration;
Metric Types
Histogram
Records distribution of values with configurable precision and percentiles:
histogram!;
You can configure per-metric or default histogram behavior with HistogramConfig
(significant figures, percentile list, and base metric toggles).
Counter
Increments a counter, aggregated client-side:
count!;
count_add!;
Gauge
Records point-in-time values:
gauge!;
Custom Writer
Implement StatsWriterTrait for custom metric destinations:
use ;
// Use with StatsWriterType::Custom(Box::new(MyWriter { ... }))
Shared Collector
Use SharedCollector when you want to own scheduling and transport externally:
use ;
let collector = default;
collector.count;
loop
SortedTags And PreparedMetric
For hot paths, you can precompute tag handling:
SortedTags: sorts and joins tags once, then reuse with*_sorted.PreparedMetric: precomputes metric+tags identity, then reuse with*_prepared.
Guidance for concurrency:
- Single-thread / low contention:
PreparedMetricis usually fastest. - Multi-thread with
TLSCollector:PreparedMetrictends to scale well. - Multi-thread with shared
MetricCollector:PreparedMetriccan add contention; preferSortedTags+*_sorted.
See examples:
examples/sorted_tags.rsexamples/prepared_metric_shared.rsexamples/sorted_tags_udp.rs
Benchmark Snapshot (Lower Is Better)
Measured on the current machine with thread_local_compare (histogram_* path):
| Scenario | Variant | Time (ns) | Throughput (M ops/s) |
|---|---|---|---|
| Single-thread | regular | 43.36 | 23.07 |
| Single-thread | sorted | 35.56 | 28.13 |
| Single-thread | prepared | 14.44 | 69.27 |
| Multi-thread shared collector | regular | 73.47 | 13.61 |
| Multi-thread shared collector | sorted | 44.92 | 22.26 |
| Multi-thread shared collector | prepared | 25.60 | 39.07 |
| Multi-thread TLS collector | regular | 7.53 | 132.87 |
| Multi-thread TLS collector | sorted | 4.73 | 211.38 |
| Multi-thread TLS collector | prepared | 3.02 | 330.65 |
Reproduce this snapshot with:
Tradeoffs
- TLS improves write throughput under contention, but uses more memory.
- With TLS, each active thread keeps a local aggregator per collector.
- This duplicates in-memory series state (keys, counters, gauges, histograms) until merge/flush.
- Approximate memory growth is proportional to
active_threads * active_series_per_thread. PreparedMetricavoids repeated metric/tag preparation work, but each aggregator still stores its own series state for prepared entries.
Feature Flags
udp: EnablesMetricCollector,MetricCollectorOptions, and built-in UDP writer types (Simple,LinuxBatch,AppleBatch)custom_writer: EnablesStatsWriterTraitexport andStatsWriterType::Customshared-collector: EnablesSharedCollector,SharedCollectorOptions, and shared in-memory aggregation APIstls-collector: EnablesTLSCollectorfor thread-local aggregationdhat-heap: Enables heap profiling support viadhatallocationcounter: Enables allocation counting instrumentation
Platform Support
- Linux (x86_64, aarch64)
- macOS (x86_64, aarch64)
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Release Workflow
Before publishing, run:
This runs verification, package/doc checks, release tests, and cargo publish --dry-run.