use crate::tracing::{TraceEvent, TraceSignificance};
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CircularTraceBuffer {
events: VecDeque<TraceEvent>,
capacity: usize,
total_events: u64,
evicted_count: u64,
}
impl CircularTraceBuffer {
#[must_use]
pub fn new() -> Self {
Self::with_capacity(1024)
}
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self {
events: VecDeque::with_capacity(capacity),
capacity,
total_events: 0,
evicted_count: 0,
}
}
pub fn push(&mut self, event: TraceEvent) {
if self.events.len() == self.capacity {
self.events.pop_front(); self.evicted_count += 1;
}
self.events.push_back(event);
self.total_events += 1;
}
#[must_use]
pub fn len(&self) -> usize {
self.events.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.events.is_empty()
}
#[must_use]
pub const fn capacity(&self) -> usize {
self.capacity
}
#[must_use]
pub const fn total_events(&self) -> u64 {
self.total_events
}
#[must_use]
pub const fn evicted_count(&self) -> u64 {
self.evicted_count
}
#[must_use]
pub fn retention_rate(&self) -> f64 {
if self.total_events == 0 {
return 1.0;
}
(self.total_events - self.evicted_count) as f64 / self.total_events as f64
}
pub fn iter(&self) -> impl Iterator<Item = &TraceEvent> {
self.events.iter()
}
pub fn iter_filtered(
&self,
min_significance: TraceSignificance,
) -> impl Iterator<Item = &TraceEvent> + '_ {
self.events
.iter()
.filter(move |e| e.significance() >= min_significance)
}
pub fn clear(&mut self) {
self.events.clear();
self.total_events = 0;
self.evicted_count = 0;
}
#[must_use]
pub fn utilization(&self) -> f64 {
self.events.len() as f64 / self.capacity as f64
}
#[must_use]
pub fn is_full(&self) -> bool {
self.events.len() == self.capacity
}
#[must_use]
pub fn stats(&self) -> BufferStats {
BufferStats {
capacity: self.capacity,
current_size: self.events.len(),
total_events: self.total_events,
evicted_count: self.evicted_count,
retention_rate: self.retention_rate(),
utilization: self.utilization(),
}
}
}
impl Default for CircularTraceBuffer {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BufferStats {
pub capacity: usize,
pub current_size: usize,
pub total_events: u64,
pub evicted_count: u64,
pub retention_rate: f64,
pub utilization: f64,
}
#[cfg(test)]
#[path = "buffer_tests_trace_002.rs"]
mod tests_extracted;