azureai-optimizer
Version:
AI-Powered Azure Infrastructure Optimization via Model Context Protocol
411 lines • 18.6 kB
JavaScript
/**
* 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