{"version":3,"file":"regression-detector.mjs","sources":["../../../../src/lib/performance/monitoring/regression-detector.ts"],"sourcesContent":["/**\n * @file Performance Regression Detector\n * @description Statistical analysis to detect performance regressions in real-time.\n * Uses moving averages, standard deviation, and trend analysis to identify\n * significant degradations in application performance.\n *\n * Features:\n * - Statistical regression detection\n * - Baseline establishment\n * - Trend analysis\n * - Anomaly detection\n * - Alert thresholds\n * - Historical comparison\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Regression severity level\n */\nexport type RegressionSeverity = 'minor' | 'moderate' | 'severe' | 'critical';\n\n/**\n * Regression status\n */\nexport type RegressionStatus = 'stable' | 'improving' | 'regressing' | 'anomaly';\n\n/**\n * Metric sample for analysis\n */\nexport interface MetricSample {\n  /** Metric name */\n  name: string;\n  /** Metric value */\n  value: number;\n  /** Timestamp */\n  timestamp: number;\n  /** Additional context */\n  context?: Record<string, unknown>;\n}\n\n/**\n * Baseline statistics for a metric\n */\nexport interface MetricBaseline {\n  /** Metric name */\n  name: string;\n  /** Mean value */\n  mean: number;\n  /** Standard deviation */\n  standardDeviation: number;\n  /** Median value */\n  median: number;\n  /** 95th percentile */\n  p95: number;\n  /** 99th percentile */\n  p99: number;\n  /** Minimum value */\n  min: number;\n  /** Maximum value */\n  max: number;\n  /** Sample count */\n  sampleCount: number;\n  /** Timestamp when baseline was established */\n  establishedAt: number;\n  /** Last updated timestamp */\n  updatedAt: number;\n}\n\n/**\n * Detected regression event\n */\nexport interface RegressionEvent {\n  /** Unique event ID */\n  id: string;\n  /** Metric name */\n  metric: string;\n  /** Current value */\n  currentValue: number;\n  /** Baseline value (mean) */\n  baselineValue: number;\n  /** Percentage deviation from baseline */\n  deviation: number;\n  /** Z-score (standard deviations from mean) */\n  zScore: number;\n  /** Regression severity */\n  severity: RegressionSeverity;\n  /** Detection timestamp */\n  timestamp: number;\n  /** Number of consecutive regression samples */\n  consecutiveRegressions: number;\n  /** Additional context */\n  context?: Record<string, unknown>;\n}\n\n/**\n * Trend analysis result\n */\nexport interface TrendAnalysis {\n  /** Metric name */\n  metric: string;\n  /** Trend direction */\n  direction: 'improving' | 'stable' | 'degrading';\n  /** Trend strength (0-1) */\n  strength: number;\n  /** Slope of linear regression */\n  slope: number;\n  /** Predicted value at next interval */\n  predictedNext: number;\n  /** Correlation coefficient (R-squared) */\n  rSquared: number;\n  /** Analysis period in samples */\n  periodSamples: number;\n  /** Timestamp */\n  timestamp: number;\n}\n\n/**\n * Anomaly detection result\n */\nexport interface AnomalyResult {\n  /** Is this value an anomaly */\n  isAnomaly: boolean;\n  /** Anomaly score (higher = more anomalous) */\n  score: number;\n  /** Z-score of the value */\n  zScore: number;\n  /** Is it an upper outlier */\n  isUpperOutlier: boolean;\n  /** Is it a lower outlier */\n  isLowerOutlier: boolean;\n  /** Expected range */\n  expectedRange: { min: number; max: number };\n}\n\n/**\n * Regression detection configuration\n */\nexport interface RegressionDetectorConfig {\n  /** Enable regression detection */\n  enabled: boolean;\n  /** Minimum samples required for baseline */\n  minBaselineSamples: number;\n  /** Maximum samples to store per metric */\n  maxSamplesPerMetric: number;\n  /** Z-score threshold for regression (default: 2.0) */\n  zScoreThreshold: number;\n  /** Percentage threshold for regression (default: 0.15 = 15%) */\n  percentageThreshold: number;\n  /** Consecutive regressions required to trigger alert */\n  consecutiveThreshold: number;\n  /** Baseline recalculation interval in ms */\n  baselineUpdateInterval: number;\n  /** Trend analysis window size */\n  trendWindowSize: number;\n  /** Enable anomaly filtering */\n  filterAnomalies: boolean;\n  /** Anomaly score threshold */\n  anomalyThreshold: number;\n  /** Severity thresholds (deviation percentages) */\n  severityThresholds: {\n    minor: number;\n    moderate: number;\n    severe: number;\n    critical: number;\n  };\n  /** Callback for regression events */\n  onRegression?: (event: RegressionEvent) => void;\n  /** Callback for recovery events */\n  onRecovery?: (metric: string, baseline: MetricBaseline) => void;\n  /** Debug mode */\n  debug: boolean;\n}\n\n/**\n * Regression detector state summary\n */\nexport interface DetectorSummary {\n  /** Total metrics tracked */\n  metricsTracked: number;\n  /** Metrics with established baselines */\n  metricsWithBaselines: number;\n  /** Metrics currently regressing */\n  regressingMetrics: string[];\n  /** Total regressions detected */\n  totalRegressions: number;\n  /** Recent regressions (last 24h) */\n  recentRegressions: RegressionEvent[];\n  /** Overall system status */\n  status: RegressionStatus;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_CONFIG: RegressionDetectorConfig = {\n  enabled: true,\n  minBaselineSamples: 30,\n  maxSamplesPerMetric: 1000,\n  zScoreThreshold: 2.0,\n  percentageThreshold: 0.15,\n  consecutiveThreshold: 3,\n  baselineUpdateInterval: 3600000, // 1 hour\n  trendWindowSize: 20,\n  filterAnomalies: true,\n  anomalyThreshold: 3.0,\n  severityThresholds: {\n    minor: 0.1, // 10%\n    moderate: 0.25, // 25%\n    severe: 0.5, // 50%\n    critical: 1.0, // 100%\n  },\n  debug: false,\n};\n\n// ============================================================================\n// Statistical Utilities\n// ============================================================================\n\n/**\n * Calculate mean of an array\n */\nfunction calculateMean(values: number[]): number {\n  if (values.length === 0) return 0;\n  return values.reduce((sum, v) => sum + v, 0) / values.length;\n}\n\n/**\n * Calculate standard deviation\n */\nfunction calculateStandardDeviation(values: number[], mean?: number): number {\n  if (values.length < 2) return 0;\n  const m = mean ?? calculateMean(values);\n  const squaredDiffs = values.map((v) => Math.pow(v - m, 2));\n  return Math.sqrt(squaredDiffs.reduce((sum, v) => sum + v, 0) / (values.length - 1));\n}\n\n/**\n * Calculate median\n */\nfunction calculateMedian(values: number[]): number {\n  if (values.length === 0) return 0;\n  const sorted = [...values].sort((a, b) => a - b);\n  const mid = Math.floor(sorted.length / 2);\n  return sorted.length % 2 === 0\n    ? ((sorted[mid - 1] ?? 0) + (sorted[mid] ?? 0)) / 2\n    : (sorted[mid] ?? 0);\n}\n\n/**\n * Calculate percentile\n */\nfunction calculatePercentile(values: number[], percentile: number): number {\n  if (values.length === 0) return 0;\n  const sorted = [...values].sort((a, b) => a - b);\n  const index = (percentile / 100) * (sorted.length - 1);\n  const lower = Math.floor(index);\n  const upper = Math.ceil(index);\n  if (lower === upper) return sorted[lower] ?? 0;\n  return (sorted[lower] ?? 0) + ((sorted[upper] ?? 0) - (sorted[lower] ?? 0)) * (index - lower);\n}\n\n/**\n * Calculate Z-score\n */\nfunction calculateZScore(value: number, mean: number, stdDev: number): number {\n  if (stdDev === 0) return 0;\n  return (value - mean) / stdDev;\n}\n\n/**\n * Calculate linear regression slope\n */\nfunction calculateLinearRegressionSlope(values: number[]): { slope: number; rSquared: number } {\n  if (values.length < 2) return { slope: 0, rSquared: 0 };\n\n  const n = values.length;\n  const xMean = (n - 1) / 2; // Mean of indices 0, 1, 2, ..., n-1\n  const yMean = calculateMean(values);\n\n  let numerator = 0;\n  let denominator = 0;\n  let ssTotal = 0;\n\n  for (let i = 0; i < n; i++) {\n    const xDiff = i - xMean;\n    const yDiff = (values[i] ?? 0) - yMean;\n    numerator += xDiff * yDiff;\n    denominator += xDiff * xDiff;\n    ssTotal += yDiff * yDiff;\n  }\n\n  const slope = denominator !== 0 ? numerator / denominator : 0;\n\n  // Calculate R-squared\n  let ssResidual = 0;\n  for (let i = 0; i < n; i++) {\n    const predicted = yMean + slope * (i - xMean);\n    ssResidual += Math.pow((values[i] ?? 0) - predicted, 2);\n  }\n\n  const rSquared = ssTotal !== 0 ? 1 - ssResidual / ssTotal : 0;\n\n  return { slope, rSquared: Math.max(0, Math.min(1, rSquared)) };\n}\n\n// ============================================================================\n// Regression Detector Class\n// ============================================================================\n\n/**\n * Performance regression detection engine\n */\nexport class RegressionDetector {\n  private config: RegressionDetectorConfig;\n  private samples: Map<string, MetricSample[]> = new Map();\n  private baselines: Map<string, MetricBaseline> = new Map();\n  private consecutiveCounts: Map<string, number> = new Map();\n  private regressionHistory: RegressionEvent[] = [];\n  private baselineUpdateTimers: Map<string, number> = new Map();\n  private idCounter = 0;\n\n  constructor(config: Partial<RegressionDetectorConfig> = {}) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n  }\n\n  /**\n   * Record a metric sample\n   */\n  recordSample(sample: MetricSample): RegressionEvent | null {\n    if (!this.config.enabled) return null;\n\n    const { name, value, timestamp } = sample;\n\n    // Initialize sample array if needed\n    if (!this.samples.has(name)) {\n      this.samples.set(name, []);\n    }\n\n    const samples = this.samples.get(name);\n    if (!samples) return null;\n    samples.push({ ...sample, timestamp: timestamp ?? Date.now() });\n\n    // Trim samples if exceeding max\n    if (samples.length > this.config.maxSamplesPerMetric) {\n      samples.shift();\n    }\n\n    // Check if we need to establish/update baseline\n    this.maybeUpdateBaseline(name);\n\n    // Check for regression\n    const baseline = this.baselines.get(name);\n    if (!baseline) return null;\n\n    // Filter anomalies if enabled\n    if (this.config.filterAnomalies) {\n      const anomaly = this.detectAnomaly(value, baseline);\n      if (anomaly.isAnomaly) {\n        this.log(`Anomaly detected for ${name}: ${value} (score: ${anomaly.score.toFixed(2)})`);\n        return null;\n      }\n    }\n\n    // Check for regression\n    return this.checkRegression(name, value, baseline, sample.context);\n  }\n\n  /**\n   * Get or establish baseline for a metric\n   */\n  getBaseline(metric: string): MetricBaseline | null {\n    return this.baselines.get(metric) ?? null;\n  }\n\n  /**\n   * Manually set baseline for a metric\n   */\n  setBaseline(metric: string, baseline: Partial<MetricBaseline>): void {\n    const existing = this.baselines.get(metric);\n    const now = Date.now();\n\n    this.baselines.set(metric, {\n      name: metric,\n      mean: baseline.mean ?? existing?.mean ?? 0,\n      standardDeviation: baseline.standardDeviation ?? existing?.standardDeviation ?? 0,\n      median: baseline.median ?? existing?.median ?? 0,\n      p95: baseline.p95 ?? existing?.p95 ?? 0,\n      p99: baseline.p99 ?? existing?.p99 ?? 0,\n      min: baseline.min ?? existing?.min ?? 0,\n      max: baseline.max ?? existing?.max ?? Infinity,\n      sampleCount: baseline.sampleCount ?? existing?.sampleCount ?? 0,\n      establishedAt: existing?.establishedAt ?? now,\n      updatedAt: now,\n    });\n  }\n\n  /**\n   * Perform trend analysis for a metric\n   */\n  analyzeTrend(metric: string): TrendAnalysis | null {\n    const samples = this.samples.get(metric);\n    if (!samples || samples.length < this.config.trendWindowSize) {\n      return null;\n    }\n\n    const recentSamples = samples.slice(-this.config.trendWindowSize);\n    const values = recentSamples.map((s) => s.value);\n    const { slope, rSquared } = calculateLinearRegressionSlope(values);\n\n    const mean = calculateMean(values);\n    const normalizedSlope = mean !== 0 ? slope / mean : 0;\n\n    // Determine direction based on slope\n    let direction: 'improving' | 'stable' | 'degrading';\n    const slopeThreshold = 0.01; // 1% change per sample\n\n    if (Math.abs(normalizedSlope) < slopeThreshold) {\n      direction = 'stable';\n    } else if (normalizedSlope < 0) {\n      // Negative slope = values decreasing = improving (for most metrics)\n      direction = 'improving';\n    } else {\n      direction = 'degrading';\n    }\n\n    // Calculate strength based on R-squared and slope magnitude\n    const strength = Math.min(1, rSquared * Math.abs(normalizedSlope) * 10);\n\n    // Predict next value\n    const lastValue = values[values.length - 1];\n    const predictedNext = (lastValue ?? 0) + slope;\n\n    return {\n      metric,\n      direction,\n      strength,\n      slope,\n      predictedNext: Math.max(0, predictedNext),\n      rSquared,\n      periodSamples: values.length,\n      timestamp: Date.now(),\n    };\n  }\n\n  /**\n   * Detect anomalies in a value\n   */\n  detectAnomaly(value: number, baseline: MetricBaseline): AnomalyResult {\n    const zScore = calculateZScore(value, baseline.mean, baseline.standardDeviation);\n    const absZScore = Math.abs(zScore);\n\n    // Calculate anomaly score (normalized)\n    const score = Math.min(absZScore / this.config.anomalyThreshold, 2);\n\n    // Determine expected range (3 sigma)\n    const rangeMultiplier = 3;\n    const expectedMin = baseline.mean - rangeMultiplier * baseline.standardDeviation;\n    const expectedMax = baseline.mean + rangeMultiplier * baseline.standardDeviation;\n\n    return {\n      isAnomaly: absZScore > this.config.anomalyThreshold,\n      score,\n      zScore,\n      isUpperOutlier: zScore > this.config.anomalyThreshold,\n      isLowerOutlier: zScore < -this.config.anomalyThreshold,\n      expectedRange: {\n        min: Math.max(0, expectedMin),\n        max: expectedMax,\n      },\n    };\n  }\n\n  /**\n   * Get regression history\n   */\n  getRegressionHistory(limit?: number): RegressionEvent[] {\n    const history = [...this.regressionHistory].reverse();\n    return limit !== null && limit !== undefined ? history.slice(0, limit) : history;\n  }\n\n  /**\n   * Get summary of detector state\n   */\n  getSummary(): DetectorSummary {\n    const recentCutoff = Date.now() - 24 * 60 * 60 * 1000; // 24 hours\n    const recentRegressions = this.regressionHistory.filter((r) => r.timestamp > recentCutoff);\n\n    const regressingMetrics: string[] = [];\n    for (const [metric, count] of this.consecutiveCounts) {\n      if (count >= this.config.consecutiveThreshold) {\n        regressingMetrics.push(metric);\n      }\n    }\n\n    // Determine overall status\n    let status: RegressionStatus = 'stable';\n    if (regressingMetrics.length > 0) {\n      status = 'regressing';\n    } else {\n      // Check if any metrics are improving\n      let improvingCount = 0;\n      for (const metric of this.baselines.keys()) {\n        const trend = this.analyzeTrend(metric);\n        if (trend?.direction === 'improving') {\n          improvingCount++;\n        }\n      }\n      if (improvingCount > this.baselines.size / 2) {\n        status = 'improving';\n      }\n    }\n\n    return {\n      metricsTracked: this.samples.size,\n      metricsWithBaselines: this.baselines.size,\n      regressingMetrics,\n      totalRegressions: this.regressionHistory.length,\n      recentRegressions,\n      status,\n    };\n  }\n\n  /**\n   * Reset detector state for a specific metric\n   */\n  resetMetric(metric: string): void {\n    this.samples.delete(metric);\n    this.baselines.delete(metric);\n    this.consecutiveCounts.delete(metric);\n    this.baselineUpdateTimers.delete(metric);\n  }\n\n  /**\n   * Reset all detector state\n   */\n  reset(): void {\n    this.samples.clear();\n    this.baselines.clear();\n    this.consecutiveCounts.clear();\n    this.regressionHistory = [];\n    this.baselineUpdateTimers.clear();\n  }\n\n  /**\n   * Export current state for persistence\n   */\n  exportState(): {\n    baselines: Record<string, MetricBaseline>;\n    consecutiveCounts: Record<string, number>;\n  } {\n    return {\n      baselines: Object.fromEntries(this.baselines),\n      consecutiveCounts: Object.fromEntries(this.consecutiveCounts),\n    };\n  }\n\n  /**\n   * Import persisted state\n   */\n  importState(state: {\n    baselines?: Record<string, MetricBaseline>;\n    consecutiveCounts?: Record<string, number>;\n  }): void {\n    if (state.baselines) {\n      this.baselines = new Map(Object.entries(state.baselines));\n    }\n    if (state.consecutiveCounts) {\n      this.consecutiveCounts = new Map(Object.entries(state.consecutiveCounts));\n    }\n  }\n\n  // ============================================================================\n  // Private Methods\n  // ============================================================================\n\n  private maybeUpdateBaseline(metric: string): void {\n    const samples = this.samples.get(metric);\n    if (!samples) return;\n\n    const existing = this.baselines.get(metric);\n    const now = Date.now();\n\n    // Check if we should update\n    const shouldUpdate =\n      !existing ||\n      (samples.length >= this.config.minBaselineSamples &&\n        now - (existing?.updatedAt ?? 0) > this.config.baselineUpdateInterval);\n\n    if (!shouldUpdate) return;\n    if (samples.length < this.config.minBaselineSamples) return;\n\n    // Calculate new baseline\n    const values = samples.map((s) => s.value);\n    const mean = calculateMean(values);\n    const standardDeviation = calculateStandardDeviation(values, mean);\n    const median = calculateMedian(values);\n    const p95 = calculatePercentile(values, 95);\n    const p99 = calculatePercentile(values, 99);\n    const min = Math.min(...values);\n    const max = Math.max(...values);\n\n    const baseline: MetricBaseline = {\n      name: metric,\n      mean,\n      standardDeviation,\n      median,\n      p95,\n      p99,\n      min,\n      max,\n      sampleCount: values.length,\n      establishedAt: existing?.establishedAt ?? now,\n      updatedAt: now,\n    };\n\n    this.baselines.set(metric, baseline);\n    this.log(\n      `Baseline updated for ${metric}: mean=${mean.toFixed(2)}, stdDev=${standardDeviation.toFixed(2)}`\n    );\n  }\n\n  private checkRegression(\n    metric: string,\n    value: number,\n    baseline: MetricBaseline,\n    context?: Record<string, unknown>\n  ): RegressionEvent | null {\n    const zScore = calculateZScore(value, baseline.mean, baseline.standardDeviation);\n    const deviation = baseline.mean !== 0 ? (value - baseline.mean) / baseline.mean : 0;\n\n    // Check if this is a regression (higher values are worse for most metrics)\n    const isRegression =\n      zScore > this.config.zScoreThreshold || deviation > this.config.percentageThreshold;\n\n    if (isRegression) {\n      // Increment consecutive count\n      const currentCount = (this.consecutiveCounts.get(metric) ?? 0) + 1;\n      this.consecutiveCounts.set(metric, currentCount);\n\n      // Only create event if we've hit the threshold\n      if (currentCount >= this.config.consecutiveThreshold) {\n        const severity = this.calculateSeverity(deviation);\n\n        const event: RegressionEvent = {\n          id: this.generateId(),\n          metric,\n          currentValue: value,\n          baselineValue: baseline.mean,\n          deviation: deviation * 100, // Convert to percentage\n          zScore,\n          severity,\n          timestamp: Date.now(),\n          consecutiveRegressions: currentCount,\n          context,\n        };\n\n        this.regressionHistory.push(event);\n        this.config.onRegression?.(event);\n        this.log(`Regression detected for ${metric}: ${(deviation * 100).toFixed(1)}% deviation`);\n\n        return event;\n      }\n    } else {\n      // Reset consecutive count on recovery\n      const previousCount = this.consecutiveCounts.get(metric) ?? 0;\n      if (previousCount >= this.config.consecutiveThreshold) {\n        this.config.onRecovery?.(metric, baseline);\n        this.log(`Recovery detected for ${metric}`);\n      }\n      this.consecutiveCounts.set(metric, 0);\n    }\n\n    return null;\n  }\n\n  private calculateSeverity(deviation: number): RegressionSeverity {\n    const absDeviation = Math.abs(deviation);\n    const thresholds = this.config.severityThresholds;\n\n    if (absDeviation >= thresholds.critical) return 'critical';\n    if (absDeviation >= thresholds.severe) return 'severe';\n    if (absDeviation >= thresholds.moderate) return 'moderate';\n    return 'minor';\n  }\n\n  private generateId(): string {\n    return `reg-${Date.now()}-${++this.idCounter}`;\n  }\n\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      console.info(`[RegressionDetector] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet detectorInstance: RegressionDetector | null = null;\n\n/**\n * Get or create the global regression detector\n */\nexport function getRegressionDetector(\n  config?: Partial<RegressionDetectorConfig>\n): RegressionDetector {\n  detectorInstance ??= new RegressionDetector(config);\n  return detectorInstance;\n}\n\n/**\n * Reset the detector instance\n */\nexport function resetRegressionDetector(): void {\n  detectorInstance?.reset();\n  detectorInstance = null;\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Record a performance sample\n */\nexport function recordPerformanceSample(\n  metric: string,\n  value: number,\n  context?: Record<string, unknown>\n): RegressionEvent | null {\n  return getRegressionDetector().recordSample({\n    name: metric,\n    value,\n    timestamp: Date.now(),\n    context,\n  });\n}\n\n/**\n * Analyze performance trend for a metric\n */\nexport function analyzePerformanceTrend(metric: string): TrendAnalysis | null {\n  return getRegressionDetector().analyzeTrend(metric);\n}\n\n/**\n * Get current regression summary\n */\nexport function getRegressionSummary(): DetectorSummary {\n  return getRegressionDetector().getSummary();\n}\n"],"names":["DEFAULT_CONFIG","calculateMean","values","sum","v","calculateStandardDeviation","mean","m","squaredDiffs","calculateMedian","sorted","a","b","mid","calculatePercentile","percentile","index","lower","upper","calculateZScore","value","stdDev","calculateLinearRegressionSlope","n","xMean","yMean","numerator","denominator","ssTotal","i","xDiff","yDiff","slope","ssResidual","predicted","rSquared","RegressionDetector","config","sample","name","timestamp","samples","baseline","anomaly","metric","existing","now","s","normalizedSlope","direction","strength","predictedNext","zScore","absZScore","score","rangeMultiplier","expectedMin","expectedMax","limit","history","recentCutoff","recentRegressions","r","regressingMetrics","count","status","improvingCount","state","standardDeviation","median","p95","p99","min","max","context","deviation","currentCount","severity","event","absDeviation","thresholds","message","args","detectorInstance","getRegressionDetector","resetRegressionDetector","recordPerformanceSample","analyzePerformanceTrend","getRegressionSummary"],"mappings":"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"}