runbooks 1.1.3__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/WEIGHT_CONFIG_README.md +1 -1
- runbooks/cfat/assessment/compliance.py +8 -8
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cfat/models.py +6 -2
- runbooks/cfat/tests/__init__.py +6 -1
- runbooks/cli/__init__.py +13 -0
- runbooks/cli/commands/cfat.py +274 -0
- runbooks/cli/commands/finops.py +1164 -0
- runbooks/cli/commands/inventory.py +379 -0
- runbooks/cli/commands/operate.py +239 -0
- runbooks/cli/commands/security.py +248 -0
- runbooks/cli/commands/validation.py +825 -0
- runbooks/cli/commands/vpc.py +310 -0
- runbooks/cli/registry.py +107 -0
- runbooks/cloudops/__init__.py +23 -30
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +549 -547
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +226 -227
- 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 +179 -215
- 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 +341 -0
- runbooks/common/aws_utils.py +75 -80
- runbooks/common/business_logic.py +127 -105
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +456 -464
- runbooks/common/cross_account_manager.py +198 -205
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +235 -0
- 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 +478 -495
- 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 +176 -194
- runbooks/common/patterns.py +204 -0
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +248 -39
- runbooks/common/rich_utils.py +643 -92
- 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 +29 -33
- 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 +488 -622
- 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 +40 -37
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +230 -292
- 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 +338 -175
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1513 -482
- 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 +25 -29
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +77 -78
- runbooks/finops/scenarios.py +1278 -439
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- runbooks/finops/tests/test_finops_dashboard.py +3 -3
- runbooks/finops/tests/test_reference_images_validation.py +2 -2
- runbooks/finops/tests/test_single_account_features.py +17 -17
- runbooks/finops/tests/validate_test_suite.py +1 -1
- runbooks/finops/types.py +3 -3
- runbooks/finops/validation_framework.py +263 -269
- runbooks/finops/vpc_cleanup_exporter.py +191 -146
- runbooks/finops/vpc_cleanup_optimizer.py +593 -575
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/hitl/enhanced_workflow_engine.py +1 -1
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/README.md +3 -3
- runbooks/inventory/Tests/common_test_data.py +30 -30
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +28 -11
- runbooks/inventory/collectors/aws_networking.py +111 -101
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/discovery.md +2 -2
- runbooks/inventory/drift_detection_cli.py +69 -96
- runbooks/inventory/find_ec2_security_groups.py +1 -1
- 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 +56 -52
- runbooks/inventory/rich_inventory_display.py +33 -32
- runbooks/inventory/unified_validation_engine.py +278 -251
- runbooks/inventory/vpc_analyzer.py +733 -696
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +382 -378
- runbooks/inventory/vpc_flow_analyzer.py +3 -3
- runbooks/main.py +152 -9147
- 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/metrics/dora_metrics_engine.py +2 -2
- 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/mcp_integration.py +1 -1
- runbooks/operate/networking_cost_heatmap.py +33 -10
- runbooks/operate/privatelink_operations.py +1 -1
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_endpoints.py +1 -1
- runbooks/operate/vpc_operations.py +648 -618
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +71 -67
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +91 -65
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +49 -44
- 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/integration_test_enterprise_security.py +5 -3
- runbooks/security/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- runbooks/security/run_script.py +1 -1
- 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/mcp_reliability_engine.py +6 -6
- 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 +51 -48
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +754 -708
- 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 +190 -162
- runbooks/vpc/mcp_no_eni_validator.py +681 -640
- 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 +1302 -1129
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.5.dist-info/METADATA +328 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/RECORD +233 -200
- 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 -956
- 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.3.dist-info/METADATA +0 -799
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,204 @@
|
|
1
|
+
"""
|
2
|
+
DRY Pattern Manager - Eliminate Pattern Duplication
|
3
|
+
|
4
|
+
Following Claude Code best practices for memory efficiency and enterprise
|
5
|
+
architecture patterns for systematic deduplication.
|
6
|
+
|
7
|
+
Official Claude Code Limitation: Context window optimization requires eliminating
|
8
|
+
redundant patterns to maximize available context for complex operations.
|
9
|
+
|
10
|
+
Enterprise Best Practice: Single source of truth for all reusable patterns
|
11
|
+
prevents inconsistencies and reduces maintenance overhead.
|
12
|
+
"""
|
13
|
+
|
14
|
+
from typing import Any, Dict, Optional, Callable
|
15
|
+
from functools import lru_cache
|
16
|
+
import click
|
17
|
+
from rich.console import Console
|
18
|
+
from rich.markup import escape
|
19
|
+
|
20
|
+
|
21
|
+
class DRYPatternManager:
|
22
|
+
"""
|
23
|
+
Don't Repeat Yourself - Load patterns once, reference everywhere.
|
24
|
+
|
25
|
+
Following Claude Code optimization principles:
|
26
|
+
- Single pattern registry (no duplicates)
|
27
|
+
- Reference-based access (@ notation concept)
|
28
|
+
- Memory efficiency through lazy loading
|
29
|
+
- Consistent patterns across all modules
|
30
|
+
|
31
|
+
Enterprise Architecture:
|
32
|
+
- Centralized pattern management
|
33
|
+
- Type-safe pattern access
|
34
|
+
- Cached pattern instances
|
35
|
+
- Extensible pattern registry
|
36
|
+
"""
|
37
|
+
|
38
|
+
_patterns: Dict[str, Any] = {}
|
39
|
+
_console: Optional[Console] = None
|
40
|
+
_loaded: bool = False
|
41
|
+
|
42
|
+
@classmethod
|
43
|
+
@lru_cache(maxsize=None)
|
44
|
+
def get_console(cls) -> Console:
|
45
|
+
"""
|
46
|
+
Single console instance for all modules.
|
47
|
+
|
48
|
+
Claude Code Best Practice: Reuse console objects to reduce memory overhead
|
49
|
+
and ensure consistent formatting across all CLI operations.
|
50
|
+
"""
|
51
|
+
if cls._console is None:
|
52
|
+
cls._console = Console()
|
53
|
+
return cls._console
|
54
|
+
|
55
|
+
@classmethod
|
56
|
+
def get_pattern(cls, name: str) -> Any:
|
57
|
+
"""
|
58
|
+
Get pattern by name with lazy loading.
|
59
|
+
|
60
|
+
Args:
|
61
|
+
name: Pattern identifier (e.g., 'error_handlers', 'click_group')
|
62
|
+
|
63
|
+
Returns:
|
64
|
+
Cached pattern instance
|
65
|
+
|
66
|
+
Raises:
|
67
|
+
KeyError: If pattern not found
|
68
|
+
"""
|
69
|
+
if not cls._loaded:
|
70
|
+
cls._load_all_patterns()
|
71
|
+
|
72
|
+
if name not in cls._patterns:
|
73
|
+
raise KeyError(f"Pattern '{name}' not found. Available: {list(cls._patterns.keys())}")
|
74
|
+
|
75
|
+
return cls._patterns[name]
|
76
|
+
|
77
|
+
@classmethod
|
78
|
+
def _load_all_patterns(cls):
|
79
|
+
"""Load all patterns once - DRY principle implementation."""
|
80
|
+
if cls._loaded:
|
81
|
+
return
|
82
|
+
|
83
|
+
# Common import patterns
|
84
|
+
cls._patterns["click"] = click
|
85
|
+
cls._patterns["console"] = cls.get_console()
|
86
|
+
|
87
|
+
# Error handling patterns
|
88
|
+
cls._patterns["error_handlers"] = cls._create_error_handlers()
|
89
|
+
|
90
|
+
# Click group patterns
|
91
|
+
cls._patterns["click_group"] = cls._create_click_group_pattern()
|
92
|
+
|
93
|
+
# Common CLI decorators reference
|
94
|
+
cls._patterns["common_decorators"] = cls._get_common_decorators()
|
95
|
+
|
96
|
+
cls._loaded = True
|
97
|
+
|
98
|
+
@classmethod
|
99
|
+
def _create_error_handlers(cls) -> Dict[str, Callable]:
|
100
|
+
"""
|
101
|
+
Centralized error handling patterns.
|
102
|
+
|
103
|
+
Eliminates 19 instances of duplicated error messages across CLI modules.
|
104
|
+
"""
|
105
|
+
console = cls.get_console()
|
106
|
+
|
107
|
+
def module_not_available_error(module_name: str, error: Exception):
|
108
|
+
"""Standardized 'module not available' error handler."""
|
109
|
+
console.print(f"[red]❌ {module_name} module not available: {error}[/red]")
|
110
|
+
|
111
|
+
def operation_failed_error(operation_name: str, error: Exception):
|
112
|
+
"""Standardized 'operation failed' error handler."""
|
113
|
+
console.print(f"[red]❌ {operation_name} failed: {error}[/red]")
|
114
|
+
|
115
|
+
def success_message(message: str, details: Optional[str] = None):
|
116
|
+
"""Standardized success message."""
|
117
|
+
console.print(f"[green]✅ {message}[/green]")
|
118
|
+
if details:
|
119
|
+
console.print(f"[dim]{details}[/dim]")
|
120
|
+
|
121
|
+
return {
|
122
|
+
"module_not_available": module_not_available_error,
|
123
|
+
"operation_failed": operation_failed_error,
|
124
|
+
"success": success_message,
|
125
|
+
}
|
126
|
+
|
127
|
+
@classmethod
|
128
|
+
def _create_click_group_pattern(cls) -> Callable:
|
129
|
+
"""
|
130
|
+
Standardized Click group creation pattern.
|
131
|
+
|
132
|
+
Eliminates 6 instances of identical @click.group patterns.
|
133
|
+
"""
|
134
|
+
|
135
|
+
def create_group(name: str, help_text: str, invoke_without_command: bool = True):
|
136
|
+
"""Create standardized Click group with common options."""
|
137
|
+
|
138
|
+
@click.group(invoke_without_command=invoke_without_command)
|
139
|
+
@click.pass_context
|
140
|
+
def group(ctx):
|
141
|
+
if ctx.invoked_subcommand is None:
|
142
|
+
click.echo(f"{name.title()} Commands:")
|
143
|
+
click.echo(help_text)
|
144
|
+
|
145
|
+
# Apply consistent group naming
|
146
|
+
group.name = name
|
147
|
+
group.__doc__ = help_text
|
148
|
+
|
149
|
+
return group
|
150
|
+
|
151
|
+
return create_group
|
152
|
+
|
153
|
+
@classmethod
|
154
|
+
def _get_common_decorators(cls):
|
155
|
+
"""Reference to common decorators - avoid importing in every module."""
|
156
|
+
try:
|
157
|
+
from runbooks.common.decorators import common_aws_options, common_output_options, common_filter_options
|
158
|
+
|
159
|
+
return {
|
160
|
+
"aws_options": common_aws_options,
|
161
|
+
"output_options": common_output_options,
|
162
|
+
"filter_options": common_filter_options,
|
163
|
+
}
|
164
|
+
except ImportError:
|
165
|
+
# Graceful degradation if decorators not available
|
166
|
+
return {}
|
167
|
+
|
168
|
+
|
169
|
+
# Convenience functions for direct pattern access
|
170
|
+
def get_console() -> Console:
|
171
|
+
"""Get shared console instance - replaces individual console = Console() calls."""
|
172
|
+
return DRYPatternManager.get_console()
|
173
|
+
|
174
|
+
|
175
|
+
def get_error_handlers() -> Dict[str, Callable]:
|
176
|
+
"""Get standardized error handlers."""
|
177
|
+
return DRYPatternManager.get_pattern("error_handlers")
|
178
|
+
|
179
|
+
|
180
|
+
def get_click_group_creator() -> Callable:
|
181
|
+
"""Get standardized Click group creator."""
|
182
|
+
return DRYPatternManager.get_pattern("click_group")
|
183
|
+
|
184
|
+
|
185
|
+
def get_common_decorators() -> Dict[str, Any]:
|
186
|
+
"""Get common CLI decorators."""
|
187
|
+
return DRYPatternManager.get_pattern("common_decorators")
|
188
|
+
|
189
|
+
|
190
|
+
# Pattern registry status for monitoring
|
191
|
+
def get_pattern_registry_status() -> Dict[str, Any]:
|
192
|
+
"""
|
193
|
+
Get DRY pattern registry status for monitoring and optimization.
|
194
|
+
|
195
|
+
Returns:
|
196
|
+
Dictionary containing registry status, loaded patterns, and memory efficiency metrics
|
197
|
+
"""
|
198
|
+
return {
|
199
|
+
"loaded": DRYPatternManager._loaded,
|
200
|
+
"pattern_count": len(DRYPatternManager._patterns),
|
201
|
+
"available_patterns": list(DRYPatternManager._patterns.keys()),
|
202
|
+
"console_shared": DRYPatternManager._console is not None,
|
203
|
+
"memory_efficiency": "Single instance sharing active",
|
204
|
+
}
|
@@ -25,14 +25,21 @@ from datetime import datetime
|
|
25
25
|
import json
|
26
26
|
|
27
27
|
from runbooks.common.rich_utils import (
|
28
|
-
console,
|
29
|
-
|
28
|
+
console,
|
29
|
+
print_success,
|
30
|
+
print_warning,
|
31
|
+
print_info,
|
32
|
+
print_error,
|
33
|
+
create_table,
|
34
|
+
create_progress_bar,
|
35
|
+
STATUS_INDICATORS,
|
30
36
|
)
|
31
37
|
|
32
38
|
|
33
39
|
@dataclass
|
34
40
|
class PerformanceMetrics:
|
35
41
|
"""Enterprise performance metrics tracking."""
|
42
|
+
|
36
43
|
operation_name: str
|
37
44
|
module_name: str
|
38
45
|
start_time: float
|
@@ -68,21 +75,22 @@ class PerformanceMetrics:
|
|
68
75
|
"api_calls": self.api_calls_count,
|
69
76
|
"success": self.success,
|
70
77
|
"business_value": self.business_value,
|
71
|
-
"resources_processed": self.resources_processed
|
78
|
+
"resources_processed": self.resources_processed,
|
72
79
|
}
|
73
80
|
|
74
81
|
|
75
82
|
@dataclass
|
76
83
|
class ModulePerformanceTargets:
|
77
84
|
"""Module-specific performance targets for enterprise operations."""
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
85
|
+
|
86
|
+
finops: int = 15 # FinOps cost analysis operations
|
87
|
+
inventory: int = 45 # Multi-account discovery operations
|
88
|
+
operate: int = 15 # Resource operations with safety validation
|
89
|
+
security: int = 45 # Comprehensive security assessments
|
90
|
+
cfat: int = 60 # Cloud foundations assessments
|
91
|
+
vpc: int = 30 # Network analysis with cost integration
|
92
|
+
remediation: int = 15 # Automated security remediation
|
93
|
+
sre: int = 30 # Site reliability engineering operations
|
86
94
|
|
87
95
|
def get_target(self, module_name: str) -> int:
|
88
96
|
"""Get performance target for module."""
|
@@ -107,10 +115,12 @@ def reset_api_counter():
|
|
107
115
|
_api_call_counter = 0
|
108
116
|
|
109
117
|
|
110
|
-
def monitor_performance(
|
111
|
-
|
112
|
-
|
113
|
-
|
118
|
+
def monitor_performance(
|
119
|
+
module_name: str = "runbooks",
|
120
|
+
operation_name: Optional[str] = None,
|
121
|
+
target_seconds: Optional[int] = None,
|
122
|
+
track_memory: bool = True,
|
123
|
+
):
|
114
124
|
"""
|
115
125
|
Decorator for comprehensive performance monitoring.
|
116
126
|
|
@@ -128,6 +138,7 @@ def monitor_performance(module_name: str = "runbooks",
|
|
128
138
|
def analyze_costs(**kwargs):
|
129
139
|
# Your operation code here
|
130
140
|
"""
|
141
|
+
|
131
142
|
def decorator(f: Callable) -> Callable:
|
132
143
|
@wraps(f)
|
133
144
|
def wrapper(*args, **kwargs):
|
@@ -143,7 +154,7 @@ def monitor_performance(module_name: str = "runbooks",
|
|
143
154
|
module_name=module_name,
|
144
155
|
start_time=time.time(),
|
145
156
|
end_time=0.0,
|
146
|
-
target_seconds=target
|
157
|
+
target_seconds=target,
|
147
158
|
)
|
148
159
|
|
149
160
|
# Start memory tracking if enabled
|
@@ -166,8 +177,8 @@ def monitor_performance(module_name: str = "runbooks",
|
|
166
177
|
|
167
178
|
# Extract business metrics if available
|
168
179
|
if isinstance(result, dict):
|
169
|
-
metrics.business_value = result.get(
|
170
|
-
metrics.resources_processed = result.get(
|
180
|
+
metrics.business_value = result.get("annual_savings", 0.0)
|
181
|
+
metrics.resources_processed = result.get("resources_count", 0)
|
171
182
|
|
172
183
|
# Capture performance data
|
173
184
|
metrics.api_calls_count = _api_call_counter
|
@@ -205,6 +216,7 @@ def monitor_performance(module_name: str = "runbooks",
|
|
205
216
|
raise
|
206
217
|
|
207
218
|
return wrapper
|
219
|
+
|
208
220
|
return decorator
|
209
221
|
|
210
222
|
|
@@ -221,8 +233,7 @@ def _provide_performance_feedback(metrics: PerformanceMetrics):
|
|
221
233
|
if execution_time <= target:
|
222
234
|
# Performance target met
|
223
235
|
print_success(
|
224
|
-
f"⚡ Performance: {execution_time:.1f}s "
|
225
|
-
f"(target: <{target}s) - {metrics.efficiency_score:.1f}% efficient"
|
236
|
+
f"⚡ Performance: {execution_time:.1f}s (target: <{target}s) - {metrics.efficiency_score:.1f}% efficient"
|
226
237
|
)
|
227
238
|
|
228
239
|
# Celebrate exceptional performance
|
@@ -232,8 +243,7 @@ def _provide_performance_feedback(metrics: PerformanceMetrics):
|
|
232
243
|
else:
|
233
244
|
# Performance target exceeded
|
234
245
|
print_warning(
|
235
|
-
f"⚠️ Performance: {execution_time:.1f}s "
|
236
|
-
f"(exceeded {target}s target by {execution_time - target:.1f}s)"
|
246
|
+
f"⚠️ Performance: {execution_time:.1f}s (exceeded {target}s target by {execution_time - target:.1f}s)"
|
237
247
|
)
|
238
248
|
|
239
249
|
# Provide optimization recommendations
|
@@ -269,16 +279,10 @@ def _provide_optimization_recommendations(metrics: PerformanceMetrics):
|
|
269
279
|
module_recommendations = {
|
270
280
|
"finops": [
|
271
281
|
"Use more specific date ranges to reduce Cost Explorer data",
|
272
|
-
"Consider account filtering for large organizations"
|
282
|
+
"Consider account filtering for large organizations",
|
273
283
|
],
|
274
|
-
"inventory": [
|
275
|
-
|
276
|
-
"Implement parallel account processing"
|
277
|
-
],
|
278
|
-
"security": [
|
279
|
-
"Focus on high-priority security checks first",
|
280
|
-
"Use incremental scanning for large environments"
|
281
|
-
]
|
284
|
+
"inventory": ["Use service-specific discovery instead of full scan", "Implement parallel account processing"],
|
285
|
+
"security": ["Focus on high-priority security checks first", "Use incremental scanning for large environments"],
|
282
286
|
}
|
283
287
|
|
284
288
|
if metrics.module_name in module_recommendations:
|
@@ -286,8 +290,7 @@ def _provide_optimization_recommendations(metrics: PerformanceMetrics):
|
|
286
290
|
print_info(f" • {rec}")
|
287
291
|
|
288
292
|
|
289
|
-
def benchmark_operation(module_name: str, operation_name: str,
|
290
|
-
target_calls: int = 10):
|
293
|
+
def benchmark_operation(module_name: str, operation_name: str, target_calls: int = 10):
|
291
294
|
"""
|
292
295
|
Decorator for benchmarking operation performance over multiple runs.
|
293
296
|
|
@@ -301,6 +304,7 @@ def benchmark_operation(module_name: str, operation_name: str,
|
|
301
304
|
def analyze_costs(**kwargs):
|
302
305
|
# Your operation code here
|
303
306
|
"""
|
307
|
+
|
304
308
|
def decorator(f: Callable) -> Callable:
|
305
309
|
@wraps(f)
|
306
310
|
def wrapper(*args, **kwargs):
|
@@ -313,8 +317,7 @@ def benchmark_operation(module_name: str, operation_name: str,
|
|
313
317
|
|
314
318
|
# Execute with monitoring
|
315
319
|
monitored_func = monitor_performance(
|
316
|
-
module_name=module_name,
|
317
|
-
operation_name=f"{operation_name}_benchmark_{run+1}"
|
320
|
+
module_name=module_name, operation_name=f"{operation_name}_benchmark_{run + 1}"
|
318
321
|
)(f)
|
319
322
|
|
320
323
|
result = monitored_func(*args, **kwargs)
|
@@ -329,6 +332,7 @@ def benchmark_operation(module_name: str, operation_name: str,
|
|
329
332
|
return result
|
330
333
|
|
331
334
|
return wrapper
|
335
|
+
|
332
336
|
return decorator
|
333
337
|
|
334
338
|
|
@@ -360,28 +364,30 @@ def _analyze_benchmark_results(results: List[PerformanceMetrics], operation_name
|
|
360
364
|
columns=[
|
361
365
|
{"name": "Metric", "style": "cyan"},
|
362
366
|
{"name": "Value", "style": "green"},
|
363
|
-
{"name": "Assessment", "style": "yellow"}
|
364
|
-
]
|
367
|
+
{"name": "Assessment", "style": "yellow"},
|
368
|
+
],
|
365
369
|
)
|
366
370
|
|
367
371
|
target = results[0].target_seconds
|
368
372
|
|
369
|
-
table.add_row("Average Time", f"{avg_time:.2f}s",
|
370
|
-
|
371
|
-
table.add_row("
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
table.add_row(
|
378
|
-
|
373
|
+
table.add_row("Average Time", f"{avg_time:.2f}s", "✅ Good" if avg_time <= target else "⚠️ Needs optimization")
|
374
|
+
table.add_row("Best Time", f"{min_time:.2f}s", "🏆 Excellent" if min_time <= target * 0.5 else "✅ Good")
|
375
|
+
table.add_row("Worst Time", f"{max_time:.2f}s", "⚠️ Investigate" if max_time > target * 1.5 else "✅ Acceptable")
|
376
|
+
table.add_row(
|
377
|
+
"Success Rate",
|
378
|
+
f"{len(execution_times)}/{len(results)}",
|
379
|
+
"✅ Perfect" if len(execution_times) == len(results) else "⚠️ Some failures",
|
380
|
+
)
|
381
|
+
table.add_row(
|
382
|
+
"Consistency",
|
383
|
+
f"±{(max_time - min_time):.2f}s",
|
384
|
+
"✅ Consistent" if (max_time - min_time) <= target * 0.2 else "⚠️ Variable",
|
385
|
+
)
|
379
386
|
|
380
387
|
console.print(table)
|
381
388
|
|
382
389
|
|
383
|
-
def get_performance_report(module_name: Optional[str] = None,
|
384
|
-
last_n_operations: int = 10) -> Dict[str, Any]:
|
390
|
+
def get_performance_report(module_name: Optional[str] = None, last_n_operations: int = 10) -> Dict[str, Any]:
|
385
391
|
"""
|
386
392
|
Generate performance report for operations.
|
387
393
|
|
@@ -395,8 +401,7 @@ def get_performance_report(module_name: Optional[str] = None,
|
|
395
401
|
# Filter operations
|
396
402
|
filtered_operations = _performance_history
|
397
403
|
if module_name:
|
398
|
-
filtered_operations = [op for op in filtered_operations
|
399
|
-
if op.module_name == module_name]
|
404
|
+
filtered_operations = [op for op in filtered_operations if op.module_name == module_name]
|
400
405
|
|
401
406
|
# Get recent operations
|
402
407
|
recent_operations = filtered_operations[-last_n_operations:]
|
@@ -418,10 +423,10 @@ def get_performance_report(module_name: Optional[str] = None,
|
|
418
423
|
"failed_operations": len(failed_ops),
|
419
424
|
"success_rate_percent": (len(successful_ops) / len(recent_operations)) * 100,
|
420
425
|
"average_execution_time": round(avg_time, 2),
|
421
|
-
"average_efficiency_score": round(avg_efficiency, 1)
|
426
|
+
"average_efficiency_score": round(avg_efficiency, 1),
|
422
427
|
},
|
423
428
|
"operations": [op.to_dict() for op in recent_operations],
|
424
|
-
"recommendations": _generate_performance_recommendations(recent_operations)
|
429
|
+
"recommendations": _generate_performance_recommendations(recent_operations),
|
425
430
|
}
|
426
431
|
|
427
432
|
return report
|
@@ -435,17 +440,12 @@ def _generate_performance_recommendations(operations: List[PerformanceMetrics])
|
|
435
440
|
return recommendations
|
436
441
|
|
437
442
|
# Analyze patterns
|
438
|
-
slow_operations = [op for op in operations
|
439
|
-
|
440
|
-
|
441
|
-
if op.memory_peak_mb > 150]
|
442
|
-
high_api_operations = [op for op in operations
|
443
|
-
if op.api_calls_count > 50]
|
443
|
+
slow_operations = [op for op in operations if op.success and op.performance_ratio > 1.5]
|
444
|
+
high_memory_operations = [op for op in operations if op.memory_peak_mb > 150]
|
445
|
+
high_api_operations = [op for op in operations if op.api_calls_count > 50]
|
444
446
|
|
445
447
|
if slow_operations:
|
446
|
-
recommendations.append(
|
447
|
-
f"⚠️ {len(slow_operations)} operations exceeded target by >50% - consider optimization"
|
448
|
-
)
|
448
|
+
recommendations.append(f"⚠️ {len(slow_operations)} operations exceeded target by >50% - consider optimization")
|
449
449
|
|
450
450
|
if high_memory_operations:
|
451
451
|
recommendations.append(
|
@@ -453,16 +453,12 @@ def _generate_performance_recommendations(operations: List[PerformanceMetrics])
|
|
453
453
|
)
|
454
454
|
|
455
455
|
if high_api_operations:
|
456
|
-
recommendations.append(
|
457
|
-
f"🔄 {len(high_api_operations)} operations made >50 API calls - consider caching"
|
458
|
-
)
|
456
|
+
recommendations.append(f"🔄 {len(high_api_operations)} operations made >50 API calls - consider caching")
|
459
457
|
|
460
458
|
# Success rate recommendations
|
461
459
|
failed_ops = [op for op in operations if not op.success]
|
462
460
|
if len(failed_ops) > len(operations) * 0.1: # >10% failure rate
|
463
|
-
recommendations.append(
|
464
|
-
"❌ High failure rate detected - review error handling and retry logic"
|
465
|
-
)
|
461
|
+
recommendations.append("❌ High failure rate detected - review error handling and retry logic")
|
466
462
|
|
467
463
|
return recommendations
|
468
464
|
|
@@ -487,7 +483,7 @@ def export_performance_data(output_path: str = "performance_report.json") -> boo
|
|
487
483
|
try:
|
488
484
|
report = get_performance_report()
|
489
485
|
|
490
|
-
with open(output_path,
|
486
|
+
with open(output_path, "w") as f:
|
491
487
|
json.dump(report, f, indent=2)
|
492
488
|
|
493
489
|
print_success(f"Performance data exported to {output_path}")
|
@@ -508,5 +504,5 @@ __all__ = [
|
|
508
504
|
"reset_api_counter",
|
509
505
|
"get_performance_report",
|
510
506
|
"clear_performance_history",
|
511
|
-
"export_performance_data"
|
512
|
-
]
|
507
|
+
"export_performance_data",
|
508
|
+
]
|