use super::{GlobExpansion, GlobOutcome, GlobSkippedEntries};
use metrics::{counter, describe_counter};
use std::sync::Once;
const EXPANSIONS_TOTAL: &str = "netsuke_manifest_glob_expansions_total";
const ENTRIES_SKIPPED_TOTAL: &str = "netsuke_manifest_glob_entries_skipped_total";
const REDACTED_PATH: &str = "<redacted>";
fn describe_metrics() {
static DESCRIBE: Once = Once::new();
DESCRIBE.call_once(|| {
describe_counter!(
EXPANSIONS_TOTAL,
"Counts glob expansions labelled by outcome: matched, or \
unopenable_prefix when the pattern's literal directory prefix \
names no directory."
);
describe_counter!(
ENTRIES_SKIPPED_TOTAL,
"Counts matched entries dropped from a glob expansion, labelled \
by reason: unreachable_symlink for a link the capability cannot \
resolve, not_a_file for a directory or other non-file."
);
});
}
pub(super) fn record(expansion: &GlobExpansion) {
match &expansion.outcome {
GlobOutcome::Matched => record_expansion_matched(expansion),
GlobOutcome::UnopenablePrefix => record_unopenable_prefix(),
}
record_skipped_entries(&expansion.skipped);
}
fn record_unopenable_prefix() {
describe_metrics();
counter!(EXPANSIONS_TOTAL, "outcome" => "unopenable_prefix").increment(1);
tracing::debug!(
pattern = REDACTED_PATH,
prefix = REDACTED_PATH,
"glob literal prefix names no directory; expanding to no matches"
);
}
fn record_expansion_matched(expansion: &GlobExpansion) {
describe_metrics();
counter!(EXPANSIONS_TOTAL, "outcome" => "matched").increment(1);
tracing::debug!(
pattern = REDACTED_PATH,
matches = expansion.paths.len(),
"glob expansion complete"
);
}
fn record_skipped_entries(skipped: &GlobSkippedEntries) {
describe_metrics();
if skipped.unreachable_symlinks != 0 {
counter!(ENTRIES_SKIPPED_TOTAL, "reason" => "unreachable_symlink")
.increment(u64::try_from(skipped.unreachable_symlinks).unwrap_or(u64::MAX));
for _ in &skipped.unreachable_symlink_samples {
record_unreachable_symlink();
}
}
if skipped.not_a_file != 0 {
counter!(ENTRIES_SKIPPED_TOTAL, "reason" => "not_a_file")
.increment(u64::try_from(skipped.not_a_file).unwrap_or(u64::MAX));
}
}
fn record_unreachable_symlink() {
tracing::debug!(
relative = REDACTED_PATH,
"glob match traverses a symbolic link the capability cannot resolve; skipping"
);
}