Initial commit of akmon project
This commit is contained in:
758
uni_modules/ak-ai-news/services/AIPerformanceMonitor.uts
Normal file
758
uni_modules/ak-ai-news/services/AIPerformanceMonitor.uts
Normal file
@@ -0,0 +1,758 @@
|
||||
// Performance Monitor and Optimization System
|
||||
// Real-time monitoring, metrics collection, and automatic optimization
|
||||
|
||||
import { type AIProvider, type AIServiceConfig } from '../types/ai-types.uts'
|
||||
|
||||
/**
|
||||
* Performance metrics data structure
|
||||
*/
|
||||
export type PerformanceMetrics = {
|
||||
timestamp: number
|
||||
service: string
|
||||
operation: string
|
||||
provider?: AIProvider
|
||||
duration: number
|
||||
success: boolean
|
||||
error?: string
|
||||
tokensUsed?: number
|
||||
costUSD?: number
|
||||
cacheHit?: boolean
|
||||
memoryUsage?: number
|
||||
cpuUsage?: number
|
||||
networkLatency?: number
|
||||
queueSize?: number
|
||||
throughput?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* System health status
|
||||
*/
|
||||
export type SystemHealth = {
|
||||
status: 'healthy' | 'warning' | 'critical'
|
||||
score: number // 0-100
|
||||
checks: {
|
||||
apiConnectivity: boolean
|
||||
memoryUsage: number
|
||||
errorRate: number
|
||||
responseTime: number
|
||||
costBudget: number
|
||||
cacheEfficiency: number
|
||||
}
|
||||
alerts: HealthAlert[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Health alert
|
||||
*/
|
||||
export type HealthAlert = {
|
||||
id: string
|
||||
severity: 'info' | 'warning' | 'error' | 'critical'
|
||||
message: string
|
||||
timestamp: number
|
||||
source: string
|
||||
resolved: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimization recommendation
|
||||
*/
|
||||
export type OptimizationRecommendation = {
|
||||
type: 'cache' | 'provider' | 'batch' | 'model' | 'timeout' | 'retry'
|
||||
priority: 'low' | 'medium' | 'high' | 'critical'
|
||||
description: string
|
||||
expectedImpact: {
|
||||
performanceGain?: string
|
||||
costSaving?: string
|
||||
reliabilityImprovement?: string
|
||||
}
|
||||
implementation: {
|
||||
action: string
|
||||
parameters: Record<string, any>
|
||||
estimatedEffort: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performance statistics aggregation
|
||||
*/
|
||||
export type PerformanceStats = {
|
||||
timeRange: {
|
||||
start: number
|
||||
end: number
|
||||
duration: number
|
||||
}
|
||||
requests: {
|
||||
total: number
|
||||
successful: number
|
||||
failed: number
|
||||
successRate: number
|
||||
}
|
||||
timing: {
|
||||
averageLatency: number
|
||||
medianLatency: number
|
||||
p95Latency: number
|
||||
p99Latency: number
|
||||
}
|
||||
costs: {
|
||||
total: number
|
||||
average: number
|
||||
byProvider: Record<string, number>
|
||||
}
|
||||
cache: {
|
||||
hitRate: number
|
||||
totalRequests: number
|
||||
hits: number
|
||||
misses: number
|
||||
}
|
||||
errors: {
|
||||
byType: Record<string, number>
|
||||
byProvider: Record<string, number>
|
||||
topErrors: Array<{ error: string; count: number }>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performance monitoring and optimization service
|
||||
*/
|
||||
export class AIPerformanceMonitor {
|
||||
private metrics: PerformanceMetrics[] = []
|
||||
private alerts: HealthAlert[] = []
|
||||
private isMonitoring = false
|
||||
private monitoringInterval?: number
|
||||
private maxMetricsHistory = 10000
|
||||
private alertThresholds = {
|
||||
errorRate: 0.05, // 5%
|
||||
responseTime: 5000, // 5 seconds
|
||||
memoryUsage: 0.8, // 80%
|
||||
costBudget: 0.9, // 90% of daily budget
|
||||
cacheHitRate: 0.3 // 30% minimum
|
||||
}
|
||||
|
||||
constructor(
|
||||
private config: {
|
||||
monitoringInterval: number
|
||||
maxHistory: number
|
||||
alertWebhook?: string
|
||||
enableAutoOptimization: boolean
|
||||
}
|
||||
) {
|
||||
this.maxMetricsHistory = config.maxHistory
|
||||
}
|
||||
|
||||
/**
|
||||
* Start performance monitoring
|
||||
*/
|
||||
startMonitoring(): void {
|
||||
if (this.isMonitoring) {
|
||||
console.log('⚠️ Performance monitoring is already running')
|
||||
return
|
||||
}
|
||||
|
||||
this.isMonitoring = true
|
||||
console.log('🚀 Starting performance monitoring...')
|
||||
|
||||
this.monitoringInterval = setInterval(() => {
|
||||
this.collectSystemMetrics()
|
||||
this.checkSystemHealth()
|
||||
this.generateOptimizationRecommendations()
|
||||
}, this.config.monitoringInterval)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop performance monitoring
|
||||
*/
|
||||
stopMonitoring(): void {
|
||||
if (this.monitoringInterval) {
|
||||
clearInterval(this.monitoringInterval)
|
||||
this.monitoringInterval = undefined
|
||||
}
|
||||
this.isMonitoring = false
|
||||
console.log('🛑 Performance monitoring stopped')
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a performance metric
|
||||
*/
|
||||
recordMetric(metric: PerformanceMetrics): void {
|
||||
metric.timestamp = metric.timestamp || Date.now()
|
||||
this.metrics.push(metric)
|
||||
|
||||
// Maintain history limit
|
||||
if (this.metrics.length > this.maxMetricsHistory) {
|
||||
this.metrics = this.metrics.slice(-this.maxMetricsHistory)
|
||||
}
|
||||
|
||||
// Real-time analysis for critical metrics
|
||||
if (!metric.success || (metric.duration && metric.duration > 10000)) {
|
||||
this.checkForImmedateAlerts(metric)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current system health
|
||||
*/
|
||||
getSystemHealth(): SystemHealth {
|
||||
const now = Date.now()
|
||||
const recentMetrics = this.metrics.filter(m => now - m.timestamp < 300000) // Last 5 minutes
|
||||
|
||||
if (recentMetrics.length === 0) {
|
||||
return {
|
||||
status: 'warning',
|
||||
score: 50,
|
||||
checks: {
|
||||
apiConnectivity: false,
|
||||
memoryUsage: 0,
|
||||
errorRate: 0,
|
||||
responseTime: 0,
|
||||
costBudget: 0,
|
||||
cacheEfficiency: 0
|
||||
},
|
||||
alerts: this.getActiveAlerts()
|
||||
}
|
||||
}
|
||||
|
||||
const errorRate = recentMetrics.filter(m => !m.success).length / recentMetrics.length
|
||||
const avgResponseTime = recentMetrics.reduce((sum, m) => sum + m.duration, 0) / recentMetrics.length
|
||||
const cacheHitRate = this.calculateCacheHitRate(recentMetrics)
|
||||
const memoryUsage = this.getMemoryUsage()
|
||||
const costBudget = this.calculateCostBudgetUsage()
|
||||
|
||||
const checks = {
|
||||
apiConnectivity: errorRate < 0.1,
|
||||
memoryUsage,
|
||||
errorRate,
|
||||
responseTime: avgResponseTime,
|
||||
costBudget,
|
||||
cacheEfficiency: cacheHitRate
|
||||
}
|
||||
|
||||
const score = this.calculateHealthScore(checks)
|
||||
const status = this.determineHealthStatus(score, checks)
|
||||
|
||||
return {
|
||||
status,
|
||||
score,
|
||||
checks,
|
||||
alerts: this.getActiveAlerts()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get performance statistics for a time range
|
||||
*/
|
||||
getPerformanceStats(
|
||||
startTime: number,
|
||||
endTime: number
|
||||
): PerformanceStats {
|
||||
const rangeMetrics = this.metrics.filter(
|
||||
m => m.timestamp >= startTime && m.timestamp <= endTime
|
||||
)
|
||||
|
||||
if (rangeMetrics.length === 0) {
|
||||
return this.getEmptyStats(startTime, endTime)
|
||||
}
|
||||
|
||||
const successful = rangeMetrics.filter(m => m.success)
|
||||
const failed = rangeMetrics.filter(m => !m.success)
|
||||
const successRate = successful.length / rangeMetrics.length
|
||||
|
||||
// Calculate timing statistics
|
||||
const durations = rangeMetrics.map(m => m.duration).sort((a, b) => a - b)
|
||||
const averageLatency = durations.reduce((sum, d) => sum + d, 0) / durations.length
|
||||
const medianLatency = durations[Math.floor(durations.length / 2)]
|
||||
const p95Latency = durations[Math.floor(durations.length * 0.95)]
|
||||
const p99Latency = durations[Math.floor(durations.length * 0.99)]
|
||||
|
||||
// Calculate cost statistics
|
||||
const totalCost = rangeMetrics.reduce((sum, m) => sum + (m.costUSD || 0), 0)
|
||||
const averageCost = totalCost / rangeMetrics.length
|
||||
const costByProvider = this.groupCostsByProvider(rangeMetrics)
|
||||
|
||||
// Calculate cache statistics
|
||||
const cacheRequests = rangeMetrics.filter(m => m.cacheHit !== undefined)
|
||||
const cacheHits = cacheRequests.filter(m => m.cacheHit).length
|
||||
const cacheMisses = cacheRequests.length - cacheHits
|
||||
const cacheHitRate = cacheRequests.length > 0 ? cacheHits / cacheRequests.length : 0
|
||||
|
||||
// Calculate error statistics
|
||||
const errorsByType = this.groupErrorsByType(failed)
|
||||
const errorsByProvider = this.groupErrorsByProvider(failed)
|
||||
const topErrors = this.getTopErrors(failed)
|
||||
|
||||
return {
|
||||
timeRange: {
|
||||
start: startTime,
|
||||
end: endTime,
|
||||
duration: endTime - startTime
|
||||
},
|
||||
requests: {
|
||||
total: rangeMetrics.length,
|
||||
successful: successful.length,
|
||||
failed: failed.length,
|
||||
successRate
|
||||
},
|
||||
timing: {
|
||||
averageLatency,
|
||||
medianLatency,
|
||||
p95Latency,
|
||||
p99Latency
|
||||
},
|
||||
costs: {
|
||||
total: totalCost,
|
||||
average: averageCost,
|
||||
byProvider: costByProvider
|
||||
},
|
||||
cache: {
|
||||
hitRate: cacheHitRate,
|
||||
totalRequests: cacheRequests.length,
|
||||
hits: cacheHits,
|
||||
misses: cacheMisses
|
||||
},
|
||||
errors: {
|
||||
byType: errorsByType,
|
||||
byProvider: errorsByProvider,
|
||||
topErrors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get optimization recommendations
|
||||
*/
|
||||
getOptimizationRecommendations(): OptimizationRecommendation[] {
|
||||
const recommendations: OptimizationRecommendation[] = []
|
||||
const recentStats = this.getPerformanceStats(
|
||||
Date.now() - 3600000, // Last hour
|
||||
Date.now()
|
||||
)
|
||||
|
||||
// Cache optimization recommendations
|
||||
if (recentStats.cache.hitRate < 0.4) {
|
||||
recommendations.push({
|
||||
type: 'cache',
|
||||
priority: 'high',
|
||||
description: `Cache hit rate is low (${(recentStats.cache.hitRate * 100).toFixed(1)}%). Consider increasing cache size or TTL.`,
|
||||
expectedImpact: {
|
||||
performanceGain: '30-50% faster response times',
|
||||
costSaving: '20-40% reduction in AI API costs'
|
||||
},
|
||||
implementation: {
|
||||
action: 'increase_cache_size',
|
||||
parameters: {
|
||||
maxSize: Math.max(1000, recentStats.cache.totalRequests * 2),
|
||||
ttl: 3600000 // 1 hour
|
||||
},
|
||||
estimatedEffort: 'Low - Configuration change'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Provider optimization recommendations
|
||||
const providerErrors = recentStats.errors.byProvider
|
||||
const worstProvider = Object.entries(providerErrors)
|
||||
.sort(([, a], [, b]) => b - a)[0]
|
||||
|
||||
if (worstProvider && worstProvider[1] > recentStats.requests.total * 0.1) {
|
||||
recommendations.push({
|
||||
type: 'provider',
|
||||
priority: 'medium',
|
||||
description: `Provider ${worstProvider[0]} has high error rate (${worstProvider[1]} errors). Consider switching primary provider.`,
|
||||
expectedImpact: {
|
||||
reliabilityImprovement: '80-90% reduction in errors'
|
||||
},
|
||||
implementation: {
|
||||
action: 'switch_primary_provider',
|
||||
parameters: {
|
||||
newPrimary: this.recommendBestProvider(recentStats),
|
||||
fallbackProviders: ['openai', 'google', 'baidu']
|
||||
},
|
||||
estimatedEffort: 'Medium - Code changes required'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Batch processing recommendations
|
||||
if (recentStats.timing.averageLatency > 3000 && recentStats.requests.total > 100) {
|
||||
recommendations.push({
|
||||
type: 'batch',
|
||||
priority: 'medium',
|
||||
description: 'High latency with significant request volume. Consider implementing batch processing.',
|
||||
expectedImpact: {
|
||||
performanceGain: '50-70% improvement in throughput',
|
||||
costSaving: '15-25% cost reduction'
|
||||
},
|
||||
implementation: {
|
||||
action: 'enable_batch_processing',
|
||||
parameters: {
|
||||
batchSize: 10,
|
||||
batchTimeout: 1000,
|
||||
concurrency: 3
|
||||
},
|
||||
estimatedEffort: 'High - Significant code changes'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Model optimization recommendations
|
||||
if (recentStats.costs.average > 0.01) { // More than 1 cent per request
|
||||
recommendations.push({
|
||||
type: 'model',
|
||||
priority: 'low',
|
||||
description: 'Request costs are high. Consider using smaller/cheaper models for simple tasks.',
|
||||
expectedImpact: {
|
||||
costSaving: '40-60% cost reduction'
|
||||
},
|
||||
implementation: {
|
||||
action: 'implement_model_selection',
|
||||
parameters: {
|
||||
simpleTaskModel: 'gpt-3.5-turbo',
|
||||
complexTaskModel: 'gpt-4',
|
||||
costThreshold: 0.005
|
||||
},
|
||||
estimatedEffort: 'Medium - Logic implementation required'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return recommendations
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply automatic optimization
|
||||
*/
|
||||
async applyOptimizations(
|
||||
recommendations: OptimizationRecommendation[]
|
||||
): Promise<{ applied: number; failed: number; results: any[] }> {
|
||||
if (!this.config.enableAutoOptimization) {
|
||||
console.log('⚠️ Auto-optimization is disabled')
|
||||
return { applied: 0, failed: 0, results: [] }
|
||||
}
|
||||
|
||||
const results: any[] = []
|
||||
let applied = 0
|
||||
let failed = 0
|
||||
|
||||
for (const rec of recommendations) {
|
||||
try {
|
||||
const result = await this.applyOptimization(rec)
|
||||
if (result.success) {
|
||||
applied++
|
||||
console.log(`✅ Applied optimization: ${rec.description}`)
|
||||
} else {
|
||||
failed++
|
||||
console.log(`❌ Failed to apply optimization: ${rec.description} - ${result.error}`)
|
||||
}
|
||||
results.push(result)
|
||||
} catch (error) {
|
||||
failed++
|
||||
console.log(`💥 Error applying optimization: ${rec.description} - ${error}`)
|
||||
results.push({ success: false, error: String(error) })
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`🔧 Auto-optimization completed: ${applied} applied, ${failed} failed`)
|
||||
return { applied, failed, results }
|
||||
}
|
||||
|
||||
/**
|
||||
* Export performance data for external analysis
|
||||
*/
|
||||
exportPerformanceData(format: 'json' | 'csv'): string {
|
||||
if (format === 'json') {
|
||||
return JSON.stringify({
|
||||
exportTime: Date.now(),
|
||||
metrics: this.metrics,
|
||||
alerts: this.alerts,
|
||||
systemHealth: this.getSystemHealth(),
|
||||
stats: this.getPerformanceStats(Date.now() - 86400000, Date.now()) // Last 24h
|
||||
}, null, 2)
|
||||
} else {
|
||||
// CSV format
|
||||
const headers = [
|
||||
'timestamp', 'service', 'operation', 'provider', 'duration',
|
||||
'success', 'tokensUsed', 'costUSD', 'cacheHit', 'error'
|
||||
]
|
||||
|
||||
const rows = this.metrics.map(m => [
|
||||
m.timestamp,
|
||||
m.service,
|
||||
m.operation,
|
||||
m.provider || '',
|
||||
m.duration,
|
||||
m.success,
|
||||
m.tokensUsed || 0,
|
||||
m.costUSD || 0,
|
||||
m.cacheHit || false,
|
||||
m.error || ''
|
||||
])
|
||||
|
||||
return [headers, ...rows].map(row => row.join(',')).join('\n')
|
||||
}
|
||||
}
|
||||
|
||||
// Private methods for internal calculations and operations
|
||||
|
||||
private collectSystemMetrics(): void {
|
||||
const memoryUsage = this.getMemoryUsage()
|
||||
const cpuUsage = this.getCpuUsage()
|
||||
|
||||
this.recordMetric({
|
||||
timestamp: Date.now(),
|
||||
service: 'system',
|
||||
operation: 'health_check',
|
||||
duration: 0,
|
||||
success: true,
|
||||
memoryUsage,
|
||||
cpuUsage
|
||||
})
|
||||
}
|
||||
|
||||
private checkSystemHealth(): void {
|
||||
const health = this.getSystemHealth()
|
||||
|
||||
if (health.status === 'critical') {
|
||||
this.createAlert({
|
||||
severity: 'critical',
|
||||
message: `System health is critical (score: ${health.score})`,
|
||||
source: 'health_monitor',
|
||||
resolved: false
|
||||
})
|
||||
} else if (health.status === 'warning') {
|
||||
this.createAlert({
|
||||
severity: 'warning',
|
||||
message: `System health degraded (score: ${health.score})`,
|
||||
source: 'health_monitor',
|
||||
resolved: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private generateOptimizationRecommendations(): void {
|
||||
const recommendations = this.getOptimizationRecommendations()
|
||||
|
||||
if (recommendations.length > 0 && this.config.enableAutoOptimization) {
|
||||
console.log(`🔧 Found ${recommendations.length} optimization opportunities`)
|
||||
this.applyOptimizations(recommendations)
|
||||
}
|
||||
}
|
||||
|
||||
private checkForImmedateAlerts(metric: PerformanceMetrics): void {
|
||||
if (!metric.success) {
|
||||
this.createAlert({
|
||||
severity: 'error',
|
||||
message: `${metric.service} ${metric.operation} failed: ${metric.error}`,
|
||||
source: metric.service,
|
||||
resolved: false
|
||||
})
|
||||
}
|
||||
|
||||
if (metric.duration && metric.duration > 10000) {
|
||||
this.createAlert({
|
||||
severity: 'warning',
|
||||
message: `High latency detected: ${metric.service} ${metric.operation} took ${metric.duration}ms`,
|
||||
source: metric.service,
|
||||
resolved: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private createAlert(alert: Omit<HealthAlert, 'id' | 'timestamp'>): void {
|
||||
const newAlert: HealthAlert = {
|
||||
id: `alert-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
||||
timestamp: Date.now(),
|
||||
...alert
|
||||
}
|
||||
|
||||
this.alerts.push(newAlert)
|
||||
|
||||
// Keep only last 100 alerts
|
||||
if (this.alerts.length > 100) {
|
||||
this.alerts = this.alerts.slice(-100)
|
||||
}
|
||||
|
||||
console.log(`🚨 ${alert.severity.toUpperCase()}: ${alert.message}`)
|
||||
}
|
||||
|
||||
private getActiveAlerts(): HealthAlert[] {
|
||||
return this.alerts.filter(a => !a.resolved && Date.now() - a.timestamp < 3600000) // Last hour
|
||||
}
|
||||
|
||||
private calculateHealthScore(checks: any): number {
|
||||
let score = 100
|
||||
|
||||
if (checks.errorRate > this.alertThresholds.errorRate) {
|
||||
score -= (checks.errorRate - this.alertThresholds.errorRate) * 500
|
||||
}
|
||||
|
||||
if (checks.responseTime > this.alertThresholds.responseTime) {
|
||||
score -= Math.min(30, (checks.responseTime - this.alertThresholds.responseTime) / 1000 * 5)
|
||||
}
|
||||
|
||||
if (checks.memoryUsage > this.alertThresholds.memoryUsage) {
|
||||
score -= (checks.memoryUsage - this.alertThresholds.memoryUsage) * 100
|
||||
}
|
||||
|
||||
if (checks.cacheEfficiency < this.alertThresholds.cacheHitRate) {
|
||||
score -= (this.alertThresholds.cacheHitRate - checks.cacheEfficiency) * 50
|
||||
}
|
||||
|
||||
return Math.max(0, Math.min(100, score))
|
||||
}
|
||||
|
||||
private determineHealthStatus(score: number, checks: any): 'healthy' | 'warning' | 'critical' {
|
||||
if (score < 30 || checks.errorRate > 0.2 || !checks.apiConnectivity) {
|
||||
return 'critical'
|
||||
} else if (score < 70 || checks.errorRate > 0.1 || checks.responseTime > 5000) {
|
||||
return 'warning'
|
||||
} else {
|
||||
return 'healthy'
|
||||
}
|
||||
}
|
||||
|
||||
private calculateCacheHitRate(metrics: PerformanceMetrics[]): number {
|
||||
const cacheMetrics = metrics.filter(m => m.cacheHit !== undefined)
|
||||
if (cacheMetrics.length === 0) return 0
|
||||
return cacheMetrics.filter(m => m.cacheHit).length / cacheMetrics.length
|
||||
}
|
||||
|
||||
private getMemoryUsage(): number {
|
||||
// Simulated memory usage - in real implementation, use actual system metrics
|
||||
return Math.random() * 0.8 + 0.2
|
||||
}
|
||||
|
||||
private getCpuUsage(): number {
|
||||
// Simulated CPU usage - in real implementation, use actual system metrics
|
||||
return Math.random() * 0.6 + 0.1
|
||||
}
|
||||
|
||||
private calculateCostBudgetUsage(): number {
|
||||
const todayStart = new Date().setHours(0, 0, 0, 0)
|
||||
const todayMetrics = this.metrics.filter(m => m.timestamp >= todayStart)
|
||||
const todayCost = todayMetrics.reduce((sum, m) => sum + (m.costUSD || 0), 0)
|
||||
const dailyBudget = 100 // $100 daily budget - should be configurable
|
||||
return todayCost / dailyBudget
|
||||
}
|
||||
|
||||
private groupCostsByProvider(metrics: PerformanceMetrics[]): Record<string, number> {
|
||||
const costs: Record<string, number> = {}
|
||||
metrics.forEach(m => {
|
||||
if (m.provider && m.costUSD) {
|
||||
costs[m.provider] = (costs[m.provider] || 0) + m.costUSD
|
||||
}
|
||||
})
|
||||
return costs
|
||||
}
|
||||
|
||||
private groupErrorsByType(failedMetrics: PerformanceMetrics[]): Record<string, number> {
|
||||
const errors: Record<string, number> = {}
|
||||
failedMetrics.forEach(m => {
|
||||
if (m.error) {
|
||||
const errorType = this.categorizeError(m.error)
|
||||
errors[errorType] = (errors[errorType] || 0) + 1
|
||||
}
|
||||
})
|
||||
return errors
|
||||
}
|
||||
|
||||
private groupErrorsByProvider(failedMetrics: PerformanceMetrics[]): Record<string, number> {
|
||||
const errors: Record<string, number> = {}
|
||||
failedMetrics.forEach(m => {
|
||||
if (m.provider) {
|
||||
errors[m.provider] = (errors[m.provider] || 0) + 1
|
||||
}
|
||||
})
|
||||
return errors
|
||||
}
|
||||
|
||||
private getTopErrors(failedMetrics: PerformanceMetrics[]): Array<{ error: string; count: number }> {
|
||||
const errorCounts: Record<string, number> = {}
|
||||
failedMetrics.forEach(m => {
|
||||
if (m.error) {
|
||||
errorCounts[m.error] = (errorCounts[m.error] || 0) + 1
|
||||
}
|
||||
})
|
||||
|
||||
return Object.entries(errorCounts)
|
||||
.map(([error, count]) => ({ error, count }))
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, 5)
|
||||
}
|
||||
|
||||
private categorizeError(error: string): string {
|
||||
const lowerError = error.toLowerCase()
|
||||
if (lowerError.includes('timeout')) return 'timeout'
|
||||
if (lowerError.includes('rate limit')) return 'rate_limit'
|
||||
if (lowerError.includes('auth')) return 'authentication'
|
||||
if (lowerError.includes('network')) return 'network'
|
||||
if (lowerError.includes('quota')) return 'quota_exceeded'
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
private recommendBestProvider(stats: PerformanceStats): AIProvider {
|
||||
const providerPerformance = {
|
||||
openai: 0,
|
||||
google: 0,
|
||||
baidu: 0
|
||||
}
|
||||
|
||||
// Simple scoring based on error rates
|
||||
Object.entries(stats.errors.byProvider).forEach(([provider, errors]) => {
|
||||
const errorRate = errors / stats.requests.total
|
||||
providerPerformance[provider as AIProvider] = 1 - errorRate
|
||||
})
|
||||
|
||||
return Object.entries(providerPerformance)
|
||||
.sort(([, a], [, b]) => b - a)[0][0] as AIProvider
|
||||
}
|
||||
|
||||
private getEmptyStats(startTime: number, endTime: number): PerformanceStats {
|
||||
return {
|
||||
timeRange: { start: startTime, end: endTime, duration: endTime - startTime },
|
||||
requests: { total: 0, successful: 0, failed: 0, successRate: 0 },
|
||||
timing: { averageLatency: 0, medianLatency: 0, p95Latency: 0, p99Latency: 0 },
|
||||
costs: { total: 0, average: 0, byProvider: {} },
|
||||
cache: { hitRate: 0, totalRequests: 0, hits: 0, misses: 0 },
|
||||
errors: { byType: {}, byProvider: {}, topErrors: [] }
|
||||
}
|
||||
}
|
||||
|
||||
private async applyOptimization(recommendation: OptimizationRecommendation): Promise<{ success: boolean; error?: string }> {
|
||||
// Simulated optimization application
|
||||
// In real implementation, this would apply actual configuration changes
|
||||
|
||||
try {
|
||||
switch (recommendation.type) {
|
||||
case 'cache':
|
||||
// Apply cache optimization
|
||||
console.log(`🔧 Applying cache optimization: ${JSON.stringify(recommendation.implementation.parameters)}`)
|
||||
break
|
||||
case 'provider':
|
||||
// Switch provider
|
||||
console.log(`🔧 Switching to provider: ${recommendation.implementation.parameters.newPrimary}`)
|
||||
break
|
||||
case 'batch':
|
||||
// Enable batch processing
|
||||
console.log(`🔧 Enabling batch processing: batch size ${recommendation.implementation.parameters.batchSize}`)
|
||||
break
|
||||
case 'model':
|
||||
// Implement model selection
|
||||
console.log(`🔧 Implementing intelligent model selection`)
|
||||
break
|
||||
default:
|
||||
return { success: false, error: 'Unknown optimization type' }
|
||||
}
|
||||
|
||||
return { success: true }
|
||||
} catch (error) {
|
||||
return { success: false, error: String(error) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export default configuration
|
||||
export const defaultPerformanceConfig = {
|
||||
monitoringInterval: 30000, // 30 seconds
|
||||
maxHistory: 10000,
|
||||
enableAutoOptimization: false, // Disabled by default for safety
|
||||
alertWebhook: undefined
|
||||
}
|
||||
Reference in New Issue
Block a user