Attribute Macro foundations::telemetry::metrics::metrics
source · #[metrics]
logging
or metrics
or telemetry
or tracing
) and crate feature metrics
only.Expand description
A macro that allows to define Prometheus metrics.
The macro is a proc macro attribute that should be put on a module containing
bodyless functions. Each bodyless function corresponds to a single metric, whose
name becomes <global prefix>_<module name>_<bodyless function name>
and function’s
Rust doc comment is reported as metric description to Prometheus.
§Labels
Arguments of the bodyless functions become labels for that metric.
The metric types must implement prometheus_client::metrics::MetricType
, they
are reexported from this module for convenience:
The metrics associated with the functions are automatically registered in a global
registry, and they can be collected with the collect
function.
§Metric attributes
Example below shows how to use all the attributes listed here.
§#[ctor]
#[ctor]
attribute allows specifying how the metric should be built (e.g. HistogramBuilder
).
Constructor should implement the MetricConstructor<MetricType>
trait.
§#[optional]
Metrics marked with #[optional]
are collected in a separate registry and reported only if
collect_optional
argument of collect
is set to true
, or, in case the telemetry server
is used, if MetricsSettings::report_optional
is set to true
.
Can be used for heavy-weight metrics (e.g. with high cardinality) that don’t need to be reported on a regular basis.
§Example
use foundations::telemetry::metrics::{metrics, Counter, Gauge, HistogramBuilder, TimeHistogram};
use serde_with::DisplayFromStr;
use std::net::IpAddr;
use std::io;
use std::sync::Arc;
mod labels {
use serde::Serialize;
#[derive(Clone, Eq, Hash, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum IpVersion {
V4,
V6,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum L4Protocol {
Tcp,
Udp,
Quic,
Unknown,
}
#[derive(Clone, Eq, Hash, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum ProxiedProtocol {
Ip,
Tcp,
Udp,
Quic,
Unknown,
}
impl From<L4Protocol> for ProxiedProtocol {
fn from(l4: L4Protocol) -> Self {
match l4 {
L4Protocol::Tcp => Self::Tcp,
L4Protocol::Udp => Self::Udp,
L4Protocol::Quic => Self::Quic,
L4Protocol::Unknown => Self::Unknown,
}
}
}
}
// The generated module contains an implicit `use super::*;` statement.
#[metrics]
pub mod my_app_metrics {
/// Number of active client connections
pub fn client_connections_active(
// Labels with an anonymous reference type will get cloned.
endpoint: &Arc<String>,
protocol: labels::L4Protocol,
ip_version: labels::IpVersion,
ingress_ip: IpAddr,
) -> Gauge;
/// Histogram of task schedule delays
#[ctor = HistogramBuilder {
// 100 us to 1 second
buckets: &[1E-4, 2E-4, 3E-4, 4E-4, 5E-4, 6E-4, 7E-4, 8E-4, 9E-4, 1E-3, 1E-2, 2E-2, 4E-2, 8E-2, 1E-1, 1.0],
}]
pub fn tokio_runtime_task_schedule_delay_histogram(
task: &Arc<str>,
) -> TimeHistogram;
/// Number of client connections
pub fn client_connections_total(
endpoint: &Arc<String>,
// Labels with type `impl Into<T>` will invoke `std::convert::Into<T>`.
protocol: impl Into<labels::ProxiedProtocol>,
ingress_ip: IpAddr,
) -> Counter;
/// Tunnel transmit error count
pub fn tunnel_transmit_errors_total(
endpoint: &Arc<String>,
protocol: labels::L4Protocol,
ingress_ip: IpAddr,
// `serde_as` attribute is allowed without decorating the metric with `serde_with::serde_as`.
#[serde_as(as = "DisplayFromStr")]
kind: io::ErrorKind,
raw_os_error: i32,
) -> Counter;
/// Number of stalled futures
#[optional]
pub fn debug_stalled_future_count(
// Labels with a `'static` lifetime are used as is, without cloning.
name: &'static str,
) -> Counter;
/// Number of Proxy-Status serialization errors
// Metrics with no labels are also obviously supported.
pub fn proxy_status_serialization_error_count() -> Counter;
}
fn usage() {
let endpoint = Arc::new("http-over-tcp".to_owned());
let l4_protocol = labels::L4Protocol::Tcp;
let ingress_ip = "127.0.0.1".parse::<IpAddr>().unwrap();
my_app_metrics::client_connections_total(
&endpoint,
l4_protocol,
ingress_ip,
).inc();
let client_connections_active = my_app_metrics::client_connections_active(
&endpoint,
l4_protocol,
labels::IpVersion::V4,
ingress_ip,
);
client_connections_active.inc();
my_app_metrics::proxy_status_serialization_error_count().inc();
client_connections_active.dec();
}
§Renamed or reexported crate
The macro will fail to compile if foundations
crate is reexported. However, the crate path
can be explicitly specified for the macro to workaround that:
mod reexport {
pub use foundations::*;
}
use self::reexport::telemetry::metrics::Counter;
#[reexport::telemetry::metrics::metrics(crate_path = "reexport")]
mod my_app_metrics {
/// Total number of tasks workers stole from each other.
fn tokio_runtime_total_task_steal_count() -> Counter;
}