UNPKG

azureai-optimizer

Version:

AI-Powered Azure Infrastructure Optimization via Model Context Protocol

411 lines 18.6 kB
/** * Performance Analysis Tool * AI-powered Azure performance optimization analysis */ // import { MonitorClient } from '@azure/arm-monitor'; import { Logger } from '../utils/logger.js'; import { MCPError, ErrorCode } from '../utils/errors.js'; export class PerformanceAnalysisTool { name = 'performance_analysis'; description = 'AI-powered Azure performance bottleneck detection and optimization'; inputSchema = { type: 'object', properties: { subscription_id: { type: 'string', description: 'Azure subscription ID to analyze' }, resource_group: { type: 'string', description: 'Optional: Specific resource group to analyze' }, resource_id: { type: 'string', description: 'Optional: Specific resource ID to analyze' }, analysis_days: { type: 'number', description: 'Number of days to analyze performance (default: 7)', default: 7, minimum: 1, maximum: 30 }, performance_threshold: { type: 'number', description: 'Performance threshold percentage (default: 80)', default: 80, minimum: 50, maximum: 95 } }, required: ['subscription_id'] }; logger; constructor(_config) { this.logger = new Logger('PerformanceAnalysisTool'); } async execute(args, _context) { const startTime = Date.now(); let apiCalls = 0; try { this.logger.info(`⚡ Starting performance analysis for subscription: ${args.subscription_id}`); // Initialize Azure clients // this._monitorClient = new MonitorClient(context.credential, args.subscription_id); // Set defaults const analysisDays = args.analysis_days || 7; const performanceThreshold = args.performance_threshold || 80; // Get resources to analyze const resourcesToAnalyze = await this.getResourcesToAnalyze(args); apiCalls++; // Analyze each resource const performanceInsights = []; for (const resource of resourcesToAnalyze) { this.logger.info(`📊 Analyzing performance for: ${resource.name}`); const insight = await this.analyzeResourcePerformance(resource, analysisDays, performanceThreshold); if (insight) { performanceInsights.push(insight); } apiCalls++; } // Perform trending analysis const trendingAnalysis = await this.performTrendingAnalysis(performanceInsights, analysisDays); // Calculate summary const summary = this.calculateSummary(performanceInsights); const result = { success: true, data: { summary, performance_insights: performanceInsights, trending_analysis: trendingAnalysis }, metadata: { execution_time: Date.now() - startTime, api_calls: apiCalls, analysis_period: `${analysisDays} days` } }; this.logger.info(`✅ Performance analysis completed`); this.logger.info(`📊 Analyzed ${summary.total_resources_analyzed} resources`); this.logger.info(`🚨 Found ${summary.performance_issues_found} performance issues`); return result; } catch (error) { this.logger.error('❌ Performance analysis failed:', error); if (error instanceof MCPError) { throw error; } throw new MCPError(ErrorCode.INTERNAL_ERROR, `Performance analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async getResourcesToAnalyze(args) { // Simplified resource discovery - in production, would use Resource Graph API const resources = []; if (args.resource_id) { // Analyze specific resource resources.push({ id: args.resource_id, name: args.resource_id.split('/').pop(), type: this.extractResourceType(args.resource_id) }); } else { // Mock resources for demonstration resources.push({ id: `/subscriptions/${args.subscription_id}/resourceGroups/production/providers/Microsoft.Compute/virtualMachines/web-server-01`, name: 'web-server-01', type: 'Microsoft.Compute/virtualMachines' }, { id: `/subscriptions/${args.subscription_id}/resourceGroups/production/providers/Microsoft.Sql/servers/sql-server-01/databases/app-db`, name: 'app-db', type: 'Microsoft.Sql/servers/databases' }); } return resources; } extractResourceType(resourceId) { const parts = resourceId.split('/'); const providerIndex = parts.findIndex(part => part === 'providers'); if (providerIndex >= 0 && providerIndex + 2 < parts.length) { return `${parts[providerIndex + 1]}/${parts[providerIndex + 2]}`; } return 'Unknown'; } async analyzeResourcePerformance(resource, days, threshold) { try { // Get performance metrics const metrics = await this.getResourceMetrics(resource.id, days); // Analyze bottlenecks const bottlenecks = this.identifyBottlenecks(metrics, threshold); // Generate recommendations const recommendations = this.generateOptimizationRecommendations(resource, metrics, bottlenecks); // Calculate performance score const performanceScore = this.calculatePerformanceScore(metrics, threshold); return { resource_id: resource.id, resource_name: resource.name, resource_type: resource.type, performance_score: performanceScore, bottlenecks: bottlenecks, optimization_recommendations: recommendations }; } catch (error) { this.logger.warn(`⚠️ Failed to analyze performance for ${resource.name}:`, error); return null; } } async getResourceMetrics(resourceId, days) { try { const endTime = new Date(); const startTime = new Date(); startTime.setDate(endTime.getDate() - days); // Get different metrics based on resource type // Metric names would be used in actual implementation if (resourceId.includes('Microsoft.Sql')) { // SQL metrics: 'cpu_percent,memory_percent,dtu_consumption_percent' } else if (resourceId.includes('Microsoft.Web')) { // Web app metrics: 'CpuPercentage,MemoryPercentage,HttpResponseTime' } // Stub implementation - actual implementation would use proper Azure Monitor API const metricsResponse = { value: [], timespan: `${startTime.toISOString()}/${endTime.toISOString()}`, interval: 'PT1H' }; return this.processPerformanceMetrics(metricsResponse); } catch (error) { this.logger.warn(`⚠️ Failed to get metrics for ${resourceId}:`, error); return this.getDefaultMetrics(); } } processPerformanceMetrics(metricsResponse) { const metrics = { cpu: { average: 0, maximum: 0, values: [] }, memory: { average: 0, maximum: 0, values: [] }, disk: { average: 0, maximum: 0, values: [] }, network: { average: 0, maximum: 0, values: [] }, response_time: { average: 0, maximum: 0, values: [] } }; if (metricsResponse.value) { metricsResponse.value.forEach((metric) => { const metricName = metric.name?.value?.toLowerCase() || ''; const timeseries = metric.timeseries?.[0]; if (timeseries?.data) { const values = timeseries.data .filter((point) => point.average !== undefined) .map((point) => ({ timestamp: point.timeStamp, average: point.average, maximum: point.maximum || point.average })); if (values.length > 0) { const avgValues = values.map((v) => v.average); const maxValues = values.map((v) => v.maximum); const average = avgValues.reduce((sum, val) => sum + val, 0) / avgValues.length; const maximum = Math.max(...maxValues); if (metricName.includes('cpu')) { metrics.cpu = { average, maximum, values: avgValues }; } else if (metricName.includes('memory')) { metrics.memory = { average, maximum, values: avgValues }; } else if (metricName.includes('disk')) { metrics.disk = { average, maximum, values: avgValues }; } else if (metricName.includes('network')) { metrics.network = { average, maximum, values: avgValues }; } else if (metricName.includes('response')) { metrics.response_time = { average, maximum, values: avgValues }; } } } }); } return metrics; } getDefaultMetrics() { return { cpu: { average: 45, maximum: 75, values: [40, 45, 50, 45, 40] }, memory: { average: 60, maximum: 80, values: [55, 60, 65, 60, 55] }, disk: { average: 30, maximum: 50, values: [25, 30, 35, 30, 25] }, network: { average: 20, maximum: 40, values: [15, 20, 25, 20, 15] }, response_time: { average: 200, maximum: 500, values: [180, 200, 220, 200, 180] } }; } identifyBottlenecks(metrics, threshold) { const bottlenecks = []; // CPU bottleneck if (metrics.cpu.average > threshold) { bottlenecks.push({ type: 'CPU', severity: this.getSeverity(metrics.cpu.average, threshold), description: `High CPU utilization detected (${metrics.cpu.average.toFixed(1)}% average, ${metrics.cpu.maximum.toFixed(1)}% peak)`, impact: 'Application performance degradation and increased response times', recommendations: [ 'Consider scaling up to a higher CPU tier', 'Optimize application code for better CPU efficiency', 'Implement CPU-intensive task scheduling during off-peak hours' ] }); } // Memory bottleneck if (metrics.memory.average > threshold) { bottlenecks.push({ type: 'Memory', severity: this.getSeverity(metrics.memory.average, threshold), description: `High memory utilization detected (${metrics.memory.average.toFixed(1)}% average, ${metrics.memory.maximum.toFixed(1)}% peak)`, impact: 'Potential memory pressure leading to performance issues', recommendations: [ 'Increase memory allocation or scale to higher memory tier', 'Optimize application memory usage and implement caching strategies', 'Review memory leaks and optimize garbage collection' ] }); } // Response time bottleneck if (metrics.response_time.average > 1000) { // 1 second threshold bottlenecks.push({ type: 'Network', severity: this.getSeverity(metrics.response_time.average / 10, 100), // Normalize to percentage description: `High response times detected (${metrics.response_time.average.toFixed(0)}ms average)`, impact: 'Poor user experience and potential timeout issues', recommendations: [ 'Implement caching strategies to reduce response times', 'Optimize database queries and API calls', 'Consider using a Content Delivery Network (CDN)' ] }); } return bottlenecks; } getSeverity(value, threshold) { const ratio = value / threshold; if (ratio >= 1.5) return 'Critical'; if (ratio >= 1.2) return 'High'; if (ratio >= 1.0) return 'Medium'; return 'Low'; } generateOptimizationRecommendations(resource, metrics, bottlenecks) { const recommendations = []; // General performance recommendations if (bottlenecks.length > 0) { recommendations.push({ title: 'Performance Monitoring Enhancement', description: 'Implement comprehensive performance monitoring and alerting', expected_improvement: 'Proactive issue detection and faster resolution', implementation_effort: 'Low', cost_impact: 'Neutral' }); } // Resource-specific recommendations if (resource.type.includes('virtualMachines')) { if (metrics.cpu.average > 70) { recommendations.push({ title: 'Virtual Machine Scale-Up', description: 'Upgrade to a higher performance VM SKU with more CPU cores', expected_improvement: '30-50% performance improvement', implementation_effort: 'Medium', cost_impact: 'Increase' }); } recommendations.push({ title: 'Auto-Scaling Implementation', description: 'Implement VM Scale Sets for automatic scaling based on demand', expected_improvement: 'Dynamic performance optimization', implementation_effort: 'High', cost_impact: 'Neutral' }); } if (resource.type.includes('Microsoft.Sql')) { recommendations.push({ title: 'Database Performance Tuning', description: 'Optimize database queries and implement proper indexing', expected_improvement: '20-40% query performance improvement', implementation_effort: 'Medium', cost_impact: 'Neutral' }); } return recommendations; } calculatePerformanceScore(metrics, threshold) { // Calculate weighted performance score const weights = { cpu: 0.3, memory: 0.3, disk: 0.2, network: 0.1, response_time: 0.1 }; let score = 100; // Deduct points for high utilization score -= Math.max(0, (metrics.cpu.average - threshold) * weights.cpu); score -= Math.max(0, (metrics.memory.average - threshold) * weights.memory); score -= Math.max(0, (metrics.disk.average - threshold) * weights.disk); score -= Math.max(0, (metrics.network.average - threshold) * weights.network); // Response time penalty (normalize to percentage) const responseTimePenalty = Math.max(0, (metrics.response_time.average - 500) / 10); score -= responseTimePenalty * weights.response_time; return Math.max(0, Math.min(100, score)); } async performTrendingAnalysis(insights, _days) { // Simplified trending analysis const avgPerformanceScore = insights.length > 0 ? insights.reduce((sum, insight) => sum + insight.performance_score, 0) / insights.length : 100; let trend = 'Stable'; if (avgPerformanceScore > 80) trend = 'Improving'; if (avgPerformanceScore < 60) trend = 'Degrading'; return { performance_trend: trend, trend_analysis: this.generateTrendAnalysis(trend, avgPerformanceScore), peak_usage_patterns: this.identifyPeakPatterns(insights) }; } generateTrendAnalysis(trend, score) { switch (trend) { case 'Improving': return `Performance is trending positively with an average score of ${score.toFixed(1)}%. Continue current optimization efforts.`; case 'Degrading': return `Performance is declining with an average score of ${score.toFixed(1)}%. Immediate attention required to address bottlenecks.`; default: return `Performance is stable with an average score of ${score.toFixed(1)}%. Monitor for any changes and optimize proactively.`; } } identifyPeakPatterns(_insights) { // Simplified peak pattern identification return [ { metric: 'CPU Usage', peak_time: '14:00-16:00', peak_value: 85, average_value: 45 }, { metric: 'Memory Usage', peak_time: '10:00-12:00', peak_value: 75, average_value: 60 } ]; } calculateSummary(insights) { const totalBottlenecks = insights.reduce((sum, insight) => sum + insight.bottlenecks.length, 0); const totalRecommendations = insights.reduce((sum, insight) => sum + insight.optimization_recommendations.length, 0); const performanceIssues = insights.filter(insight => insight.performance_score < 70).length; return { total_resources_analyzed: insights.length, performance_issues_found: performanceIssues, bottlenecks_identified: totalBottlenecks, optimization_opportunities: totalRecommendations }; } } //# sourceMappingURL=performance-analysis.js.map