Skip to main content

scxtop/mcp/
event_buffer.rs

1// Copyright (c) Meta Platforms, Inc. and affiliates.
2//
3// This software may be used and distributed according to the terms of the
4// GNU General Public License version 2.
5
6use crate::Action;
7use serde_json::Value;
8use std::collections::VecDeque;
9use std::sync::{Arc, Mutex};
10use std::time::{SystemTime, UNIX_EPOCH};
11
12/// Maximum number of events to buffer
13const MAX_BUFFER_SIZE: usize = 100_000;
14
15/// Event with timestamp and metadata
16#[derive(Clone, Debug)]
17pub struct BufferedEvent {
18    pub timestamp: u64,
19    pub action: Action,
20    pub json: Value,
21}
22
23/// Ring buffer for storing recent events
24pub struct EventBuffer {
25    events: VecDeque<BufferedEvent>,
26    max_size: usize,
27    total_received: u64,
28    total_dropped: u64,
29    enabled: bool,
30}
31
32impl EventBuffer {
33    pub fn new() -> Self {
34        Self::with_capacity(MAX_BUFFER_SIZE)
35    }
36
37    pub fn with_capacity(capacity: usize) -> Self {
38        Self {
39            events: VecDeque::with_capacity(capacity),
40            max_size: capacity,
41            total_received: 0,
42            total_dropped: 0,
43            enabled: false, // Disabled by default to prevent overhead
44        }
45    }
46
47    /// Enable event collection
48    pub fn start(&mut self) {
49        self.enabled = true;
50    }
51
52    /// Disable event collection
53    pub fn stop(&mut self) {
54        self.enabled = false;
55    }
56
57    /// Check if buffer is actively collecting
58    pub fn is_enabled(&self) -> bool {
59        self.enabled
60    }
61
62    /// Clear all buffered events and reset statistics
63    pub fn reset(&mut self) {
64        self.events.clear();
65        self.total_received = 0;
66        self.total_dropped = 0;
67    }
68
69    /// Push a new event, dropping oldest if buffer is full
70    /// Returns true if event was recorded, false if buffer is disabled
71    pub fn push(&mut self, action: Action, json: Value) -> bool {
72        if !self.enabled {
73            return false;
74        }
75
76        self.total_received += 1;
77
78        let timestamp = SystemTime::now()
79            .duration_since(UNIX_EPOCH)
80            .unwrap()
81            .as_nanos() as u64;
82
83        let event = BufferedEvent {
84            timestamp,
85            action,
86            json,
87        };
88
89        if self.events.len() >= self.max_size {
90            self.events.pop_front();
91            self.total_dropped += 1;
92        }
93
94        self.events.push_back(event);
95        true
96    }
97
98    /// Get events in time range
99    pub fn get_events_in_range(&self, start_ts: u64, end_ts: u64) -> Vec<&BufferedEvent> {
100        self.events
101            .iter()
102            .filter(|e| e.timestamp >= start_ts && e.timestamp <= end_ts)
103            .collect()
104    }
105
106    /// Get last N events
107    pub fn get_last_n(&self, n: usize) -> Vec<&BufferedEvent> {
108        self.events.iter().rev().take(n).collect()
109    }
110
111    /// Get statistics about the buffer
112    pub fn stats(&self) -> EventBufferStats {
113        EventBufferStats {
114            enabled: self.enabled,
115            current_size: self.events.len(),
116            max_size: self.max_size,
117            total_received: self.total_received,
118            total_dropped: self.total_dropped,
119            oldest_timestamp: self.events.front().map(|e| e.timestamp),
120            newest_timestamp: self.events.back().map(|e| e.timestamp),
121        }
122    }
123
124    /// Clear all events
125    pub fn clear(&mut self) {
126        self.events.clear();
127    }
128}
129
130#[derive(Debug, Clone, serde::Serialize)]
131pub struct EventBufferStats {
132    pub enabled: bool,
133    pub current_size: usize,
134    pub max_size: usize,
135    pub total_received: u64,
136    pub total_dropped: u64,
137    pub oldest_timestamp: Option<u64>,
138    pub newest_timestamp: Option<u64>,
139}
140
141/// Shared event buffer
142pub type SharedEventBuffer = Arc<Mutex<EventBuffer>>;
143
144impl Default for EventBuffer {
145    fn default() -> Self {
146        Self::new()
147    }
148}