use metrics::{counter, describe_counter, describe_gauge, gauge};
use std::sync::Once;
static DESCRIBE: Once = Once::new();
fn describe() {
DESCRIBE.call_once(|| {
describe_counter!(
"faucet_backfill_units_total",
"Backfill window units finished, by outcome (ok | err | skipped)"
);
describe_gauge!(
"faucet_backfill_progress_ratio",
"Completed fraction of the in-flight backfill's planned units (0.0-1.0)"
);
});
}
pub(crate) fn record_unit(pipeline: &str, outcome: &'static str) {
describe();
counter!(
"faucet_backfill_units_total",
"pipeline" => pipeline.to_owned(),
"outcome" => outcome,
)
.increment(1);
}
fn progress_ratio(done: usize, planned: usize) -> f64 {
if planned == 0 {
1.0
} else {
(done as f64 / planned as f64).min(1.0)
}
}
pub(crate) fn set_progress(pipeline: &str, done: usize, planned: usize) {
describe();
gauge!(
"faucet_backfill_progress_ratio",
"pipeline" => pipeline.to_owned(),
)
.set(progress_ratio(done, planned));
}
#[cfg(test)]
mod tests {
use super::progress_ratio;
#[test]
fn empty_plan_is_fully_done() {
assert_eq!(progress_ratio(0, 0), 1.0);
assert_eq!(progress_ratio(5, 0), 1.0);
}
#[test]
fn none_done_is_zero() {
assert_eq!(progress_ratio(0, 4), 0.0);
}
#[test]
fn all_done_is_one() {
assert_eq!(progress_ratio(4, 4), 1.0);
}
#[test]
fn partial_is_the_fraction() {
assert_eq!(progress_ratio(1, 4), 0.25);
assert_eq!(progress_ratio(3, 4), 0.75);
}
#[test]
fn over_count_is_clamped_to_one() {
assert_eq!(progress_ratio(9, 4), 1.0);
}
#[test]
fn never_produces_nan() {
for (d, p) in [(0, 0), (0, 1), (1, 1), (3, 7), (100, 1)] {
assert!(!progress_ratio(d, p).is_nan(), "nan for {d}/{p}");
}
}
}