use tracing::{info_span, warn, Span};
pub const OBSERVABILITY_FIELD_ALLOWLIST: &[&str] = &[
"run_id",
"plan_id",
"variant_id",
"fold_id",
"controller_id",
"phase",
"node_id",
"partition_id",
"cache_hit",
"oof_refused",
"category",
"code",
"violator_count",
];
pub fn phase_span(
run_id: &str,
plan_id: &str,
phase: &str,
variant_id: Option<&str>,
fold_id: Option<&str>,
) -> Span {
info_span!(
"dag_ml.phase",
run_id = run_id,
plan_id = plan_id,
phase = phase,
variant_id = variant_id.unwrap_or_default(),
fold_id = fold_id.unwrap_or_default(),
)
}
pub fn node_span(
run_id: &str,
plan_id: &str,
phase: &str,
node_id: &str,
controller_id: &str,
) -> Span {
info_span!(
"dag_ml.node",
run_id = run_id,
plan_id = plan_id,
phase = phase,
node_id = node_id,
controller_id = controller_id,
)
}
pub fn emit_oof_refusal(node_id: &str, violator_count: usize) {
warn!(
oof_refused = true,
category = "validation",
code = "oof_leakage",
node_id = node_id,
violator_count = violator_count,
"out-of-fold leakage refused"
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn allowlist_contains_no_data_bearing_field() {
for field in OBSERVABILITY_FIELD_ALLOWLIST {
for forbidden in ["data", "features", "targets", "sample", "metadata"] {
assert!(
!field.contains(forbidden),
"allowlisted field `{field}` leaks `{forbidden}`"
);
}
}
}
#[test]
fn helpers_emit_without_subscriber() {
let span = phase_span(
"run:1",
"plan:1",
"FIT_CV",
Some("variant:0"),
Some("fold:0"),
);
let _entered = span.entered();
let _node = node_span("run:1", "plan:1", "FIT_CV", "node:model", "controller:m").entered();
emit_oof_refusal("node:model", 2);
}
}