use crate::trace::{TraceSpanRecord, SCOUTER_EVAL_SCENARIO_ID_ATTR};
use crate::TraceId as ScouterTraceId;
use std::collections::{HashMap, HashSet};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::RwLock;
pub const CAPTURE_BUFFER_MAX: usize = 20_000;
pub static CAPTURING: AtomicBool = AtomicBool::new(false);
pub static CAPTURE_BUFFER: RwLock<Vec<TraceSpanRecord>> = RwLock::new(Vec::new());
pub fn is_capturing() -> bool {
CAPTURING.load(Ordering::Acquire)
}
pub fn drain_captured_spans() -> Vec<TraceSpanRecord> {
std::mem::take(&mut *CAPTURE_BUFFER.write().unwrap_or_else(|p| p.into_inner()))
}
pub fn get_captured_spans_by_trace_ids(
trace_ids: &HashSet<ScouterTraceId>,
) -> Vec<TraceSpanRecord> {
let buf = CAPTURE_BUFFER.read().unwrap_or_else(|p| p.into_inner());
buf.iter()
.filter(|span| trace_ids.contains(&span.trace_id))
.cloned()
.collect()
}
pub fn get_all_captured_spans() -> Vec<TraceSpanRecord> {
CAPTURE_BUFFER
.read()
.unwrap_or_else(|p| p.into_inner())
.clone()
}
pub fn get_spans_grouped_by_scenario_id(
scenario_ids: &HashSet<String>,
) -> HashMap<String, Vec<TraceSpanRecord>> {
let buf = CAPTURE_BUFFER.read().unwrap_or_else(|p| p.into_inner());
let mut trace_to_scenario: HashMap<ScouterTraceId, String> = HashMap::new();
for span in buf.iter() {
for attr in &span.attributes {
if attr.key == SCOUTER_EVAL_SCENARIO_ID_ATTR {
if let Some(sid) = attr.value.as_str() {
if scenario_ids.contains(sid) {
trace_to_scenario.insert(span.trace_id, sid.to_string());
}
}
break;
}
}
}
let mut grouped: HashMap<String, Vec<TraceSpanRecord>> = HashMap::new();
for span in buf.iter() {
if let Some(sid) = trace_to_scenario.get(&span.trace_id) {
grouped.entry(sid.clone()).or_default().push(span.clone());
}
}
grouped
}
pub fn get_trace_ids_by_scenario_ids(scenario_ids: &HashSet<String>) -> HashSet<ScouterTraceId> {
let buf = CAPTURE_BUFFER.read().unwrap_or_else(|p| p.into_inner());
buf.iter()
.filter(|span| {
span.attributes.iter().any(|attr| {
attr.key == SCOUTER_EVAL_SCENARIO_ID_ATTR
&& attr
.value
.as_str()
.map(|v| scenario_ids.contains(v))
.unwrap_or(false)
})
})
.map(|span| span.trace_id)
.collect()
}