use super::*;
use crate::observability::otel_instruments::build_instruments;
use opentelemetry::metrics::MeterProvider as _;
use opentelemetry_sdk::metrics::SdkMeterProvider;
#[test]
fn init_disabled_returns_inert_guard() {
let cfg = ObservabilityConfig::builder().enabled(false).build();
let guard = init(cfg).expect("inert init never fails");
assert!(!guard.is_active());
guard.force_flush(); }
#[test]
fn sampler_builds_for_ratio() {
let _ = build_sampler(0.5);
let _ = build_sampler(2.0); }
#[test]
fn traceparent_none_empty_and_invalid_are_noops() {
let span = tracing::info_span!("test");
set_span_parent_from_traceparent(&span, None);
set_span_parent_from_traceparent(&span, Some(" "));
set_span_parent_from_traceparent(&span, Some("not-a-traceparent"));
}
#[test]
fn traceparent_valid_header_is_accepted() {
let span = tracing::info_span!("test");
let valid = "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01";
set_span_parent_from_traceparent(&span, Some(valid));
}
struct IsolatedInstruments {
_provider: SdkMeterProvider,
instruments: Instruments,
}
impl IsolatedInstruments {
fn build() -> Self {
let provider = SdkMeterProvider::builder().build();
let meter = provider.meter(SCOPE);
let instruments = build_instruments(&meter);
Self {
_provider: provider,
instruments,
}
}
fn resolved_kinds(&self, name: &str) -> usize {
let i = &self.instruments;
[
counter_for(i, name).is_some(),
histogram_for(i, name).is_some(),
gauge_for(i, name).is_some(),
]
.into_iter()
.filter(|resolved| *resolved)
.count()
}
}
#[test]
fn every_catalogued_metric_resolves_to_exactly_one_live_instrument_or_is_stats_only() {
let iso = IsolatedInstruments::build();
let stats_only: std::collections::HashSet<&str> =
catalog::STATS_ONLY_METRICS.iter().map(|m| m.name).collect();
let mut unresolved = Vec::new();
let mut ambiguous = Vec::new();
let mut stats_only_but_wired = Vec::new();
for name in catalog::ALL_METRICS {
let kinds = iso.resolved_kinds(name);
if stats_only.contains(name) {
if kinds != 0 {
stats_only_but_wired.push(*name);
}
continue;
}
match kinds {
0 => unresolved.push(*name),
1 => {}
_ => ambiguous.push(*name),
}
}
assert!(
unresolved.is_empty(),
"catalogued metrics resolve to NO live instrument (wire them in \
otel_instruments.rs + the matching resolver, or declare them in \
catalog::STATS_ONLY_METRICS with their reason): {unresolved:?}"
);
assert!(
ambiguous.is_empty(),
"catalogued metrics resolve to more than one instrument kind: {ambiguous:?}"
);
assert!(
stats_only_but_wired.is_empty(),
"metrics declared STATS_ONLY have a live instrument — delete the stale \
exemption: {stats_only_but_wired:?}"
);
}
#[test]
fn an_unregistered_name_resolves_to_no_instrument() {
let iso = IsolatedInstruments::build();
for bogus in [
"cqlite.definitely.not.a.metric",
"",
"cqlite.read.rows.but.longer",
"read.rows",
] {
assert_eq!(
iso.resolved_kinds(bogus),
0,
"{bogus:?} must not resolve to any dedicated instrument"
);
}
assert_eq!(iso.resolved_kinds(catalog::READ_ROWS), 1);
assert_eq!(iso.resolved_kinds(catalog::READ_DURATION), 1);
assert_eq!(iso.resolved_kinds(catalog::SSTABLES_OPEN), 1);
}
#[test]
fn every_live_instrument_is_catalogued_and_resolves_only_as_its_own_kind() {
let iso = IsolatedInstruments::build();
let i = &iso.instruments;
let catalogued: std::collections::HashSet<&str> =
catalog::ALL_METRICS.iter().copied().collect();
let live: Vec<(&str, &str)> = i
.counters
.keys()
.map(|n| ("counter", *n))
.chain(i.histograms.keys().map(|n| ("histogram", *n)))
.chain(i.gauges.keys().map(|n| ("gauge", *n)))
.collect();
let uncatalogued: Vec<&(&str, &str)> = live
.iter()
.filter(|(_, name)| !catalogued.contains(name))
.collect();
assert!(
uncatalogued.is_empty(),
"live instruments exist for metrics ABSENT from ALL_METRICS: {uncatalogued:?}"
);
for (kind, name) in &live {
assert_eq!(
iso.resolved_kinds(name),
1,
"{name} (registered as a {kind}) must resolve as exactly one kind"
);
}
let stats_only: std::collections::HashSet<&str> =
catalog::STATS_ONLY_METRICS.iter().map(|m| m.name).collect();
let expected = catalog::ALL_METRICS
.iter()
.filter(|name| !stats_only.contains(*name))
.count();
assert_eq!(
live.len(),
expected,
"the live instrument set must be exactly the catalogued metrics that are not \
declared STATS_ONLY"
);
}
#[cfg(feature = "observability-testing")]
#[test]
fn a_stats_only_name_cannot_create_an_instrument_through_the_emit_path() {
use opentelemetry_sdk::metrics::{InMemoryMetricExporterBuilder, PeriodicReader};
const UNKNOWN_COUNTER: &str = "cqlite.test.uncatalogued.counter";
const UNKNOWN_HISTOGRAM: &str = "cqlite.test.uncatalogued.histogram";
const UNKNOWN_GAUGE: &str = "cqlite.test.uncatalogued.gauge";
let exporter = InMemoryMetricExporterBuilder::new().build();
let reader = PeriodicReader::builder(exporter.clone()).build();
let provider = SdkMeterProvider::builder().with_reader(reader).build();
let meter = provider.meter(SCOPE);
let instruments = build_instruments(&meter);
assert!(
!catalog::STATS_ONLY_METRICS.is_empty(),
"no stats-only metric is declared, so this guard would assert nothing"
);
for m in catalog::STATS_ONLY_METRICS {
add_counter_with(&instruments, &meter, m.name, 1, &[]);
record_histogram_with(&instruments, &meter, m.name, 1.0, &[]);
record_gauge_with(&instruments, &meter, m.name, 1, &[]);
}
add_counter_with(&instruments, &meter, UNKNOWN_COUNTER, 1, &[]);
record_histogram_with(&instruments, &meter, UNKNOWN_HISTOGRAM, 1.0, &[]);
record_gauge_with(&instruments, &meter, UNKNOWN_GAUGE, 1, &[]);
let _ = provider.force_flush();
let collected = exporter
.get_finished_metrics()
.expect("the in-memory exporter must yield collected metrics");
let scraped: std::collections::HashSet<String> = collected
.iter()
.flat_map(|rm| rm.scope_metrics())
.flat_map(|sm| sm.metrics())
.map(|m| m.name().to_string())
.collect();
for control in [UNKNOWN_COUNTER, UNKNOWN_HISTOGRAM, UNKNOWN_GAUGE] {
assert!(
scraped.contains(control),
"{control} was emitted through the ad-hoc fallback and must be on the \
scrape; its absence means this guard measures nothing (collected: \
{scraped:?})"
);
}
let scrapeable: Vec<&str> = catalog::STATS_ONLY_METRICS
.iter()
.map(|m| m.name)
.filter(|name| scraped.contains(*name))
.collect();
assert!(
scrapeable.is_empty(),
"metrics declared STATS_ONLY reached a scrape through the emit path — the \
ad-hoc fallback must refuse to build an instrument for them: {scrapeable:?}"
);
}