PerformanceDomainService.ts•7.33 kB
import { PerformanceMetric, MetricId } from '../entities/PerformanceMetric.js';
import { PerformanceAlert, AlertId, AlertType, AlertSeverity } from '../entities/PerformanceAlert.js';
export interface PerformanceMetricRepository {
  save(metric: PerformanceMetric): Promise<void>;
  findById(id: MetricId): Promise<PerformanceMetric | null>;
  findRecent(limit: number): Promise<PerformanceMetric[]>;
  findByTimeRange(startTime: Date, endTime: Date): Promise<PerformanceMetric[]>;
  clear(): Promise<void>;
}
export interface PerformanceAlertRepository {
  save(alert: PerformanceAlert): Promise<void>;
  findById(id: AlertId): Promise<PerformanceAlert | null>;
  findActive(): Promise<PerformanceAlert[]>;
  findAll(): Promise<PerformanceAlert[]>;
  findByType(type: AlertType): Promise<PerformanceAlert[]>;
}
export interface MetricsCollector {
  collectCurrentMetrics(): Promise<{
    connectionPool: any;
    query: any;
    system: any;
  }>;
}
export class PerformanceDomainService {
  constructor(
    private readonly metricRepository: PerformanceMetricRepository,
    private readonly alertRepository: PerformanceAlertRepository,
    private readonly metricsCollector: MetricsCollector
  ) {}
  async collectAndStoreMetrics(): Promise<PerformanceMetric> {
    const rawMetrics = await this.metricsCollector.collectCurrentMetrics();
    const metricId: MetricId = { value: this.generateMetricId() };
    const metric = new PerformanceMetric(
      metricId,
      new Date(),
      rawMetrics.connectionPool,
      rawMetrics.query,
      rawMetrics.system
    );
    await this.metricRepository.save(metric);
    // create alerts based on metrics
    await this.evaluateAndCreateAlerts(metric);
    return metric;
  }
  async evaluateAndCreateAlerts(metric: PerformanceMetric): Promise<PerformanceAlert[]> {
    const alerts: PerformanceAlert[] = [];
    // check connection pool health
    const poolHealth = metric.evaluateConnectionPoolHealth();
    if (poolHealth !== 'healthy') {
      const alert = this.createConnectionPoolAlert(metric, poolHealth);
      alerts.push(alert);
      await this.alertRepository.save(alert);
    }
    // check query performance
    const queryHealth = metric.evaluateQueryPerformance();
    if (queryHealth !== 'healthy') {
      const alert = this.createQueryPerformanceAlert(metric, queryHealth);
      alerts.push(alert);
      await this.alertRepository.save(alert);
    }
    // check system health
    const systemHealth = metric.evaluateSystemHealth();
    if (systemHealth !== 'healthy') {
      const alert = this.createSystemAlert(metric, systemHealth);
      alerts.push(alert);
      await this.alertRepository.save(alert);
    }
    return alerts;
  }
  async getPerformanceSummary(timeRange: string = '1h'): Promise<{
    currentMetric: PerformanceMetric | null;
    activeAlerts: PerformanceAlert[];
    overallHealth: 'healthy' | 'warning' | 'critical';
    recommendations: string[];
  }> {
    const recentMetrics = await this.metricRepository.findRecent(1);
    const currentMetric = recentMetrics[0] || null;
    const activeAlerts = await this.alertRepository.findActive();
    let overallHealth: 'healthy' | 'warning' | 'critical' = 'healthy';
    if (currentMetric) {
      overallHealth = currentMetric.getOverallHealth();
    }
    const recommendations = this.generateRecommendations(currentMetric, activeAlerts);
    return {
      currentMetric,
      activeAlerts,
      overallHealth,
      recommendations,
    };
  }
  async acknowledgeAlert(alertId: AlertId): Promise<void> {
    const alert = await this.alertRepository.findById(alertId);
    if (!alert) {
      throw new Error(`Alert with id ${alertId.value} not found`);
    }
    alert.acknowledge();
    await this.alertRepository.save(alert);
  }
  async resolveAlert(alertId: AlertId): Promise<void> {
    const alert = await this.alertRepository.findById(alertId);
    if (!alert) {
      throw new Error(`Alert with id ${alertId.value} not found`);
    }
    alert.resolve();
    await this.alertRepository.save(alert);
  }
  private createConnectionPoolAlert(
    metric: PerformanceMetric,
    health: 'warning' | 'critical'
  ): PerformanceAlert {
    const alertId: AlertId = { value: this.generateAlertId() };
    const severity: AlertSeverity = health === 'critical' ? 'critical' : 'high';
    return new PerformanceAlert(
      alertId,
      'connection_pool_high_utilization',
      severity,
      `Connection pool utilization is ${health}: ${metric.connectionPool.utilization}%`,
      {
        utilization: metric.connectionPool.utilization,
        totalConnections: metric.connectionPool.totalConnections,
        activeConnections: metric.connectionPool.activeConnections,
      }
    );
  }
  private createQueryPerformanceAlert(
    metric: PerformanceMetric,
    health: 'warning' | 'critical'
  ): PerformanceAlert {
    const alertId: AlertId = { value: this.generateAlertId() };
    const severity: AlertSeverity = health === 'critical' ? 'critical' : 'high';
    return new PerformanceAlert(
      alertId,
      'slow_query_detected',
      severity,
      `Query performance is ${health}: avg ${metric.query.averageExecutionTime}ms`,
      {
        averageExecutionTime: metric.query.averageExecutionTime,
        slowQueries: metric.query.slowQueries,
        totalQueries: metric.query.totalQueries,
      }
    );
  }
  private createSystemAlert(
    metric: PerformanceMetric,
    health: 'warning' | 'critical'
  ): PerformanceAlert {
    const alertId: AlertId = { value: this.generateAlertId() };
    const severity: AlertSeverity = health === 'critical' ? 'critical' : 'high';
    return new PerformanceAlert(
      alertId,
      'high_cpu_usage',
      severity,
      `System resources are ${health}`,
      {
        cpuUsage: metric.system.cpuUsage,
        memoryUsage: metric.system.memoryUsage,
        diskUsage: metric.system.diskUsage,
      }
    );
  }
  private generateRecommendations(
    currentMetric: PerformanceMetric | null,
    activeAlerts: PerformanceAlert[]
  ): string[] {
    const recommendations: string[] = [];
    if (!currentMetric) {
      recommendations.push(
        'No current metrics available. Start monitoring to get recommendations.'
      );
      return recommendations;
    }
    // connection pool recommendations
    if (currentMetric.connectionPool.utilization > 80) {
      recommendations.push('Consider increasing connection pool size');
    }
    // query performance recommendations
    if (currentMetric.query.averageExecutionTime > 2000) {
      recommendations.push('Review and optimize slow queries');
      recommendations.push('Consider adding database indexes');
    }
    // system resource recommendations
    if (currentMetric.system.cpuUsage > 70) {
      recommendations.push('Monitor CPU usage and consider scaling resources');
    }
    if (currentMetric.system.memoryUsage > 70) {
      recommendations.push('Monitor memory usage and consider increasing available memory');
    }
    return recommendations;
  }
  private generateMetricId(): string {
    return `metric_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
  private generateAlertId(): string {
    return `alert_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
}