use parking_lot::Mutex;
use std::sync::OnceLock;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkerCensusEntry {
pub resource: &'static str,
pub kind: &'static str,
pub count: usize,
pub thread_name: &'static str,
pub sizing: &'static str,
pub binding: &'static str,
}
static CENSUS: OnceLock<Mutex<Vec<WorkerCensusEntry>>> = OnceLock::new();
static BOOT_DUMPED: OnceLock<()> = OnceLock::new();
static EXPORT_HOOK: OnceLock<fn(&[WorkerCensusEntry])> = OnceLock::new();
pub fn set_export_hook(hook: fn(&[WorkerCensusEntry])) {
let _ = EXPORT_HOOK.set(hook);
}
pub fn emit_boot_table() {
let table = snapshot();
BOOT_DUMPED.get_or_init(|| {
crate::op_info!(domain = pump, entries = ?table,
"boot table full",
);
});
}
fn table_cell() -> &'static Mutex<Vec<WorkerCensusEntry>> {
CENSUS.get_or_init(|| Mutex::new(Vec::new()))
}
pub fn register(entry: WorkerCensusEntry) {
let late = BOOT_DUMPED.get().is_some();
let announced = (entry.resource, entry.count, entry.thread_name, entry.sizing);
{
let mut table = table_cell().lock();
match table.iter_mut().find(|e| e.resource == entry.resource) {
Some(slot) => *slot = entry,
None => table.push(entry),
}
table.sort_by(|a, b| a.resource.cmp(b.resource));
}
if late {
crate::op_info!(
domain = pump,
resource = announced.0,
count = announced.1,
thread_name = announced.2,
sizing = announced.3,
"registered after boot dump — new spawn site must register",
);
}
if let Some(hook) = EXPORT_HOOK.get() {
hook(&snapshot());
}
}
#[must_use]
pub fn snapshot() -> Vec<WorkerCensusEntry> {
table_cell().lock().clone()
}
#[cfg(test)]
#[expect(clippy::unwrap_used, clippy::expect_used)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicUsize, Ordering};
fn probe(n: usize, name: &str) -> WorkerCensusEntry {
WorkerCensusEntry {
resource: Box::leak(format!("census-probe-{n}").into_boxed_str()),
kind: "test resource",
count: n + 1,
thread_name: Box::leak(name.to_string().into_boxed_str()),
sizing: "test sizing rule",
binding: "logical",
}
}
#[test]
fn register_upserts_by_resource_and_snapshot_is_sorted() {
let a = probe(1, "census-probe-a-{n}");
let b = probe(2, "census-probe-b-{n}");
register(a.clone());
let mut updated = a.clone();
updated.count = 7;
register(updated.clone());
register(b);
let snap = snapshot();
let ra = snap
.iter()
.find(|e| e.resource == "census-probe-1")
.expect("probe-1 registered");
assert_eq!(
ra.count, 7,
"re-registering an id must UPSERT, not duplicate"
);
assert_eq!(
snap.iter()
.filter(|e| e.resource == "census-probe-1")
.count(),
1,
"duplicate ids must not double-count in the census"
);
let rb = snap
.iter()
.find(|e| e.resource == "census-probe-2")
.expect("probe-2 registered");
let idx = |id: &str| snap.iter().position(|e| e.resource == id).unwrap();
assert!(
idx("census-probe-1") < idx("census-probe-2"),
"snapshot must be sorted by resource id"
);
assert_eq!(ra.thread_name, "census-probe-a-{n}");
assert_eq!(rb.count, 3);
}
#[test]
fn export_hook_fires_on_registration_with_full_snapshot() {
static FIRES: AtomicUsize = AtomicUsize::new(0);
static LAST_LEN: AtomicUsize = AtomicUsize::new(0);
fn counting_hook(entries: &[WorkerCensusEntry]) {
FIRES.fetch_add(1, Ordering::SeqCst);
LAST_LEN.store(entries.len(), Ordering::SeqCst);
}
set_export_hook(counting_hook);
let before = FIRES.load(Ordering::SeqCst);
register(probe(3, "census-probe-hook"));
assert!(
FIRES.load(Ordering::SeqCst) > before,
"each registration must re-fire the export hook"
);
let len = LAST_LEN.load(Ordering::SeqCst);
assert!(
len >= 1,
"hook must receive the FULL snapshot, not the entry"
);
assert!(
snapshot().iter().any(|e| e.resource == "census-probe-3"),
"hook-fired snapshot must contain the new resource"
);
}
struct RecordingSubscriber(std::sync::Mutex<String>);
struct LogLineVisitor<'a>(&'a mut String);
impl tracing_core::field::Visit for LogLineVisitor<'_> {
fn record_debug(
&mut self,
field: &tracing_core::field::Field,
value: &dyn std::fmt::Debug,
) {
std::fmt::write(self.0, format_args!("{}={:?} ", field.name(), value)).ok();
}
}
impl tracing_core::Subscriber for RecordingSubscriber {
fn enabled(&self, _: &tracing_core::Metadata<'_>) -> bool {
true
}
fn new_span(&self, _: &tracing_core::span::Attributes<'_>) -> tracing_core::span::Id {
tracing_core::span::Id::from_u64(1)
}
fn record(&self, _: &tracing_core::span::Id, _: &tracing_core::span::Record<'_>) {}
fn enter(&self, _: &tracing_core::span::Id) {}
fn exit(&self, _: &tracing_core::span::Id) {}
fn record_follows_from(&self, _: &tracing_core::span::Id, _: &tracing_core::span::Id) {}
fn event(&self, event: &tracing_core::event::Event<'_>) {
let mut buf = String::new();
event.record(&mut LogLineVisitor(&mut buf));
if let Ok(mut s) = self.0.lock() {
s.push_str(&buf);
}
}
}
#[test]
fn boot_table_emits_one_info_line_with_the_full_table() {
register(probe(4, "census-probe-boot"));
let rec = std::sync::Arc::new(RecordingSubscriber(std::sync::Mutex::new(String::new())));
let sunk = std::sync::Arc::clone(&rec);
tracing::subscriber::with_default(sunk, emit_boot_table);
let logged = rec.0.lock().unwrap().clone();
assert!(
!logged.contains("[worker-census]"),
"tag left in message: {logged}"
);
assert!(
logged.contains("census-probe-boot"),
"boot table missing the registered resource: {logged}"
);
}
#[test]
fn comm_histogram_census_matches_registry() {
const THREAD_NAME: &str = "census-comm-probe";
const COMM_MAX: usize = 15;
register(WorkerCensusEntry {
resource: Box::leak("census-probe-comm".to_string().into_boxed_str()),
kind: "comm-probe threads",
count: 3,
thread_name: THREAD_NAME,
sizing: "test: exactly 3 threads",
binding: "pinned",
});
let deadline = std::time::Duration::from_secs(5);
let poll = std::time::Duration::from_millis(50);
let start = std::time::Instant::now();
std::thread::scope(|s| {
let parked = std::sync::Arc::new(std::sync::Barrier::new(4));
for _ in 0..3 {
let parked = std::sync::Arc::clone(&parked);
std::thread::Builder::new()
.name(THREAD_NAME.to_string())
.spawn_scoped(s, move || {
parked.wait();
parked.wait();
})
.expect("comm-probe thread spawn");
}
parked.wait();
let comm = &THREAD_NAME[..THREAD_NAME.len().min(COMM_MAX)];
let histogram = loop {
let mut h = std::collections::BTreeMap::new();
for task in std::fs::read_dir("/proc/self/task")
.expect("task dir is present on linux")
.flatten()
{
if let Ok(comm) = std::fs::read_to_string(task.path().join("comm")) {
*h.entry(comm.trim().to_string()).or_insert(0_u64) += 1;
}
}
if h.get(comm) == Some(&3) {
break h;
}
assert!(
start.elapsed() <= deadline,
"live /proc comm histogram must census-match the registry: {h:?}"
);
std::thread::sleep(poll);
};
parked.wait();
assert_eq!(
histogram.get(comm),
Some(&3),
"live /proc comm histogram must census-match the registry: {histogram:?}"
);
});
}
}