use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
fn repo_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.parent()
.expect("cli/ has a parent")
.to_path_buf()
}
fn metric_tokens(text: &str) -> BTreeSet<String> {
let bytes = text.as_bytes();
let mut out = BTreeSet::new();
let needle = b"faucet_";
let mut i = 0;
while i + needle.len() <= bytes.len() {
if &bytes[i..i + needle.len()] == needle
&& (i == 0 || !(bytes[i - 1].is_ascii_alphanumeric() || bytes[i - 1] == b'_'))
{
let mut j = i + needle.len();
while j < bytes.len()
&& (bytes[j].is_ascii_lowercase() || bytes[j].is_ascii_digit() || bytes[j] == b'_')
{
j += 1;
}
if j > i + needle.len() {
out.insert(text[i..j].to_string());
}
i = j;
} else {
i += 1;
}
}
out
}
fn strip_histogram_suffix(name: &str) -> String {
for suffix in ["_bucket", "_sum", "_count"] {
if let Some(base) = name.strip_suffix(suffix) {
return base.to_string();
}
}
name.to_string()
}
fn defined_metrics(root: &Path) -> BTreeSet<String> {
let mut defined = BTreeSet::new();
let dirs = [
root.join("crates/core/src"),
root.join("crates/lineage/src"),
root.join("cli/src"),
];
fn walk(dir: &Path, defined: &mut BTreeSet<String>) {
for entry in std::fs::read_dir(dir).expect("read source dir") {
let path = entry.expect("dir entry").path();
if path.is_dir() {
walk(&path, defined);
} else if path.extension().and_then(|e| e.to_str()) == Some("rs") {
let text = std::fs::read_to_string(&path).expect("read source file");
defined.extend(metric_tokens(&text));
}
}
}
for dir in dirs {
walk(&dir, &mut defined);
}
defined
}
fn referenced_metrics(path: &Path) -> BTreeSet<String> {
let text =
std::fs::read_to_string(path).unwrap_or_else(|e| panic!("read {}: {e}", path.display()));
metric_tokens(&text)
.into_iter()
.map(|m| strip_histogram_suffix(&m))
.collect()
}
#[test]
fn artifacts_exist_and_parse() {
let root = repo_root();
let alerts = root.join("observability/prometheus/alerts.yml");
let parsed: serde_yaml::Value =
serde_yaml::from_str(&std::fs::read_to_string(&alerts).expect("alerts.yml exists"))
.expect("alerts.yml parses as YAML");
let groups = parsed["groups"].as_sequence().expect("alert groups");
assert!(groups.len() >= 3, "alert groups present");
let dashboards: Vec<PathBuf> = std::fs::read_dir(root.join("observability/grafana"))
.expect("grafana dir")
.map(|e| e.expect("entry").path())
.filter(|p| p.extension().and_then(|e| e.to_str()) == Some("json"))
.collect();
assert!(dashboards.len() >= 4, "four dashboards ship");
for d in &dashboards {
let parsed: serde_json::Value =
serde_json::from_str(&std::fs::read_to_string(d).expect("dashboard readable"))
.unwrap_or_else(|e| panic!("{} is not valid JSON: {e}", d.display()));
assert!(
parsed["uid"]
.as_str()
.unwrap_or_default()
.starts_with("faucet-"),
"{}: dashboard uid must be faucet-prefixed",
d.display()
);
assert!(
!parsed["panels"]
.as_array()
.unwrap_or(&Vec::new())
.is_empty(),
"{}: dashboard has panels",
d.display()
);
}
}
#[test]
fn every_referenced_metric_exists_in_the_codebase() {
let root = repo_root();
let defined = defined_metrics(&root);
assert!(
defined.contains("faucet_pipeline_runs_total"),
"sanity: definition scan found the core metrics"
);
let mut artifacts: Vec<PathBuf> = vec![root.join("observability/prometheus/alerts.yml")];
artifacts.extend(
std::fs::read_dir(root.join("observability/grafana"))
.expect("grafana dir")
.map(|e| e.expect("entry").path())
.filter(|p| p.extension().and_then(|e| e.to_str()) == Some("json")),
);
let mut unknown: Vec<String> = Vec::new();
for artifact in &artifacts {
for metric in referenced_metrics(artifact) {
if !defined.contains(&metric) {
unknown.push(format!(
"{} references unknown metric `{}`",
artifact.strip_prefix(&root).unwrap_or(artifact).display(),
metric
));
}
}
}
assert!(
unknown.is_empty(),
"observability artifacts reference metrics that do not exist in the codebase \
(renamed without updating the dashboards/alerts?):\n {}",
unknown.join("\n ")
);
}
#[test]
fn histogram_suffixes_strip_correctly() {
assert_eq!(
strip_histogram_suffix("faucet_pipeline_run_duration_seconds_bucket"),
"faucet_pipeline_run_duration_seconds"
);
assert_eq!(strip_histogram_suffix("faucet_x_sum"), "faucet_x");
assert_eq!(strip_histogram_suffix("faucet_x_count"), "faucet_x");
assert_eq!(
strip_histogram_suffix("faucet_pipeline_runs_total"),
"faucet_pipeline_runs_total"
);
let toks = metric_tokens(r#"rate(faucet_a_total[5m]) + prefaucet_b faucet_c"#);
assert!(toks.contains("faucet_a_total"));
assert!(toks.contains("faucet_c"));
assert!(!toks.contains("faucet_b"), "prefixed token not a match");
}