runbooks 1.1.4__py3-none-any.whl → 1.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- runbooks/__init__.py +31 -2
- runbooks/__init___optimized.py +18 -4
- runbooks/_platform/__init__.py +1 -5
- runbooks/_platform/core/runbooks_wrapper.py +141 -138
- runbooks/aws2/accuracy_validator.py +812 -0
- runbooks/base.py +7 -0
- runbooks/cfat/assessment/compliance.py +1 -1
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cli/__init__.py +1 -1
- runbooks/cli/commands/cfat.py +64 -23
- runbooks/cli/commands/finops.py +1005 -54
- runbooks/cli/commands/inventory.py +138 -35
- runbooks/cli/commands/operate.py +9 -36
- runbooks/cli/commands/security.py +42 -18
- runbooks/cli/commands/validation.py +432 -18
- runbooks/cli/commands/vpc.py +81 -17
- runbooks/cli/registry.py +22 -10
- runbooks/cloudops/__init__.py +20 -27
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +544 -542
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +224 -225
- runbooks/cloudops/lifecycle_manager.py +5 -4
- runbooks/cloudops/mcp_cost_validation.py +252 -235
- runbooks/cloudops/models.py +78 -53
- runbooks/cloudops/monitoring_automation.py +5 -4
- runbooks/cloudops/notebook_framework.py +177 -213
- runbooks/cloudops/security_enforcer.py +125 -159
- runbooks/common/accuracy_validator.py +11 -0
- runbooks/common/aws_pricing.py +349 -326
- runbooks/common/aws_pricing_api.py +211 -212
- runbooks/common/aws_profile_manager.py +40 -36
- runbooks/common/aws_utils.py +74 -79
- runbooks/common/business_logic.py +126 -104
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +455 -463
- runbooks/common/cross_account_manager.py +197 -204
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +29 -19
- runbooks/common/dry_run_examples.py +173 -208
- runbooks/common/dry_run_framework.py +157 -155
- runbooks/common/enhanced_exception_handler.py +15 -4
- runbooks/common/enhanced_logging_example.py +50 -64
- runbooks/common/enhanced_logging_integration_example.py +65 -37
- runbooks/common/env_utils.py +16 -16
- runbooks/common/error_handling.py +40 -38
- runbooks/common/lazy_loader.py +41 -23
- runbooks/common/logging_integration_helper.py +79 -86
- runbooks/common/mcp_cost_explorer_integration.py +476 -493
- runbooks/common/mcp_integration.py +63 -74
- runbooks/common/memory_optimization.py +140 -118
- runbooks/common/module_cli_base.py +37 -58
- runbooks/common/organizations_client.py +175 -193
- runbooks/common/patterns.py +23 -25
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +111 -37
- runbooks/common/rich_utils.py +201 -141
- runbooks/common/sre_performance_suite.py +177 -186
- runbooks/enterprise/__init__.py +1 -1
- runbooks/enterprise/logging.py +144 -106
- runbooks/enterprise/security.py +187 -204
- runbooks/enterprise/validation.py +43 -56
- runbooks/finops/__init__.py +26 -30
- runbooks/finops/account_resolver.py +1 -1
- runbooks/finops/advanced_optimization_engine.py +980 -0
- runbooks/finops/automation_core.py +268 -231
- runbooks/finops/business_case_config.py +184 -179
- runbooks/finops/cli.py +660 -139
- runbooks/finops/commvault_ec2_analysis.py +157 -164
- runbooks/finops/compute_cost_optimizer.py +336 -320
- runbooks/finops/config.py +20 -20
- runbooks/finops/cost_optimizer.py +484 -618
- runbooks/finops/cost_processor.py +332 -214
- runbooks/finops/dashboard_runner.py +1006 -172
- runbooks/finops/ebs_cost_optimizer.py +991 -657
- runbooks/finops/elastic_ip_optimizer.py +317 -257
- runbooks/finops/enhanced_mcp_integration.py +340 -0
- runbooks/finops/enhanced_progress.py +32 -29
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +223 -285
- runbooks/finops/executive_export.py +203 -160
- runbooks/finops/helpers.py +130 -288
- runbooks/finops/iam_guidance.py +1 -1
- runbooks/finops/infrastructure/__init__.py +80 -0
- runbooks/finops/infrastructure/commands.py +506 -0
- runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
- runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
- runbooks/finops/markdown_exporter.py +337 -174
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1512 -481
- runbooks/finops/network_cost_optimizer.py +657 -587
- runbooks/finops/notebook_utils.py +226 -188
- runbooks/finops/optimization_engine.py +1136 -0
- runbooks/finops/optimizer.py +19 -23
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +64 -65
- runbooks/finops/scenarios.py +1277 -438
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- runbooks/finops/types.py +3 -3
- runbooks/finops/validation_framework.py +259 -265
- runbooks/finops/vpc_cleanup_exporter.py +189 -144
- runbooks/finops/vpc_cleanup_optimizer.py +591 -573
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +1 -1
- runbooks/inventory/collectors/aws_networking.py +109 -99
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/drift_detection_cli.py +69 -96
- runbooks/inventory/inventory_mcp_cli.py +48 -46
- runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
- runbooks/inventory/mcp_inventory_validator.py +549 -465
- runbooks/inventory/mcp_vpc_validator.py +359 -442
- runbooks/inventory/organizations_discovery.py +55 -51
- runbooks/inventory/rich_inventory_display.py +33 -32
- runbooks/inventory/unified_validation_engine.py +278 -251
- runbooks/inventory/vpc_analyzer.py +732 -695
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +382 -378
- runbooks/inventory/vpc_flow_analyzer.py +1 -1
- runbooks/main.py +49 -34
- runbooks/main_final.py +91 -60
- runbooks/main_minimal.py +22 -10
- runbooks/main_optimized.py +131 -100
- runbooks/main_ultra_minimal.py +7 -2
- runbooks/mcp/__init__.py +36 -0
- runbooks/mcp/integration.py +679 -0
- runbooks/monitoring/performance_monitor.py +9 -4
- runbooks/operate/dynamodb_operations.py +3 -1
- runbooks/operate/ec2_operations.py +145 -137
- runbooks/operate/iam_operations.py +146 -152
- runbooks/operate/networking_cost_heatmap.py +29 -8
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_operations.py +646 -616
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +70 -66
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +86 -60
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +46 -41
- runbooks/security/__init__.py +19 -0
- runbooks/security/assessment_runner.py +1150 -0
- runbooks/security/baseline_checker.py +812 -0
- runbooks/security/cloudops_automation_security_validator.py +509 -535
- runbooks/security/compliance_automation_engine.py +17 -17
- runbooks/security/config/__init__.py +2 -2
- runbooks/security/config/compliance_config.py +50 -50
- runbooks/security/config_template_generator.py +63 -76
- runbooks/security/enterprise_security_framework.py +1 -1
- runbooks/security/executive_security_dashboard.py +519 -508
- runbooks/security/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- runbooks/security/security_baseline_tester.py +1 -1
- runbooks/security/security_cli.py +143 -112
- runbooks/security/test_2way_validation.py +439 -0
- runbooks/security/two_way_validation_framework.py +852 -0
- runbooks/sre/production_monitoring_framework.py +167 -177
- runbooks/tdd/__init__.py +15 -0
- runbooks/tdd/cli.py +1071 -0
- runbooks/utils/__init__.py +14 -17
- runbooks/utils/logger.py +7 -2
- runbooks/utils/version_validator.py +50 -47
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +745 -704
- runbooks/validation/mcp_validator.py +906 -228
- runbooks/validation/terraform_citations_validator.py +104 -115
- runbooks/validation/terraform_drift_detector.py +447 -451
- runbooks/vpc/README.md +617 -0
- runbooks/vpc/__init__.py +8 -1
- runbooks/vpc/analyzer.py +577 -0
- runbooks/vpc/cleanup_wrapper.py +476 -413
- runbooks/vpc/cli_cloudtrail_commands.py +339 -0
- runbooks/vpc/cli_mcp_validation_commands.py +480 -0
- runbooks/vpc/cloudtrail_audit_integration.py +717 -0
- runbooks/vpc/config.py +92 -97
- runbooks/vpc/cost_engine.py +411 -148
- runbooks/vpc/cost_explorer_integration.py +553 -0
- runbooks/vpc/cross_account_session.py +101 -106
- runbooks/vpc/enhanced_mcp_validation.py +917 -0
- runbooks/vpc/eni_gate_validator.py +961 -0
- runbooks/vpc/heatmap_engine.py +185 -160
- runbooks/vpc/mcp_no_eni_validator.py +680 -639
- runbooks/vpc/nat_gateway_optimizer.py +358 -0
- runbooks/vpc/networking_wrapper.py +15 -8
- runbooks/vpc/pdca_remediation_planner.py +528 -0
- runbooks/vpc/performance_optimized_analyzer.py +219 -231
- runbooks/vpc/runbooks_adapter.py +1167 -241
- runbooks/vpc/tdd_red_phase_stubs.py +601 -0
- runbooks/vpc/test_data_loader.py +358 -0
- runbooks/vpc/tests/conftest.py +314 -4
- runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
- runbooks/vpc/tests/test_cost_engine.py +0 -2
- runbooks/vpc/topology_generator.py +326 -0
- runbooks/vpc/unified_scenarios.py +1297 -1124
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.5.dist-info/METADATA +328 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/RECORD +214 -193
- runbooks/finops/README.md +0 -414
- runbooks/finops/accuracy_cross_validator.py +0 -647
- runbooks/finops/business_cases.py +0 -950
- runbooks/finops/dashboard_router.py +0 -922
- runbooks/finops/ebs_optimizer.py +0 -973
- runbooks/finops/embedded_mcp_validator.py +0 -1629
- runbooks/finops/enhanced_dashboard_runner.py +0 -527
- runbooks/finops/finops_dashboard.py +0 -584
- runbooks/finops/finops_scenarios.py +0 -1218
- runbooks/finops/legacy_migration.py +0 -730
- runbooks/finops/multi_dashboard.py +0 -1519
- runbooks/finops/single_dashboard.py +0 -1113
- runbooks/finops/unlimited_scenarios.py +0 -393
- runbooks-1.1.4.dist-info/METADATA +0 -800
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
"""
|
3
3
|
Memory Optimization Framework for CloudOps-Runbooks
|
4
|
-
|
4
|
+
|
5
5
|
🎯 SRE Automation Specialist Implementation
|
6
6
|
Following proven systematic delegation patterns for memory management and optimization.
|
7
7
|
|
@@ -29,10 +29,11 @@ import tracemalloc
|
|
29
29
|
|
30
30
|
try:
|
31
31
|
import psutil
|
32
|
+
|
32
33
|
PSUTIL_AVAILABLE = True
|
33
34
|
except ImportError:
|
34
35
|
PSUTIL_AVAILABLE = False
|
35
|
-
|
36
|
+
|
36
37
|
from runbooks.common.rich_utils import (
|
37
38
|
console,
|
38
39
|
print_header,
|
@@ -40,7 +41,7 @@ from runbooks.common.rich_utils import (
|
|
40
41
|
print_warning,
|
41
42
|
print_error,
|
42
43
|
create_table,
|
43
|
-
STATUS_INDICATORS
|
44
|
+
STATUS_INDICATORS,
|
44
45
|
)
|
45
46
|
|
46
47
|
logger = logging.getLogger(__name__)
|
@@ -49,6 +50,7 @@ logger = logging.getLogger(__name__)
|
|
49
50
|
@dataclass
|
50
51
|
class MemorySnapshot:
|
51
52
|
"""Memory usage snapshot for monitoring"""
|
53
|
+
|
52
54
|
timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
53
55
|
memory_mb: float = 0.0
|
54
56
|
peak_memory_mb: float = 0.0
|
@@ -58,9 +60,10 @@ class MemorySnapshot:
|
|
58
60
|
operation_context: Optional[str] = None
|
59
61
|
|
60
62
|
|
61
|
-
@dataclass
|
63
|
+
@dataclass
|
62
64
|
class MemoryOptimizationMetrics:
|
63
65
|
"""Memory optimization performance metrics"""
|
66
|
+
|
64
67
|
operation_name: str
|
65
68
|
start_memory_mb: float = 0.0
|
66
69
|
peak_memory_mb: float = 0.0
|
@@ -75,43 +78,45 @@ class MemoryOptimizationMetrics:
|
|
75
78
|
class MemoryOptimizer:
|
76
79
|
"""
|
77
80
|
Enterprise memory optimization system for large-scale CloudOps operations
|
78
|
-
|
81
|
+
|
79
82
|
Provides:
|
80
83
|
- Real-time memory monitoring with alerting thresholds
|
81
|
-
- Automatic garbage collection optimization
|
84
|
+
- Automatic garbage collection optimization
|
82
85
|
- Memory-efficient data processing patterns
|
83
86
|
- Resource cleanup automation
|
84
87
|
- Memory leak detection and prevention
|
85
88
|
"""
|
86
|
-
|
87
|
-
def __init__(
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
|
90
|
+
def __init__(
|
91
|
+
self,
|
92
|
+
warning_threshold_mb: float = 1024,
|
93
|
+
critical_threshold_mb: float = 2048,
|
94
|
+
monitoring_interval_seconds: float = 5.0,
|
95
|
+
):
|
91
96
|
"""
|
92
97
|
Initialize memory optimizer
|
93
|
-
|
98
|
+
|
94
99
|
Args:
|
95
100
|
warning_threshold_mb: Memory warning threshold in MB
|
96
|
-
critical_threshold_mb: Memory critical threshold in MB
|
101
|
+
critical_threshold_mb: Memory critical threshold in MB
|
97
102
|
monitoring_interval_seconds: Memory monitoring check interval
|
98
103
|
"""
|
99
104
|
self.warning_threshold_mb = warning_threshold_mb
|
100
105
|
self.critical_threshold_mb = critical_threshold_mb
|
101
106
|
self.monitoring_interval_seconds = monitoring_interval_seconds
|
102
|
-
|
107
|
+
|
103
108
|
# Memory tracking
|
104
109
|
self.snapshots: List[MemorySnapshot] = []
|
105
110
|
self.metrics: List[MemoryOptimizationMetrics] = []
|
106
111
|
self.monitoring_active = False
|
107
112
|
self.monitoring_thread: Optional[threading.Thread] = None
|
108
|
-
|
113
|
+
|
109
114
|
# Process handle if psutil available
|
110
115
|
self.process = psutil.Process() if PSUTIL_AVAILABLE else None
|
111
|
-
|
116
|
+
|
112
117
|
# Memory management strategies
|
113
118
|
self._setup_gc_optimization()
|
114
|
-
|
119
|
+
|
115
120
|
# Weak reference tracking for leak detection
|
116
121
|
self._tracked_objects: weakref.WeakSet = weakref.WeakSet()
|
117
122
|
|
@@ -119,74 +124,78 @@ class MemoryOptimizer:
|
|
119
124
|
"""Configure garbage collection optimization"""
|
120
125
|
# Optimize garbage collection thresholds for large-scale operations
|
121
126
|
gc.set_threshold(700, 10, 10) # More aggressive collection
|
122
|
-
|
127
|
+
|
123
128
|
# Enable automatic garbage collection
|
124
129
|
if not gc.isenabled():
|
125
130
|
gc.enable()
|
126
|
-
|
131
|
+
|
127
132
|
logger.debug("Memory optimization: Garbage collection configured")
|
128
133
|
|
129
134
|
@contextmanager
|
130
135
|
def optimize_memory_usage(self, operation_name: str, enable_monitoring: bool = True):
|
131
136
|
"""
|
132
137
|
Context manager for memory-optimized operation execution
|
133
|
-
|
138
|
+
|
134
139
|
Args:
|
135
140
|
operation_name: Name of operation being optimized
|
136
141
|
enable_monitoring: Whether to enable real-time monitoring
|
137
142
|
"""
|
138
143
|
# Initialize metrics
|
139
144
|
metrics = MemoryOptimizationMetrics(operation_name=operation_name)
|
140
|
-
|
145
|
+
|
141
146
|
# Start monitoring if requested
|
142
147
|
if enable_monitoring:
|
143
148
|
self.start_memory_monitoring()
|
144
|
-
|
149
|
+
|
145
150
|
# Record initial memory state
|
146
151
|
initial_snapshot = self._take_memory_snapshot(operation_name)
|
147
152
|
metrics.start_memory_mb = initial_snapshot.memory_mb
|
148
|
-
|
153
|
+
|
149
154
|
try:
|
150
|
-
console.log(
|
151
|
-
|
155
|
+
console.log(
|
156
|
+
f"[dim]🧠 Starting memory-optimized: {operation_name} (current: {initial_snapshot.memory_mb:.1f}MB)[/]"
|
157
|
+
)
|
158
|
+
|
152
159
|
yield metrics
|
153
|
-
|
160
|
+
|
154
161
|
# Record final state and calculate savings
|
155
162
|
final_snapshot = self._take_memory_snapshot(f"{operation_name}_end")
|
156
163
|
metrics.end_memory_mb = final_snapshot.memory_mb
|
157
|
-
metrics.peak_memory_mb =
|
158
|
-
|
164
|
+
metrics.peak_memory_mb = (
|
165
|
+
max(s.peak_memory_mb for s in self.snapshots[-10:]) if self.snapshots else final_snapshot.memory_mb
|
166
|
+
)
|
167
|
+
|
159
168
|
# Calculate memory efficiency
|
160
169
|
if metrics.start_memory_mb > 0:
|
161
170
|
memory_change = metrics.end_memory_mb - metrics.start_memory_mb
|
162
171
|
if memory_change < 0:
|
163
172
|
metrics.memory_saved_mb = abs(memory_change)
|
164
173
|
metrics.optimization_techniques_applied.append("memory_cleanup")
|
165
|
-
|
174
|
+
|
166
175
|
metrics.success = True
|
167
176
|
self._log_memory_results(metrics)
|
168
|
-
|
177
|
+
|
169
178
|
except Exception as e:
|
170
179
|
# Handle memory issues during operation
|
171
180
|
error_snapshot = self._take_memory_snapshot(f"{operation_name}_error")
|
172
181
|
metrics.end_memory_mb = error_snapshot.memory_mb
|
173
182
|
metrics.success = False
|
174
|
-
|
183
|
+
|
175
184
|
# Force garbage collection on error
|
176
185
|
collected = gc.collect()
|
177
186
|
metrics.gc_collections_triggered += collected
|
178
187
|
metrics.optimization_techniques_applied.append("error_gc_cleanup")
|
179
|
-
|
188
|
+
|
180
189
|
print_error(f"Memory optimization failed for {operation_name}", e)
|
181
190
|
raise
|
182
|
-
|
191
|
+
|
183
192
|
finally:
|
184
193
|
# Stop monitoring and store metrics
|
185
194
|
if enable_monitoring:
|
186
195
|
self.stop_memory_monitoring()
|
187
|
-
|
196
|
+
|
188
197
|
self.metrics.append(metrics)
|
189
|
-
|
198
|
+
|
190
199
|
# Cleanup operation-specific resources
|
191
200
|
self._cleanup_operation_resources()
|
192
201
|
|
@@ -194,113 +203,118 @@ class MemoryOptimizer:
|
|
194
203
|
"""Start background memory monitoring"""
|
195
204
|
if self.monitoring_active:
|
196
205
|
return
|
197
|
-
|
206
|
+
|
198
207
|
self.monitoring_active = True
|
199
|
-
|
208
|
+
|
200
209
|
def monitor_memory():
|
201
210
|
while self.monitoring_active:
|
202
211
|
try:
|
203
212
|
snapshot = self._take_memory_snapshot("monitoring")
|
204
213
|
self.snapshots.append(snapshot)
|
205
|
-
|
214
|
+
|
206
215
|
# Check thresholds and alert
|
207
216
|
self._check_memory_thresholds(snapshot)
|
208
|
-
|
217
|
+
|
209
218
|
# Limit snapshot history to prevent memory growth
|
210
219
|
if len(self.snapshots) > 1000:
|
211
220
|
self.snapshots = self.snapshots[-500:] # Keep recent 500
|
212
|
-
|
221
|
+
|
213
222
|
time.sleep(self.monitoring_interval_seconds)
|
214
|
-
|
223
|
+
|
215
224
|
except Exception as e:
|
216
225
|
logger.debug(f"Memory monitoring error: {e}")
|
217
226
|
break
|
218
|
-
|
227
|
+
|
219
228
|
self.monitoring_thread = threading.Thread(target=monitor_memory, daemon=True)
|
220
229
|
self.monitoring_thread.start()
|
221
|
-
|
230
|
+
|
222
231
|
logger.debug("Memory monitoring started")
|
223
232
|
|
224
233
|
def stop_memory_monitoring(self):
|
225
234
|
"""Stop background memory monitoring"""
|
226
235
|
self.monitoring_active = False
|
227
|
-
|
236
|
+
|
228
237
|
if self.monitoring_thread and self.monitoring_thread.is_alive():
|
229
238
|
self.monitoring_thread.join(timeout=5.0)
|
230
|
-
|
239
|
+
|
231
240
|
logger.debug("Memory monitoring stopped")
|
232
241
|
|
233
242
|
def _take_memory_snapshot(self, operation_context: str) -> MemorySnapshot:
|
234
243
|
"""Take comprehensive memory usage snapshot"""
|
235
244
|
snapshot = MemorySnapshot(operation_context=operation_context)
|
236
|
-
|
245
|
+
|
237
246
|
if self.process and PSUTIL_AVAILABLE:
|
238
247
|
try:
|
239
248
|
memory_info = self.process.memory_info()
|
240
249
|
snapshot.memory_mb = memory_info.rss / (1024 * 1024)
|
241
|
-
snapshot.peak_memory_mb = getattr(memory_info,
|
242
|
-
|
250
|
+
snapshot.peak_memory_mb = getattr(memory_info, "peak_wset", memory_info.rss) / (1024 * 1024)
|
251
|
+
|
243
252
|
# Memory percentage if available
|
244
253
|
try:
|
245
254
|
snapshot.memory_percent = self.process.memory_percent()
|
246
255
|
except:
|
247
256
|
snapshot.memory_percent = 0.0
|
248
|
-
|
257
|
+
|
249
258
|
except Exception as e:
|
250
259
|
logger.debug(f"Failed to get process memory info: {e}")
|
251
260
|
else:
|
252
261
|
# Fallback using tracemalloc if available
|
253
262
|
try:
|
254
263
|
import tracemalloc
|
264
|
+
|
255
265
|
if tracemalloc.is_tracing():
|
256
266
|
current, peak = tracemalloc.get_traced_memory()
|
257
267
|
snapshot.memory_mb = current / (1024 * 1024)
|
258
268
|
snapshot.peak_memory_mb = peak / (1024 * 1024)
|
259
269
|
except:
|
260
270
|
pass
|
261
|
-
|
271
|
+
|
262
272
|
# GC statistics
|
263
273
|
snapshot.gc_collections = tuple(gc.get_count())
|
264
|
-
|
274
|
+
|
265
275
|
# Active objects count
|
266
276
|
try:
|
267
277
|
snapshot.active_objects = len(gc.get_objects())
|
268
278
|
except:
|
269
279
|
snapshot.active_objects = 0
|
270
|
-
|
280
|
+
|
271
281
|
return snapshot
|
272
282
|
|
273
283
|
def _check_memory_thresholds(self, snapshot: MemorySnapshot):
|
274
284
|
"""Check memory usage against thresholds and alert if needed"""
|
275
285
|
if snapshot.memory_mb > self.critical_threshold_mb:
|
276
|
-
console.log(
|
277
|
-
|
286
|
+
console.log(
|
287
|
+
f"[red]🚨 CRITICAL: Memory usage {snapshot.memory_mb:.1f}MB exceeds critical threshold {self.critical_threshold_mb}MB[/red]"
|
288
|
+
)
|
289
|
+
|
278
290
|
# Force aggressive garbage collection
|
279
291
|
collected = self._force_garbage_collection()
|
280
292
|
console.log(f"[yellow]🗑️ Emergency GC collected {collected} objects[/yellow]")
|
281
|
-
|
293
|
+
|
282
294
|
elif snapshot.memory_mb > self.warning_threshold_mb:
|
283
|
-
console.log(
|
295
|
+
console.log(
|
296
|
+
f"[yellow]⚠️ WARNING: Memory usage {snapshot.memory_mb:.1f}MB exceeds warning threshold {self.warning_threshold_mb}MB[/yellow]"
|
297
|
+
)
|
284
298
|
|
285
299
|
def _force_garbage_collection(self) -> int:
|
286
300
|
"""Force comprehensive garbage collection"""
|
287
301
|
total_collected = 0
|
288
|
-
|
302
|
+
|
289
303
|
# Multiple GC passes for thorough cleanup
|
290
304
|
for generation in range(3):
|
291
305
|
collected = gc.collect(generation)
|
292
306
|
total_collected += collected
|
293
|
-
|
307
|
+
|
294
308
|
# Additional cleanup
|
295
309
|
gc.collect() # Final full collection
|
296
|
-
|
310
|
+
|
297
311
|
return total_collected
|
298
312
|
|
299
313
|
def _cleanup_operation_resources(self):
|
300
314
|
"""Clean up operation-specific resources"""
|
301
315
|
# Force garbage collection
|
302
316
|
gc.collect()
|
303
|
-
|
317
|
+
|
304
318
|
# Clear internal caches if they've grown large
|
305
319
|
if len(self.snapshots) > 100:
|
306
320
|
self.snapshots = self.snapshots[-50:] # Keep recent snapshots
|
@@ -308,58 +322,65 @@ class MemoryOptimizer:
|
|
308
322
|
def _log_memory_results(self, metrics: MemoryOptimizationMetrics):
|
309
323
|
"""Log memory optimization results"""
|
310
324
|
if metrics.memory_saved_mb > 0:
|
311
|
-
print_success(
|
312
|
-
|
313
|
-
|
325
|
+
print_success(
|
326
|
+
f"Memory optimized for {metrics.operation_name}: "
|
327
|
+
f"saved {metrics.memory_saved_mb:.1f}MB "
|
328
|
+
f"({metrics.start_memory_mb:.1f}MB → {metrics.end_memory_mb:.1f}MB)"
|
329
|
+
)
|
314
330
|
elif metrics.end_memory_mb <= metrics.start_memory_mb * 1.1: # Within 10%
|
315
|
-
console.log(
|
316
|
-
|
331
|
+
console.log(
|
332
|
+
f"[green]Memory stable for {metrics.operation_name}: "
|
333
|
+
f"{metrics.start_memory_mb:.1f}MB → {metrics.end_memory_mb:.1f}MB[/green]"
|
334
|
+
)
|
317
335
|
else:
|
318
|
-
console.log(
|
319
|
-
|
336
|
+
console.log(
|
337
|
+
f"[yellow]Memory increased for {metrics.operation_name}: "
|
338
|
+
f"{metrics.start_memory_mb:.1f}MB → {metrics.end_memory_mb:.1f}MB[/yellow]"
|
339
|
+
)
|
320
340
|
|
321
341
|
def create_memory_efficient_iterator(self, data: List[Any], batch_size: int = 100) -> Iterator[List[Any]]:
|
322
342
|
"""
|
323
343
|
Create memory-efficient iterator for large datasets
|
324
|
-
|
344
|
+
|
325
345
|
Args:
|
326
346
|
data: Large dataset to process
|
327
347
|
batch_size: Size of each batch to yield
|
328
|
-
|
348
|
+
|
329
349
|
Yields:
|
330
350
|
Batched data chunks for memory-efficient processing
|
331
351
|
"""
|
332
352
|
for i in range(0, len(data), batch_size):
|
333
|
-
batch = data[i:i + batch_size]
|
353
|
+
batch = data[i : i + batch_size]
|
334
354
|
yield batch
|
335
|
-
|
355
|
+
|
336
356
|
# Trigger GC every 10 batches to prevent memory buildup
|
337
357
|
if i > 0 and (i // batch_size) % 10 == 0:
|
338
358
|
gc.collect()
|
339
359
|
|
340
|
-
def optimize_large_dict_processing(
|
341
|
-
|
360
|
+
def optimize_large_dict_processing(
|
361
|
+
self, large_dict: Dict[str, Any], chunk_size: int = 1000
|
362
|
+
) -> Iterator[Dict[str, Any]]:
|
342
363
|
"""
|
343
364
|
Memory-efficient large dictionary processing
|
344
|
-
|
365
|
+
|
345
366
|
Args:
|
346
367
|
large_dict: Large dictionary to process
|
347
368
|
chunk_size: Number of items to process per chunk
|
348
|
-
|
369
|
+
|
349
370
|
Yields:
|
350
371
|
Dictionary chunks for processing
|
351
372
|
"""
|
352
373
|
items = list(large_dict.items())
|
353
|
-
|
374
|
+
|
354
375
|
for i in range(0, len(items), chunk_size):
|
355
|
-
chunk_items = items[i:i + chunk_size]
|
376
|
+
chunk_items = items[i : i + chunk_size]
|
356
377
|
chunk_dict = dict(chunk_items)
|
357
|
-
|
378
|
+
|
358
379
|
yield chunk_dict
|
359
|
-
|
380
|
+
|
360
381
|
# Clean up temporary variables
|
361
382
|
del chunk_items, chunk_dict
|
362
|
-
|
383
|
+
|
363
384
|
# Periodic GC
|
364
385
|
if i > 0 and (i // chunk_size) % 5 == 0:
|
365
386
|
gc.collect()
|
@@ -372,13 +393,13 @@ class MemoryOptimizer:
|
|
372
393
|
def get_memory_usage_report(self) -> Dict[str, Any]:
|
373
394
|
"""Get comprehensive memory usage report"""
|
374
395
|
current_snapshot = self._take_memory_snapshot("report_generation")
|
375
|
-
|
396
|
+
|
376
397
|
# Calculate statistics from recent snapshots
|
377
398
|
recent_snapshots = self.snapshots[-20:] if self.snapshots else [current_snapshot]
|
378
|
-
|
399
|
+
|
379
400
|
avg_memory = sum(s.memory_mb for s in recent_snapshots) / len(recent_snapshots)
|
380
401
|
peak_memory = max(s.peak_memory_mb for s in recent_snapshots)
|
381
|
-
|
402
|
+
|
382
403
|
return {
|
383
404
|
"current_memory_mb": current_snapshot.memory_mb,
|
384
405
|
"average_memory_mb": avg_memory,
|
@@ -390,7 +411,7 @@ class MemoryOptimizer:
|
|
390
411
|
"gc_collections": current_snapshot.gc_collections,
|
391
412
|
"tracked_objects": len(self._tracked_objects),
|
392
413
|
"memory_status": self._get_memory_status(current_snapshot),
|
393
|
-
"optimization_recommendations": self._get_optimization_recommendations(current_snapshot)
|
414
|
+
"optimization_recommendations": self._get_optimization_recommendations(current_snapshot),
|
394
415
|
}
|
395
416
|
|
396
417
|
def _get_memory_status(self, snapshot: MemorySnapshot) -> str:
|
@@ -407,21 +428,21 @@ class MemoryOptimizer:
|
|
407
428
|
def _get_optimization_recommendations(self, snapshot: MemorySnapshot) -> List[str]:
|
408
429
|
"""Generate memory optimization recommendations"""
|
409
430
|
recommendations = []
|
410
|
-
|
431
|
+
|
411
432
|
if snapshot.memory_mb > self.critical_threshold_mb:
|
412
433
|
recommendations.append("Immediate garbage collection required")
|
413
434
|
recommendations.append("Consider batch processing for large operations")
|
414
|
-
|
435
|
+
|
415
436
|
if snapshot.memory_mb > self.warning_threshold_mb:
|
416
437
|
recommendations.append("Monitor memory usage closely")
|
417
438
|
recommendations.append("Implement streaming processing for large datasets")
|
418
|
-
|
439
|
+
|
419
440
|
if snapshot.active_objects > 100000:
|
420
441
|
recommendations.append("High object count detected - review object lifecycle")
|
421
|
-
|
442
|
+
|
422
443
|
if len(self._tracked_objects) > 0:
|
423
444
|
recommendations.append(f"{len(self._tracked_objects)} objects being tracked for leaks")
|
424
|
-
|
445
|
+
|
425
446
|
return recommendations
|
426
447
|
|
427
448
|
def create_memory_summary_table(self) -> None:
|
@@ -429,9 +450,9 @@ class MemoryOptimizer:
|
|
429
450
|
if not self.metrics:
|
430
451
|
console.print("[yellow]No memory optimization metrics available[/yellow]")
|
431
452
|
return
|
432
|
-
|
453
|
+
|
433
454
|
print_header("Memory Optimization Summary", "SRE Memory Management")
|
434
|
-
|
455
|
+
|
435
456
|
# Create metrics table
|
436
457
|
table = create_table(
|
437
458
|
title="Memory Optimization Results",
|
@@ -442,38 +463,38 @@ class MemoryOptimizer:
|
|
442
463
|
{"name": "End (MB)", "style": "white", "justify": "right"},
|
443
464
|
{"name": "Saved (MB)", "style": "green", "justify": "right"},
|
444
465
|
{"name": "Optimizations", "style": "dim", "justify": "left", "max_width": 25},
|
445
|
-
{"name": "Status", "style": "white", "justify": "center"}
|
446
|
-
]
|
466
|
+
{"name": "Status", "style": "white", "justify": "center"},
|
467
|
+
],
|
447
468
|
)
|
448
|
-
|
469
|
+
|
449
470
|
for metrics in self.metrics:
|
450
|
-
status_icon = STATUS_INDICATORS[
|
451
|
-
status_color =
|
452
|
-
|
471
|
+
status_icon = STATUS_INDICATORS["success"] if metrics.success else STATUS_INDICATORS["error"]
|
472
|
+
status_color = "green" if metrics.success else "red"
|
473
|
+
|
453
474
|
saved_text = f"+{metrics.memory_saved_mb:.1f}" if metrics.memory_saved_mb > 0 else "0.0"
|
454
|
-
|
475
|
+
|
455
476
|
table.add_row(
|
456
477
|
metrics.operation_name,
|
457
478
|
f"{metrics.start_memory_mb:.1f}",
|
458
479
|
f"{metrics.peak_memory_mb:.1f}",
|
459
480
|
f"{metrics.end_memory_mb:.1f}",
|
460
481
|
saved_text,
|
461
|
-
", ".join(metrics.optimization_techniques_applied[:2])
|
462
|
-
|
482
|
+
", ".join(metrics.optimization_techniques_applied[:2])
|
483
|
+
+ ("..." if len(metrics.optimization_techniques_applied) > 2 else ""),
|
484
|
+
f"[{status_color}]{status_icon}[/]",
|
463
485
|
)
|
464
|
-
|
486
|
+
|
465
487
|
console.print(table)
|
466
|
-
|
488
|
+
|
467
489
|
# Current memory status
|
468
490
|
report = self.get_memory_usage_report()
|
469
|
-
status_color = {
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
console.print(f"\n[{status_color}]Current Memory: {report['current_memory_mb']:.1f}MB ({report['memory_status'].upper()})[/{status_color}]")
|
491
|
+
status_color = {"good": "green", "moderate": "yellow", "warning": "yellow", "critical": "red"}.get(
|
492
|
+
report["memory_status"], "white"
|
493
|
+
)
|
494
|
+
|
495
|
+
console.print(
|
496
|
+
f"\n[{status_color}]Current Memory: {report['current_memory_mb']:.1f}MB ({report['memory_status'].upper()})[/{status_color}]"
|
497
|
+
)
|
477
498
|
|
478
499
|
def clear_optimization_data(self):
|
479
500
|
"""Clear all optimization tracking data"""
|
@@ -488,14 +509,12 @@ class MemoryOptimizer:
|
|
488
509
|
_memory_optimizer: Optional[MemoryOptimizer] = None
|
489
510
|
|
490
511
|
|
491
|
-
def get_memory_optimizer(warning_threshold_mb: float = 1024,
|
492
|
-
critical_threshold_mb: float = 2048) -> MemoryOptimizer:
|
512
|
+
def get_memory_optimizer(warning_threshold_mb: float = 1024, critical_threshold_mb: float = 2048) -> MemoryOptimizer:
|
493
513
|
"""Get or create global memory optimizer instance"""
|
494
514
|
global _memory_optimizer
|
495
515
|
if _memory_optimizer is None:
|
496
516
|
_memory_optimizer = MemoryOptimizer(
|
497
|
-
warning_threshold_mb=warning_threshold_mb,
|
498
|
-
critical_threshold_mb=critical_threshold_mb
|
517
|
+
warning_threshold_mb=warning_threshold_mb, critical_threshold_mb=critical_threshold_mb
|
499
518
|
)
|
500
519
|
return _memory_optimizer
|
501
520
|
|
@@ -511,14 +530,17 @@ def create_memory_report():
|
|
511
530
|
# Memory optimization decorators
|
512
531
|
def memory_optimized(operation_name: str = None, enable_monitoring: bool = True):
|
513
532
|
"""Decorator for memory-optimized function execution"""
|
533
|
+
|
514
534
|
def decorator(func: Callable) -> Callable:
|
515
535
|
def wrapper(*args, **kwargs):
|
516
536
|
optimizer = get_memory_optimizer()
|
517
537
|
op_name = operation_name or f"{func.__module__}.{func.__name__}"
|
518
|
-
|
538
|
+
|
519
539
|
with optimizer.optimize_memory_usage(op_name, enable_monitoring):
|
520
540
|
return func(*args, **kwargs)
|
541
|
+
|
521
542
|
return wrapper
|
543
|
+
|
522
544
|
return decorator
|
523
545
|
|
524
546
|
|
@@ -527,7 +549,7 @@ __all__ = [
|
|
527
549
|
"MemoryOptimizer",
|
528
550
|
"MemorySnapshot",
|
529
551
|
"MemoryOptimizationMetrics",
|
530
|
-
"get_memory_optimizer",
|
552
|
+
"get_memory_optimizer",
|
531
553
|
"create_memory_report",
|
532
|
-
"memory_optimized"
|
533
|
-
]
|
554
|
+
"memory_optimized",
|
555
|
+
]
|