memscope_rs/unified/strategies/
hybrid_strategy.rs1use crate::unified::strategies::{AsyncStrategy, ThreadLocalStrategy};
6use crate::unified::tracking_dispatcher::{
7 MemoryTracker, TrackerConfig, TrackerError, TrackerStatistics, TrackerType,
8};
9use tracing::{debug, info};
10
11pub struct HybridStrategy {
15 thread_tracker: ThreadLocalStrategy,
17 async_tracker: AsyncStrategy,
19 config: Option<TrackerConfig>,
21 coordination_state: HybridCoordinationState,
23}
24
25#[derive(Debug, Clone)]
28struct HybridCoordinationState {
29 is_active: bool,
31 _primary_mode: TrackingMode,
33 _fallback_mode: TrackingMode,
35}
36
37#[derive(Debug, Clone, PartialEq)]
39enum TrackingMode {
40 DualMode,
42 Adaptive,
44}
45
46impl Default for HybridCoordinationState {
47 fn default() -> Self {
49 Self {
50 is_active: false,
51 _primary_mode: TrackingMode::Adaptive,
52 _fallback_mode: TrackingMode::DualMode,
53 }
54 }
55}
56
57impl HybridStrategy {
58 pub fn new() -> Self {
60 debug!("Creating new hybrid strategy");
61
62 Self {
63 thread_tracker: ThreadLocalStrategy::new(),
64 async_tracker: AsyncStrategy::new(),
65 config: None,
66 coordination_state: HybridCoordinationState::default(),
67 }
68 }
69}
70
71impl MemoryTracker for HybridStrategy {
72 fn initialize(&mut self, config: TrackerConfig) -> Result<(), TrackerError> {
74 debug!("Initializing hybrid strategy with config: {:?}", config);
75
76 self.thread_tracker.initialize(config.clone())?;
78 self.async_tracker.initialize(config.clone())?;
79
80 self.config = Some(config);
81
82 info!("Hybrid strategy initialized successfully");
83 Ok(())
84 }
85
86 fn start_tracking(&mut self) -> Result<(), TrackerError> {
88 debug!("Starting hybrid tracking");
89
90 self.thread_tracker.start_tracking()?;
92 self.async_tracker.start_tracking()?;
93
94 self.coordination_state.is_active = true;
95
96 info!("Hybrid tracking started successfully");
97 Ok(())
98 }
99
100 fn stop_tracking(&mut self) -> Result<Vec<u8>, TrackerError> {
102 debug!("Stopping hybrid tracking");
103
104 let thread_data = self.thread_tracker.stop_tracking()?;
106 let async_data = self.async_tracker.stop_tracking()?;
107
108 let thread_json: serde_json::Value = serde_json::from_slice(&thread_data)?;
110 let async_json: serde_json::Value = serde_json::from_slice(&async_data)?;
111
112 let mut merged = serde_json::Map::new();
113 merged.insert("thread_data".to_string(), thread_json);
114 merged.insert("async_data".to_string(), async_json);
115 merged.insert(
116 "strategy_type".to_string(),
117 serde_json::Value::String("hybrid".to_string()),
118 );
119
120 let merged_json = serde_json::to_string_pretty(&merged).map_err(|e| {
121 TrackerError::DataCollectionFailed {
122 reason: format!("Failed to merge hybrid data: {e}"),
123 }
124 })?;
125
126 self.coordination_state.is_active = false;
127
128 info!("Hybrid tracking stopped and data merged");
129 Ok(merged_json.into_bytes())
130 }
131
132 fn get_statistics(&self) -> TrackerStatistics {
134 let thread_stats = self.thread_tracker.get_statistics();
135 let async_stats = self.async_tracker.get_statistics();
136
137 TrackerStatistics {
138 allocations_tracked: thread_stats.allocations_tracked + async_stats.allocations_tracked,
139 memory_tracked_bytes: thread_stats.memory_tracked_bytes
140 + async_stats.memory_tracked_bytes,
141 overhead_bytes: thread_stats.overhead_bytes + async_stats.overhead_bytes,
142 tracking_duration_ms: thread_stats
143 .tracking_duration_ms
144 .max(async_stats.tracking_duration_ms),
145 }
146 }
147
148 fn is_active(&self) -> bool {
150 self.coordination_state.is_active
151 && (self.thread_tracker.is_active() || self.async_tracker.is_active())
152 }
153
154 fn tracker_type(&self) -> TrackerType {
156 TrackerType::HybridTracker
157 }
158}
159
160impl Default for HybridStrategy {
161 fn default() -> Self {
162 Self::new()
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[test]
171 fn test_hybrid_strategy_creation() {
172 let strategy = HybridStrategy::new();
173 assert!(!strategy.is_active());
174 assert_eq!(strategy.tracker_type(), TrackerType::HybridTracker);
175 }
176
177 #[test]
178 fn test_hybrid_initialization() {
179 let mut strategy = HybridStrategy::new();
180 let config = TrackerConfig::default();
181
182 let result = strategy.initialize(config);
183 assert!(result.is_ok());
184 }
185
186 #[test]
187 fn test_hybrid_tracking_lifecycle() {
188 let mut strategy = HybridStrategy::new();
189 strategy.initialize(TrackerConfig::default()).unwrap();
190
191 assert!(strategy.start_tracking().is_ok());
193 assert!(strategy.is_active());
194
195 let data = strategy.stop_tracking();
197 assert!(data.is_ok());
198 assert!(!strategy.is_active());
199 }
200}