Derive Macro Metrics
#[derive(Metrics)]
{
// Attributes available to this derive:
#[metrics]
#[metric]
}
Expand description
Metrics derive macro.
Instruments all of the struct fields and creates a [Default] implementation for the struct
recording all of the metrics.
Additionally, it creates a describe method on the struct, which
internally calls the describe statements for all metric fields.
Sample usage:
use metrics::{Counter, Gauge, Histogram};
use metrics_derive::Metrics;
#[derive(Metrics)]
#[metrics(scope = "metrics_custom")]
pub struct CustomMetrics {
/// A gauge with doc comment description.
gauge: Gauge,
#[metric(rename = "second_gauge", describe = "A gauge with metric attribute description.")]
gauge2: Gauge,
/// Some doc comment
#[metric(describe = "Metric attribute description will be preferred over doc comment.")]
counter: Counter,
/// A renamed histogram.
#[metric(rename = "histogram")]
histo: Histogram,
}The example above will be expanded to:
pub struct CustomMetrics {
/// A gauge with doc comment description.
gauge: metrics::Gauge,
gauge2: metrics::Gauge,
/// Some doc comment
counter: metrics::Counter,
/// A renamed histogram.
histo: metrics::Histogram,
}
impl Default for CustomMetrics {
fn default() -> Self {
Self {
gauge: metrics::gauge!("metrics_custom_gauge"),
gauge2: metrics::gauge!("metrics_custom_second_gauge"),
counter: metrics::counter!("metrics_custom_counter"),
histo: metrics::histogram!("metrics_custom_histogram"),
}
}
}
impl CustomMetrics {
/// Describe all exposed metrics
pub fn describe() {
metrics::describe_gauge!(
"metrics_custom_gauge",
"A gauge with doc comment description."
);
metrics::describe_gauge!(
"metrics_custom_second_gauge",
"A gauge with metric attribute description."
);
metrics::describe_counter!(
"metrics_custom_counter",
"Metric attribute description will be preferred over doc comment."
);
metrics::describe_histogram!("metrics_custom_histogram", "A renamed histogram.");
}
}
impl std::fmt::Debug for CustomMetrics {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CustomMetrics").finish()
}
}Similarly, you can derive metrics with “dynamic” scope, meaning their scope can be set at the time of instantiation. For example:
use metrics_derive::Metrics;
#[derive(Metrics)]
#[metrics(dynamic = true)]
pub struct DynamicScopeMetrics {
/// A gauge with doc comment description.
gauge: metrics::Gauge,
}The example with dynamic scope will expand to
pub struct DynamicScopeMetrics {
/// A gauge with doc comment description.
gauge: metrics::Gauge,
}
impl DynamicScopeMetrics {
pub fn new(scope: &str) -> Self {
Self { gauge: metrics::gauge!(format!("{}{}{}", scope, "_", "gauge")) }
}
pub fn describe(scope: &str) {
metrics::describe_gauge!(
format!("{}{}{}", scope, "_", "gauge"),
"A gauge with doc comment description."
);
}
}
impl std::fmt::Debug for DynamicScopeMetrics {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DynamicScopeMetrics").finish()
}
}§Per-field labels
You can attach labels to individual fields using the labels attribute.
This is useful when you want multiple fields to share the same metric name
but be distinguished by label values:
use metrics::Counter;
use metrics_derive::Metrics;
#[derive(Metrics)]
#[metrics(scope = "forwarder")]
pub struct TransactionMetrics {
/// Number of transactions.
#[metric(rename = "transactions", labels = [("outcome", "forwarded")])]
forwarded: Counter,
/// Number of transactions.
#[metric(rename = "transactions", labels = [("outcome", "dropped")])]
dropped: Counter,
}Field-level labels are appended to any struct-level labels passed via
new_with_labels(). Multiple labels can be specified per field:
use metrics::Counter;
use metrics_derive::Metrics;
#[derive(Metrics)]
#[metrics(scope = "api")]
pub struct RequestMetrics {
/// Request count.
#[metric(rename = "requests", labels = [("method", "GET"), ("status", "200")])]
get_success: Counter,
}§Global labels
You can also specify labels at the struct level that apply to all fields.
These are combined with any instance labels passed via new_with_labels():
use metrics::Counter;
use metrics_derive::Metrics;
#[derive(Metrics)]
#[metrics(scope = "api", labels = [("service", "gateway"), ("version", "v1")])]
pub struct ApiMetrics {
/// Total requests.
requests: Counter,
/// Successful requests (with additional field-level labels).
#[metric(labels = [("status", "success")])]
success: Counter,
}Label order: instance labels (from new_with_labels) → global labels → field labels.
Label values can also be arbitrary expressions, such as constants:
use metrics::Counter;
use metrics_derive::Metrics;
const SERVICE_NAME: &str = "gateway";
#[derive(Metrics)]
#[metrics(scope = "api", labels = [("service", SERVICE_NAME)])]
pub struct ConstLabelMetrics {
/// Total requests.
requests: Counter,
}