Skip to main content

seyk_embed/
diagnostics.rs

1//! Opt-in, content-free phase markers for external memory samplers.
2//! Set SEYK_MEMORY_DIAGNOSTICS=1 before process startup. No source content,
3//! token IDs, paths, errors or vectors are emitted.
4use std::io::Write;
5use std::sync::OnceLock;
6use std::time::Instant;
7
8fn enabled() -> bool {
9    static ENABLED: OnceLock<bool> = OnceLock::new();
10    *ENABLED.get_or_init(|| std::env::var_os("SEYK_MEMORY_DIAGNOSTICS").is_some_and(|v| v == "1"))
11}
12
13fn marker(event: &'static str, state: &'static str, counts: &[(&'static str, usize)]) {
14    if !enabled() {
15        return;
16    }
17    static START: OnceLock<Instant> = OnceLock::new();
18    let elapsed = START.get_or_init(Instant::now).elapsed().as_micros();
19    let mut line = format!(
20        "seyk_memory pid={} t_us={elapsed} event={event} state={state}",
21        std::process::id()
22    );
23    for (key, value) in counts {
24        use std::fmt::Write;
25        // Writing to a String cannot fail.
26        write!(line, " {key}={value}").expect("format diagnostic counts");
27    }
28    // Diagnostics must not change retrieval behavior on a closed stderr pipe.
29    let _ = writeln!(std::io::stderr().lock(), "{line}");
30}
31
32/// Emit numeric workload metadata; names must be static program constants.
33pub fn counts(event: &'static str, values: &[(&'static str, usize)]) {
34    marker(event, "count", values);
35}
36
37/// A phase emits paired begin/end markers, including early error returns.
38pub struct Phase(&'static str);
39impl Phase {
40    pub fn new(event: &'static str) -> Self {
41        marker(event, "begin", &[]);
42        Self(event)
43    }
44}
45impl Drop for Phase {
46    fn drop(&mut self) {
47        marker(self.0, "end", &[]);
48    }
49}