aetos 0.1.0

A Rust proc macro library for generating Prometheus metrics rendering code from annotated structs
Documentation

Aetos

A Rust proc macro library for generating Prometheus metrics rendering code from annotated structs.

Quick Start

use aetos::{metrics, Label};

#[derive(Label)]
struct RequestLabels<'a> {
    method: &'a str,
    status: u32,
}

#[metrics]
struct MyMetrics<'a> {
    // Scalar metric, no labels
    #[counter(help = "Total requests")]
    requests: u64,

    // Vec metric, single label shorthand
    #[counter(help = "Events by type", label = "event_type")]
    events: Vec<(String, u64)>,

    // Vec metric, multiple labels requires a Label type
    #[counter(help = "HTTP requests by method and status")]
    http_requests: Vec<(RequestLabels<'a>, u64)>,
}

let metrics = MyMetrics {
    requests: 1000,
    events: vec![
        ("stake".to_string(), 10),
        ("unstake".to_string(), 5),
    ],
    http_requests: vec![
        (RequestLabels { method: "GET", status: 200 }, 150),
        (RequestLabels { method: "POST", status: 404 }, 3),
    ],
};

println!("{}", metrics);

This outputs:

# HELP requests Total requests
# TYPE requests counter
requests 1000
# HELP events Events by type
# TYPE events counter
events{event_type="stake"} 10
events{event_type="unstake"} 5
# HELP http_requests HTTP requests by method and status
# TYPE http_requests counter
http_requests{method="GET",status="200"} 150
http_requests{method="POST",status="404"} 3

Histograms

Histograms track value distributions across predefined buckets:

use aetos::{define_histogram, metrics, Label};

#[derive(Label, Hash, Eq, PartialEq, Clone, Debug)]
struct ResponseLabel {
    endpoint: &'static str,
}

// Labeled histogram
define_histogram!(Latency<ResponseLabel> = [0.1, 0.5, 1.0, 5.0]);

// Unlabeled histogram
define_histogram!(QueueTime<()> = [0.01, 0.1, 1.0]);

#[metrics]
struct Metrics {
    #[histogram(help = "Response time by endpoint")]
    response_time: Latency,

    #[histogram(help = "Queue wait time")]
    queue_time: QueueTime,
}

let mut m = Metrics {
    response_time: Latency::default(),
    queue_time: QueueTime::default(),
};

m.response_time.observe(ResponseLabel { endpoint: "/api" }, 0.25);
m.queue_time.observe((), 0.05);

println!("{}", m);

If you don't want to manually specify buckets, you can use these functions to generate them

use aetos::{define_histogram, linear_buckets};

define_histogram!(RequestLatency<()> = linear_buckets::<10>(0.1, 0.1));
// Generates buckets: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
use aetos::{define_histogram, exponential_buckets};

define_histogram!(ResponseSize<()> = exponential_buckets::<8>(0.001, 2.0));
// Generates buckets: [0.001, 0.002, 0.004, 0.008, 0.016, 0.032, 0.064, 0.128]