memscope_rs/core/tracker/
tracking_manager.rs

1//! Unified tracking manager interface.
2//!
3//! This module provides a unified interface that combines memory tracking and scope tracking
4//! while preserving all existing functionality.
5
6use super::memory_tracker::{get_tracker, MemoryTracker};
7use crate::core::types::{
8    AllocationInfo, MemoryStats, ScopeAnalysis, ScopeLifecycleMetrics, TrackingResult,
9};
10use std::sync::Arc;
11
12/// Unified tracking manager that combines memory and scope tracking
13/// This provides a unified interface that combines memory tracking and scope tracking
14/// while preserving all existing functionality.
15pub struct TrackingManager {
16    memory_tracker: Arc<MemoryTracker>,
17    scope_tracker: Arc<crate::core::scope_tracker::ScopeTracker>,
18}
19
20impl TrackingManager {
21    /// Create a new tracking manager instance
22    pub fn new() -> Self {
23        Self {
24            memory_tracker: get_tracker(),
25            scope_tracker: crate::core::scope_tracker::get_global_scope_tracker(),
26        }
27    }
28
29    /// Get the memory tracker instance
30    pub fn memory_tracker(&self) -> &Arc<MemoryTracker> {
31        &self.memory_tracker
32    }
33
34    /// Get the scope tracker instance
35    pub fn scope_tracker(&self) -> &Arc<crate::core::scope_tracker::ScopeTracker> {
36        &self.scope_tracker
37    }
38
39    /// Track memory allocation
40    pub fn track_allocation(&self, ptr: usize, size: usize) -> TrackingResult<()> {
41        self.memory_tracker.track_allocation(ptr, size)
42    }
43
44    /// Track memory deallocation
45    pub fn track_deallocation(&self, ptr: usize) -> TrackingResult<()> {
46        self.memory_tracker.track_deallocation(ptr)
47    }
48
49    /// Associate variable with memory allocation
50    pub fn associate_var(
51        &self,
52        ptr: usize,
53        var_name: String,
54        type_name: String,
55    ) -> TrackingResult<()> {
56        self.memory_tracker.associate_var(ptr, var_name, type_name)
57    }
58
59    /// Enter a new scope
60    pub fn enter_scope(&self, name: String) -> TrackingResult<crate::core::scope_tracker::ScopeId> {
61        self.scope_tracker.enter_scope(name)
62    }
63
64    /// Exit a scope
65    pub fn exit_scope(&self, scope_id: crate::core::scope_tracker::ScopeId) -> TrackingResult<()> {
66        self.scope_tracker.exit_scope(scope_id)
67    }
68
69    /// Associate variable with current scope
70    pub fn associate_variable(
71        &self,
72        variable_name: String,
73        memory_size: usize,
74    ) -> TrackingResult<()> {
75        self.scope_tracker
76            .associate_variable(variable_name, memory_size)
77    }
78
79    /// Get memory statistics
80    pub fn get_stats(&self) -> TrackingResult<MemoryStats> {
81        self.memory_tracker.get_stats()
82    }
83
84    /// Get active allocations
85    pub fn get_active_allocations(&self) -> TrackingResult<Vec<AllocationInfo>> {
86        self.memory_tracker.get_active_allocations()
87    }
88
89    /// Get allocation history
90    pub fn get_allocation_history(&self) -> TrackingResult<Vec<AllocationInfo>> {
91        self.memory_tracker.get_allocation_history()
92    }
93
94    /// Get scope analysis
95    pub fn get_scope_analysis(&self) -> TrackingResult<ScopeAnalysis> {
96        self.scope_tracker.get_scope_analysis()
97    }
98
99    /// Perform comprehensive tracking analysis
100    pub fn perform_comprehensive_analysis(&self) -> TrackingResult<ComprehensiveTrackingReport> {
101        let memory_stats = self.get_stats()?;
102        let active_allocations = self.get_active_allocations()?;
103        let allocation_history = self.get_allocation_history()?;
104        let scope_analysis = self.get_scope_analysis()?;
105        let scope_metrics = self.scope_tracker.get_scope_lifecycle_metrics()?;
106
107        Ok(ComprehensiveTrackingReport {
108            memory_stats,
109            active_allocations,
110            allocation_history,
111            scope_analysis,
112            scope_metrics,
113            analysis_timestamp: std::time::SystemTime::now()
114                .duration_since(std::time::UNIX_EPOCH)
115                .unwrap_or_default()
116                .as_secs(),
117        })
118    }
119}
120
121impl Default for TrackingManager {
122    fn default() -> Self {
123        Self::new()
124    }
125}
126
127/// Comprehensive tracking report
128#[derive(Debug, Clone)]
129pub struct ComprehensiveTrackingReport {
130    /// Overall memory statistics
131    pub memory_stats: MemoryStats,
132    /// Currently active memory allocations
133    pub active_allocations: Vec<AllocationInfo>,
134    /// Historical allocation data
135    pub allocation_history: Vec<AllocationInfo>,
136    /// Scope analysis results
137    pub scope_analysis: ScopeAnalysis,
138    /// Scope lifecycle metrics
139    pub scope_metrics: Vec<ScopeLifecycleMetrics>,
140    /// Timestamp when report was generated
141    pub analysis_timestamp: u64,
142}
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147
148    #[test]
149    fn test_tracking_manager_creation() {
150        // Test that TrackingManager can be created
151        let manager = TrackingManager::new();
152
153        // Verify it has the expected components
154        let _memory_tracker = manager.memory_tracker();
155        let _scope_tracker = manager.scope_tracker();
156
157        // If we get here without panicking, creation was successful
158    }
159
160    #[test]
161    fn test_tracking_manager_default() {
162        // Test that Default trait works
163        let manager = TrackingManager::default();
164
165        // Should be equivalent to new()
166        let _memory_tracker = manager.memory_tracker();
167        let _scope_tracker = manager.scope_tracker();
168    }
169
170    #[test]
171    fn test_comprehensive_tracking_report_structure() {
172        // Test the ComprehensiveTrackingReport structure
173        use crate::core::types::{
174            ConcurrencyAnalysis, FragmentationAnalysis, MemoryStats, ScopeAnalysis, ScopeHierarchy,
175            ScopeLifecycleMetrics, SystemLibraryStats,
176        };
177
178        let report = ComprehensiveTrackingReport {
179            memory_stats: MemoryStats {
180                total_allocations: 10,
181                total_allocated: 1024,
182                active_allocations: 5,
183                active_memory: 512,
184                peak_allocations: 8,
185                peak_memory: 800,
186                total_deallocations: 5,
187                total_deallocated: 512,
188                leaked_allocations: 0,
189                leaked_memory: 0,
190                fragmentation_analysis: FragmentationAnalysis::default(),
191                lifecycle_stats: ScopeLifecycleMetrics::default(),
192                allocations: vec![],
193                system_library_stats: SystemLibraryStats::default(),
194                concurrency_analysis: ConcurrencyAnalysis::default(),
195            },
196            active_allocations: vec![],
197            allocation_history: vec![],
198            scope_analysis: ScopeAnalysis {
199                total_scopes: 3,
200                active_scopes: 1,
201                max_depth: 2,
202                average_lifetime: 0.0,
203                memory_efficiency: 0.0,
204                scopes: vec![],
205                scope_hierarchy: ScopeHierarchy::default(),
206                cross_scope_references: vec![],
207            },
208            scope_metrics: vec![],
209            analysis_timestamp: 1234567890,
210        };
211
212        // Test that the report can be created and accessed
213        assert_eq!(report.memory_stats.total_allocations, 10);
214        assert_eq!(report.memory_stats.active_allocations, 5);
215        assert_eq!(report.scope_analysis.total_scopes, 3);
216        assert_eq!(report.analysis_timestamp, 1234567890);
217    }
218
219    #[test]
220    fn test_comprehensive_tracking_report_clone() {
221        // Test that ComprehensiveTrackingReport can be cloned
222        use crate::core::types::{
223            ConcurrencyAnalysis, FragmentationAnalysis, MemoryStats, ScopeAnalysis, ScopeHierarchy,
224            ScopeLifecycleMetrics, SystemLibraryStats,
225        };
226
227        let original = ComprehensiveTrackingReport {
228            memory_stats: MemoryStats {
229                total_allocations: 5,
230                total_allocated: 500,
231                active_allocations: 3,
232                active_memory: 300,
233                peak_allocations: 4,
234                peak_memory: 400,
235                total_deallocations: 2,
236                total_deallocated: 200,
237                leaked_allocations: 0,
238                leaked_memory: 0,
239                fragmentation_analysis: FragmentationAnalysis::default(),
240                lifecycle_stats: ScopeLifecycleMetrics::default(),
241                allocations: vec![],
242                system_library_stats: SystemLibraryStats::default(),
243                concurrency_analysis: ConcurrencyAnalysis::default(),
244            },
245            active_allocations: vec![],
246            allocation_history: vec![],
247            scope_analysis: ScopeAnalysis {
248                total_scopes: 2,
249                active_scopes: 1,
250                max_depth: 1,
251                average_lifetime: 0.0,
252                memory_efficiency: 0.0,
253                scopes: vec![],
254                scope_hierarchy: ScopeHierarchy::default(),
255                cross_scope_references: vec![],
256            },
257            scope_metrics: vec![],
258            analysis_timestamp: 9876543210,
259        };
260
261        let cloned = original.clone();
262
263        // Verify clone has same values
264        assert_eq!(
265            original.memory_stats.total_allocations,
266            cloned.memory_stats.total_allocations
267        );
268        assert_eq!(
269            original.scope_analysis.total_scopes,
270            cloned.scope_analysis.total_scopes
271        );
272        assert_eq!(original.analysis_timestamp, cloned.analysis_timestamp);
273    }
274
275    #[test]
276    fn test_comprehensive_tracking_report_debug() {
277        // Test that ComprehensiveTrackingReport implements Debug
278        use crate::core::types::{
279            ConcurrencyAnalysis, FragmentationAnalysis, MemoryStats, ScopeAnalysis, ScopeHierarchy,
280            ScopeLifecycleMetrics, SystemLibraryStats,
281        };
282
283        let report = ComprehensiveTrackingReport {
284            memory_stats: MemoryStats {
285                total_allocations: 1,
286                total_allocated: 100,
287                active_allocations: 1,
288                active_memory: 100,
289                peak_allocations: 1,
290                peak_memory: 100,
291                total_deallocations: 0,
292                total_deallocated: 0,
293                leaked_allocations: 0,
294                leaked_memory: 0,
295                fragmentation_analysis: FragmentationAnalysis::default(),
296                lifecycle_stats: ScopeLifecycleMetrics::default(),
297                allocations: vec![],
298                system_library_stats: SystemLibraryStats::default(),
299                concurrency_analysis: ConcurrencyAnalysis::default(),
300            },
301            active_allocations: vec![],
302            allocation_history: vec![],
303            scope_analysis: ScopeAnalysis {
304                total_scopes: 1,
305                active_scopes: 1,
306                max_depth: 1,
307                average_lifetime: 0.0,
308                memory_efficiency: 0.0,
309                scopes: vec![],
310                scope_hierarchy: ScopeHierarchy::default(),
311                cross_scope_references: vec![],
312            },
313            scope_metrics: vec![],
314            analysis_timestamp: 1111111111,
315        };
316
317        let debug_str = format!("{report:?}");
318
319        // Should contain key information
320        assert!(debug_str.contains("ComprehensiveTrackingReport"));
321        assert!(debug_str.contains("memory_stats"));
322        assert!(debug_str.contains("scope_analysis"));
323        assert!(debug_str.contains("analysis_timestamp"));
324    }
325
326    #[test]
327    fn test_tracking_manager_method_signatures() {
328        // Test that all TrackingManager methods have correct signatures
329        let manager = TrackingManager::new();
330
331        // Test memory_tracker method
332        let _memory_tracker: &Arc<MemoryTracker> = manager.memory_tracker();
333
334        // Test scope_tracker method
335        let _scope_tracker: &Arc<crate::core::scope_tracker::ScopeTracker> =
336            manager.scope_tracker();
337
338        // Test method signatures without actually calling them (to avoid global state issues)
339        // We just verify the methods exist and have correct types
340
341        // These would normally be tested, but we avoid calling them due to global state:
342        // let _: TrackingResult<()> = manager.track_allocation(0x1000, 1024);
343        // let _: TrackingResult<()> = manager.track_deallocation(0x1000);
344        // let _: TrackingResult<()> = manager.associate_var(0x1000, "var".to_string(), "type".to_string());
345        // let _: TrackingResult<crate::core::scope_tracker::ScopeId> = manager.enter_scope("scope".to_string());
346        // let _: TrackingResult<()> = manager.exit_scope(1);
347        // let _: TrackingResult<()> = manager.associate_variable("var".to_string(), 1024);
348        // let _: TrackingResult<MemoryStats> = manager.get_stats();
349        // let _: TrackingResult<Vec<AllocationInfo>> = manager.get_active_allocations();
350        // let _: TrackingResult<Vec<AllocationInfo>> = manager.get_allocation_history();
351        // let _: TrackingResult<ScopeAnalysis> = manager.get_scope_analysis();
352        // let _: TrackingResult<ComprehensiveTrackingReport> = manager.perform_comprehensive_analysis();
353    }
354
355    #[test]
356    fn test_tracking_manager_component_access() {
357        // Test that we can access the internal components
358        let manager = TrackingManager::new();
359
360        // Access memory tracker
361        let memory_tracker = manager.memory_tracker();
362        // Arc is always valid, so we just check we can access it
363        let _ = memory_tracker;
364
365        // Access scope tracker
366        let scope_tracker = manager.scope_tracker();
367        // Arc is always valid, so we just check we can access it
368        let _ = scope_tracker;
369
370        // Test that we can access them multiple times
371        let _memory_tracker2 = manager.memory_tracker();
372        let _scope_tracker2 = manager.scope_tracker();
373    }
374}