use super::*;
const INSTRUMENT_BUILDERS: [&str; 6] = [
".u64_counter(",
".f64_counter(",
".u64_histogram(",
".f64_histogram(",
".i64_gauge(",
".u64_gauge(",
];
const REGISTRATION_CALLS: [(&str, &str); 3] = [
(".counter(", "counter"),
(".histogram(", "histogram"),
(".gauge(", "gauge"),
];
const OTEL_RESOLVERS: [&str; 3] = ["fn counter_for", "fn histogram_for", "fn gauge_for"];
const ARGUMENT_END: [&str; 2] = [",", ")"];
const PATTERN_END: [&str; 2] = ["=>", "|"];
fn complete_catalog_ident(arg: &str, terminators: &[&str]) -> Option<String> {
let rest = arg.strip_prefix("catalog::")?;
let ident: String = rest
.chars()
.take_while(|c| c.is_ascii_uppercase() || c.is_ascii_digit() || *c == '_')
.collect();
if ident.is_empty() {
return None;
}
let after = rest[ident.len()..].trim_start();
terminators
.iter()
.any(|t| after.starts_with(t))
.then_some(ident)
}
fn call_argument(src: &str, end: usize) -> String {
src[end..]
.trim_start()
.chars()
.take(40)
.collect::<String>()
.replace('\n', " ")
}
fn parse_registrations(src: &str) -> Result<std::collections::BTreeMap<String, String>, String> {
let mut out = std::collections::BTreeMap::new();
for (call, kind) in REGISTRATION_CALLS {
for (i, _) in src.match_indices(call) {
let end = i + call.len();
let arg = src[end..].trim_start();
let Some(ident) = complete_catalog_ident(arg, &ARGUMENT_END) else {
return Err(format!(
"`{call}` is a Registry registration whose first argument is not a \
`catalog::IDENT` constant: {:?}. Register metrics by their catalog \
constant — a string literal or a local alias hides the metric from \
the catalogue guards (#1705, F4)",
call_argument(src, end)
));
};
if let Some(prior) = out.insert(ident.clone(), kind.to_string()) {
if prior != kind {
return Err(format!(
"catalog::{ident} is registered as both a {prior} and a {kind}"
));
}
return Err(format!(
"catalog::{ident} is registered twice as a {kind} — the second \
registration silently replaces the first"
));
}
}
}
if out.is_empty() {
return Err(
"no Registry registrations found — REGISTRATION_CALLS no longer matches the \
otel sources, and a guard with an empty subject set passes vacuously"
.to_string(),
);
}
Ok(out)
}
fn parse_builder_constructions(src: &str) -> Result<std::collections::BTreeSet<String>, String> {
let mut out = std::collections::BTreeSet::new();
let mut registry_helpers = 0usize;
let mut adhoc_fallbacks = 0usize;
for builder in INSTRUMENT_BUILDERS {
for (i, _) in src.match_indices(builder) {
let end = i + builder.len();
let arg = src[end..].trim_start();
if let Some(ident) = complete_catalog_ident(arg, &ARGUMENT_END) {
out.insert(ident);
continue;
}
let is_name_param = arg
.strip_prefix("name")
.is_some_and(|rest| rest.trim_start().starts_with(')'));
let receiver: String = src[i.saturating_sub(64)..i]
.split_whitespace()
.collect::<Vec<_>>()
.join("");
if is_name_param && receiver.ends_with(".meter") {
registry_helpers += 1;
continue;
}
if is_name_param && (receiver.ends_with("meter()") || receiver.ends_with("meter")) {
adhoc_fallbacks += 1;
continue;
}
return Err(format!(
"`{builder}` is called with an argument this guard cannot classify: {:?}. \
An instrument must be built either from a `catalog::IDENT` constant or \
by a `Registry` helper / the ad-hoc `_ =>` fallback from its `name` \
parameter — anything else (a string literal, a local alias) would hide \
the metric from the catalogue guards (#1705, F4)",
call_argument(src, end)
));
}
}
if registry_helpers != 3 {
return Err(format!(
"expected the 3 `Registry` instrument helpers, found {registry_helpers} — \
the construction site moved, so this guard is no longer reading it"
));
}
if adhoc_fallbacks != 3 {
return Err(format!(
"expected the 3 ad-hoc `_ =>` fallbacks in otel.rs, found {adhoc_fallbacks} — \
either a fallback was added without being classified here, or the emit path \
no longer has one"
));
}
Ok(out)
}
fn resolver_bodies(src: &str) -> Result<Vec<&str>, String> {
let mut out = Vec::new();
for resolver in OTEL_RESOLVERS {
let start = src.find(resolver).ok_or_else(|| {
format!(
"`{resolver}` not found in the otel sources — the emit path resolves \
names through these three functions, so renaming one must be reflected \
in OTEL_RESOLVERS rather than leaving the guards blind"
)
})?;
let body = &src[start..];
let end = body
.find("\n}\n")
.ok_or_else(|| format!("`{resolver}` must end at a column-0 closing brace"))?;
out.push(&body[..end]);
}
Ok(out)
}
fn handwritten_dispatch_arms(src: &str) -> Result<std::collections::BTreeSet<String>, String> {
let mut out = std::collections::BTreeSet::new();
for body in resolver_bodies(src)? {
for (i, _) in body.match_indices("catalog::") {
let rest = &body[i..];
if let Some(ident) = complete_catalog_ident(rest, &PATTERN_END) {
out.insert(ident);
}
}
}
Ok(out)
}
fn check_resolvers_have_no_handwritten_dispatch(src: &str) -> Result<(), String> {
match handwritten_dispatch_arms(src) {
Err(why) => Err(format!("the otel resolvers could not be parsed: {why}")),
Ok(arms) if !arms.is_empty() => Err(format!(
"the otel resolvers contain hand-written per-metric dispatch arms for \
{arms:?}. Registration must stay ONE construct (a `Registry` call), or a \
name/instrument mismatch becomes representable again and invisible to every \
guard (#1705, F3)"
)),
Ok(_) => Ok(()),
}
}
fn assert_resolvers_have_no_handwritten_dispatch(src: &str) {
if let Err(why) = check_resolvers_have_no_handwritten_dispatch(src) {
panic!("{why}");
}
}
fn otel_registrations(src: &str) -> std::collections::BTreeMap<String, String> {
parse_registrations(src).unwrap_or_else(|why| panic!("otel registration parse failed: {why}"))
}
fn otel_instrument_bindings(src: &str) -> std::collections::BTreeSet<String> {
let mut out: std::collections::BTreeSet<String> = otel_registrations(src).into_keys().collect();
out.extend(
parse_builder_constructions(src)
.unwrap_or_else(|why| panic!("otel construction parse failed: {why}")),
);
out.extend(
handwritten_dispatch_arms(src)
.unwrap_or_else(|why| panic!("otel resolver parse failed: {why}")),
);
out
}
fn otel_registered_instruments(src: &str) -> std::collections::BTreeSet<String> {
assert_resolvers_have_no_handwritten_dispatch(src);
otel_registrations(src).into_keys().collect()
}
#[test]
fn partition_access_probe_metrics_have_dedicated_registrations_not_the_adhoc_fallback() {
assert_every_otel_source_is_scanned();
let registrations = otel_registrations(&otel_sources_uncommented());
for (metric, ident, kind) in [
(
READ_PARTITION_ACCESS_DISTINCT_PARTITIONS,
"READ_PARTITION_ACCESS_DISTINCT_PARTITIONS",
"counter",
),
(
READ_PARTITION_ACCESS_ACCESSES,
"READ_PARTITION_ACCESS_ACCESSES",
"counter",
),
(
READ_PARTITION_ACCESS_BYTES,
"READ_PARTITION_ACCESS_BYTES",
"counter",
),
(
READ_PARTITION_ACCESS_SAMPLE_DENOMINATOR,
"READ_PARTITION_ACCESS_SAMPLE_DENOMINATOR",
"gauge",
),
] {
assert_eq!(
registrations.get(ident).map(String::as_str),
Some(kind),
"{metric} must be registered as a dedicated {kind} so its series carries \
its catalogued unit and description, never the ad-hoc fallback"
);
}
let otel_src = otel_sources_uncommented();
for (ident, unit) in [
("READ_PARTITION_ACCESS_BYTES", "BYTES"),
("READ_PARTITION_ACCESS_SAMPLE_DENOMINATOR", "DIMENSIONLESS"),
] {
let at = otel_src
.find(&format!("catalog::{ident},"))
.unwrap_or_else(|| panic!("no registration call for catalog::{ident}"));
let tail: String = otel_src[at..].chars().take(160).collect();
assert!(
tail.contains(&format!("catalog::unit::{unit}")),
"catalog::{ident} must be registered with unit::{unit}: {tail:?}"
);
}
}
#[test]
fn every_instrument_registered_in_otel_is_catalogued() {
assert_every_otel_source_is_scanned();
let otel_src = otel_sources_uncommented();
let otel_src = otel_src.as_str();
let catalogued: std::collections::HashSet<&str> = ALL_METRICS.iter().copied().collect();
assert_every_catalog_source_is_scanned();
let ident_to_value = parse_str_consts(catalog_sources());
let mut missing = Vec::new();
let mut refs: Vec<String> = otel_instrument_bindings(otel_src).into_iter().collect();
refs.sort();
for ident in refs {
let value = ident_to_value.get(ident.as_str()).copied().unwrap_or_else(|| {
panic!("otel.rs binds an instrument to catalog::{ident}, which is not a metric-name constant in the catalog sources")
});
if !catalogued.contains(value) {
missing.push(format!("catalog::{ident} (\"{value}\")"));
}
}
assert!(
missing.is_empty(),
"otel.rs registers instruments for metrics ABSENT from ALL_METRICS \
(add them to catalog::ALL_METRICS): {missing:?}"
);
}
#[test]
fn every_catalogued_metric_is_otel_registered_or_declared_stats_only() {
assert_every_otel_source_is_scanned();
let refs = otel_registered_instruments(&otel_sources_uncommented());
let value_to_ident = value_to_ident();
let stats_only: std::collections::HashSet<&str> =
STATS_ONLY_METRICS.iter().map(|m| m.name).collect();
let mut phantom = Vec::new();
for name in ALL_METRICS {
let ident = value_to_ident.get(name).copied().unwrap_or_else(|| {
panic!(
"ALL_METRICS entry {name:?} has no `pub const` declaration in the catalog sources"
)
});
if !refs.contains(ident) && !stats_only.contains(name) {
phantom.push(format!("catalog::{ident} (\"{name}\")"));
}
}
assert!(
phantom.is_empty(),
"ALL_METRICS names metrics with NO registered otel instrument and no \
STATS_ONLY_METRICS declaration — either wire the instrument in \
otel_instruments.rs/otel.rs, or declare it stats-only with its reason: \
{phantom:?}"
);
}
#[test]
fn stats_only_metrics_are_catalogued_and_never_otel_registered() {
assert_every_otel_source_is_scanned();
let refs = otel_instrument_bindings(&otel_sources_uncommented());
let value_to_ident = value_to_ident();
let mut seen = std::collections::HashSet::new();
for name in STATS_ONLY_METRICS.iter().map(|m| m.name) {
assert!(
ALL_METRICS.contains(&name),
"{name} is declared stats-only but is not in ALL_METRICS"
);
assert!(
seen.insert(name),
"duplicate STATS_ONLY_METRICS entry {name}"
);
let ident = value_to_ident.get(name).copied().unwrap_or_else(|| {
panic!("STATS_ONLY_METRICS entry {name:?} has no `pub const` in catalog.rs")
});
assert!(
!refs.contains(ident),
"catalog::{ident} (\"{name}\") IS registered as an otel instrument — \
remove it from STATS_ONLY_METRICS, or the reverse registration guard \
carries a stale exemption"
);
}
}
#[test]
fn saturation_gauges_have_dedicated_registrations_not_the_adhoc_fallback() {
assert_every_otel_source_is_scanned();
let registrations = otel_registrations(&otel_sources_uncommented());
for ident in [
"MERGE_EGRESS_CHANNEL_DEPTH",
"MERGE_ACTIVE_MERGES",
"PROC_THREADS",
"PROC_FDS",
"PROC_RSS_BYTES",
"FLIGHT_BLOCKING_TASKS_IN_USE",
"FLIGHT_TABLES_DISCOVERED",
"FLIGHT_WARM_TABLES",
] {
assert_eq!(
registrations.get(ident).map(String::as_str),
Some("gauge"),
"catalog::{ident} has no dedicated GAUGE registration — the gauge would \
fall through to the ad-hoc per-call-rebuilt fallback (#2412)"
);
}
}
fn synthetic_otel_source(resolver_extra: &str, registrations: &str) -> String {
format!(
"fn counter_for(i: &Instruments, name: &str) -> Option<&Counter<u64>> {{\n\
{resolver_extra} i.counters.get(name)\n}}\n\
fn histogram_for() {{\n i.histograms.get(name)\n}}\n\
fn gauge_for() {{\n i.gauges.get(name)\n}}\n\
fn add_counter() {{\n meter().u64_counter(name).build()\n}}\n\
fn record_histogram() {{\n meter().f64_histogram(name).build()\n}}\n\
fn record_gauge() {{\n meter().i64_gauge(name).build()\n}}\n\
impl Registry {{\n\
\x20 fn counter(&mut self) {{ self.meter.u64_counter(name).build() }}\n\
\x20 fn histogram(&mut self) {{ self.meter.f64_histogram(name).build() }}\n\
\x20 fn gauge(&mut self) {{ self.meter.i64_gauge(name).build() }}\n}}\n\
fn register_all(reg: &mut Registry) {{\n\
\x20 reg.counter(catalog::ANCHOR, catalog::unit::ROWS, \"anchor\");\n\
{registrations}}}\n"
)
}
fn synthetic_registered(resolver_extra: &str, registrations: &str) -> (bool, bool) {
let src = strip_rust_comments(&synthetic_otel_source(resolver_extra, registrations));
(
otel_instrument_bindings(&src).contains("GHOST"),
otel_registered_instruments(&src).contains("GHOST"),
)
}
#[test]
fn a_comment_or_a_dead_reference_cannot_pass_as_a_registered_instrument() {
let commented_out = synthetic_registered(
"",
" // reg.counter(catalog::GHOST, catalog::unit::ROWS, \"g\");\n",
);
assert_eq!(
commented_out,
(false, false),
"a commented-out registration must register nothing"
);
let doc_link = synthetic_registered("", " /* reg.counter(catalog::GHOST, u, \"g\") */\n");
assert_eq!(
doc_link,
(false, false),
"a doc link / block comment must register nothing"
);
let dead_code = synthetic_registered("", " let _ = catalog::GHOST;\n");
assert_eq!(
dead_code,
(false, false),
"a dead reference that registers no instrument must register nothing"
);
}
#[test]
fn a_registry_call_is_the_whole_registration() {
assert_eq!(
synthetic_registered(
"",
" reg.counter(catalog::GHOST, catalog::unit::ROWS, \"g\");\n"
),
(true, true),
"a Registry call registers the metric outright"
);
assert_eq!(
synthetic_registered(
"",
" reg.gauge(\n catalog::GHOST,\n catalog::unit::ROWS,\n \"g\",\n );\n"
),
(true, true),
"a wrapped registration must not drop out"
);
}
#[test]
fn a_handwritten_dispatch_arm_is_rejected_because_it_can_mis_wire() {
let mis_wired = strip_rust_comments(&synthetic_otel_source(
" let _ = match name { catalog::READ_ROWS => &i.read_bytes, _ => return None };\n",
"",
));
let arms = handwritten_dispatch_arms(&mis_wired).expect("the resolvers must parse");
assert!(
arms.contains("READ_ROWS"),
"a mis-wired dispatch arm must be detected: {arms:?}"
);
let why = check_resolvers_have_no_handwritten_dispatch(&mis_wired)
.expect_err("a mis-wired dispatch arm must RED the guard, not merely be listed");
assert!(
why.contains("READ_ROWS") && why.contains("hand-written per-metric dispatch"),
"the rejection must name the offending arm: {why}"
);
let hand_wired = strip_rust_comments(&synthetic_otel_source(
" let _ = match name { catalog::READ_ROWS => &i.read_rows, _ => return None };\n",
"",
));
assert!(
check_resolvers_have_no_handwritten_dispatch(&hand_wired).is_err(),
"any per-metric dispatch arm must be rejected, correct-looking or not"
);
assert_every_otel_source_is_scanned();
assert_resolvers_have_no_handwritten_dispatch(&otel_sources_uncommented());
}
#[test]
fn an_unrecognised_registration_argument_fails_closed() {
for (label, registration) in [
(
"string literal",
" reg.counter(\"cqlite.ghost\", catalog::unit::ROWS, \"g\");\n",
),
(
"local alias",
" reg.counter(GHOST_NAME, catalog::unit::ROWS, \"g\");\n",
),
(
"function call",
" reg.gauge(ghost_name(), catalog::unit::ROWS, \"g\");\n",
),
(
"method call on the constant",
" reg.counter(catalog::GHOST.trim_start_matches(\"cqlite.\"), u, \"g\");\n",
),
(
"concatenation",
" reg.counter(&[catalog::GHOST, \".v2\"].concat(), u, \"g\");\n",
),
] {
let src = strip_rust_comments(&synthetic_otel_source("", registration));
let Err(why) = parse_registrations(&src) else {
panic!("a {label} registration argument must fail closed");
};
assert!(
why.contains("not a\n `catalog::IDENT` constant")
|| why.contains("`catalog::IDENT` constant"),
"unexpected rejection reason for a {label}: {why}"
);
}
let literal_builder = strip_rust_comments(&synthetic_otel_source(
" let _ = meter().u64_counter(\"cqlite.ghost\").build();\n",
"",
));
let why = parse_builder_constructions(&literal_builder)
.expect_err("a string-literal builder argument must fail closed");
assert!(
why.contains("cannot classify"),
"unexpected rejection reason: {why}"
);
let alias_builder = strip_rust_comments(&synthetic_otel_source(
" let _ = meter().i64_gauge(GHOST_NAME).build();\n",
"",
));
assert!(parse_builder_constructions(&alias_builder).is_err());
let suffixed_builder = strip_rust_comments(&synthetic_otel_source(
" let _ = meter().u64_counter(catalog::GHOST.trim()).build();\n",
"",
));
assert!(
parse_builder_constructions(&suffixed_builder).is_err(),
"a method call on a catalog constant must not pass as that constant"
);
assert_eq!(
complete_catalog_ident("catalog::GHOST, u, \"g\");", &ARGUMENT_END),
Some("GHOST".to_string())
);
assert_eq!(
complete_catalog_ident("catalog::GHOST\n )", &ARGUMENT_END),
Some("GHOST".to_string())
);
assert_eq!(
complete_catalog_ident("catalog::GHOST.trim(), u", &ARGUMENT_END),
None
);
assert_eq!(
complete_catalog_ident("catalog::GHOST as &str, u", &ARGUMENT_END),
None
);
assert_eq!(
complete_catalog_ident("catalog::GHOST => x", &ARGUMENT_END),
None
);
assert_eq!(
complete_catalog_ident("catalog::GHOST | catalog::OTHER => x", &PATTERN_END),
Some("GHOST".to_string()),
"an arm ALTERNATIVE is still a hand-written arm"
);
let catalog_builder = strip_rust_comments(&synthetic_otel_source(
" let _ = meter().u64_counter(catalog::GHOST).build();\n",
"",
));
assert!(parse_builder_constructions(&catalog_builder)
.expect("a catalog-named builder call is classifiable")
.contains("GHOST"));
let clean = strip_rust_comments(&synthetic_otel_source("", ""));
assert_eq!(
parse_builder_constructions(&clean).expect("the exempt calls must classify"),
std::collections::BTreeSet::new()
);
assert_every_otel_source_is_scanned();
assert!(parse_builder_constructions(&otel_sources_uncommented())
.expect("the real otel sources must classify")
.is_empty());
}
#[test]
fn a_missing_resolver_reds_the_parse_instead_of_emptying_it() {
let no_gauge_resolver =
"fn counter_for() {\n i.counters.get(name)\n}\nfn histogram_for() {\n i.histograms.get(name)\n}\n";
let why = resolver_bodies(no_gauge_resolver)
.expect_err("a missing resolver must fail the parse, not quietly return nothing");
assert!(why.contains("fn gauge_for"), "unexpected reason: {why}");
assert!(handwritten_dispatch_arms(no_gauge_resolver).is_err());
assert!(
check_resolvers_have_no_handwritten_dispatch(no_gauge_resolver).is_err(),
"the guard must red on an unparseable resolver set, never pass vacuously"
);
let no_registrations = "fn counter_for() {}\n";
assert!(parse_registrations(no_registrations).is_err());
}
#[test]
fn the_real_otel_sources_register_wired_metrics_and_not_the_stats_only_ones() {
assert_every_otel_source_is_scanned();
let registered = otel_registered_instruments(&otel_sources_uncommented());
for wired in ["READ_ROWS", "READ_DURATION", "SSTABLES_OPEN"] {
assert!(
registered.contains(wired),
"catalog::{wired} is wired in the otel sources but the parser did not \
see it registered"
);
}
for stats_only in ["KEY_CACHE_HITS", "KEY_CACHE_CAPACITY_BYTES"] {
assert!(
!registered.contains(stats_only),
"catalog::{stats_only} is declared stats-only, so nothing may register it"
);
}
assert!(
registered.len() > 60,
"the registered set collapsed to {} entries — the parse is broken, and a \
shrunken subject set is a vacuous guard",
registered.len()
);
}