{"version":3,"file":"api-metrics.mjs","sources":["../../../../src/lib/api/advanced/api-metrics.ts"],"sourcesContent":["/**\n * API Metrics\n *\n * Collects and reports API performance metrics including\n * latency, error rates, and throughput.\n *\n * @module api/advanced/api-metrics\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Single request metric.\n */\nexport interface RequestMetric {\n  /** Request URL/endpoint */\n  endpoint: string;\n  /** HTTP method */\n  method: string;\n  /** Response status code */\n  status: number;\n  /** Request duration in milliseconds */\n  duration: number;\n  /** Request timestamp */\n  timestamp: number;\n  /** Whether request succeeded */\n  success: boolean;\n  /** Error message if failed */\n  error?: string;\n  /** Request size in bytes */\n  requestSize?: number;\n  /** Response size in bytes */\n  responseSize?: number;\n  /** Correlation ID */\n  correlationId?: string;\n  /** Custom tags */\n  tags?: Record<string, string>;\n}\n\n/**\n * Aggregated metrics for an endpoint.\n */\nexport interface EndpointMetrics {\n  /** Endpoint path */\n  endpoint: string;\n  /** Total request count */\n  totalRequests: number;\n  /** Successful requests */\n  successCount: number;\n  /** Failed requests */\n  errorCount: number;\n  /** Success rate (0-1) */\n  successRate: number;\n  /** Average duration in ms */\n  avgDuration: number;\n  /** Minimum duration in ms */\n  minDuration: number;\n  /** Maximum duration in ms */\n  maxDuration: number;\n  /** P50 latency in ms */\n  p50Latency: number;\n  /** P90 latency in ms */\n  p90Latency: number;\n  /** P95 latency in ms */\n  p95Latency: number;\n  /** P99 latency in ms */\n  p99Latency: number;\n  /** Status code distribution */\n  statusCodes: Record<number, number>;\n  /** Error distribution */\n  errors: Record<string, number>;\n  /** Last request timestamp */\n  lastRequestAt: number;\n  /** Requests per second (recent) */\n  requestsPerSecond: number;\n}\n\n/**\n * Overall API metrics.\n */\nexport interface OverallMetrics {\n  /** Total requests across all endpoints */\n  totalRequests: number;\n  /** Total successful requests */\n  totalSuccess: number;\n  /** Total failed requests */\n  totalErrors: number;\n  /** Overall success rate */\n  successRate: number;\n  /** Overall average duration */\n  avgDuration: number;\n  /** Overall P95 latency */\n  p95Latency: number;\n  /** Total requests per second */\n  requestsPerSecond: number;\n  /** Unique endpoints count */\n  endpointCount: number;\n  /** Metrics collection start time */\n  collectionStartedAt: number;\n  /** Time window in milliseconds */\n  windowMs: number;\n}\n\n/**\n * Metrics collector configuration.\n */\nexport interface MetricsConfig {\n  /** Maximum number of metrics to store */\n  maxMetrics?: number;\n  /** Time window for aggregation (ms) */\n  windowMs?: number;\n  /** Flush interval for reporters (ms) */\n  flushInterval?: number;\n  /** Enable detailed per-request storage */\n  enableDetailedMetrics?: boolean;\n  /** Endpoints to exclude from collection */\n  excludeEndpoints?: string[];\n  /** Custom metric reporter */\n  reporter?: MetricsReporter;\n}\n\n/**\n * Metrics reporter interface.\n */\nexport interface MetricsReporter {\n  /** Report a single metric */\n  report: (metric: RequestMetric) => void;\n  /** Flush all metrics */\n  flush: (metrics: RequestMetric[]) => void;\n  /** Report aggregated metrics */\n  reportAggregated?: (metrics: OverallMetrics) => void;\n}\n\n// =============================================================================\n// API Metrics Collector Class\n// =============================================================================\n\n/**\n * API Metrics Collector for performance monitoring.\n *\n * @example\n * ```typescript\n * const metrics = new APIMetricsCollector({\n *   maxMetrics: 10000,\n *   windowMs: 60000,\n *   reporter: {\n *     report: (metric) => console.log(metric),\n *     flush: (metrics) => sendToAnalytics(metrics),\n *   },\n * });\n *\n * // Record a metric\n * metrics.record({\n *   endpoint: '/users',\n *   method: 'GET',\n *   status: 200,\n *   duration: 150,\n *   timestamp: Date.now(),\n *   success: true,\n * });\n *\n * // Get endpoint metrics\n * const userMetrics = metrics.getEndpointMetrics('/users');\n * console.log(`P95 latency: ${userMetrics.p95Latency}ms`);\n * ```\n */\nexport class APIMetricsCollector {\n  private config: Required<MetricsConfig>;\n  private metrics: RequestMetric[];\n  private endpointCache: Map<string, number[]>;\n  private collectionStartedAt: number;\n  private readonly flushTimer?: ReturnType<typeof setInterval>;\n\n  /**\n   * Create a new metrics collector.\n   *\n   * @param config - Collector configuration\n   */\n  constructor(config: MetricsConfig = {}) {\n    this.config = {\n      maxMetrics: 10000,\n      windowMs: 300000, // 5 minutes\n      flushInterval: 60000, // 1 minute\n      enableDetailedMetrics: true,\n      excludeEndpoints: [],\n      reporter: { report: () => {}, flush: () => {} },\n      ...config,\n    };\n\n    this.metrics = [];\n    this.endpointCache = new Map();\n    this.collectionStartedAt = Date.now();\n\n    // Start flush timer\n    if (this.config.flushInterval > 0) {\n      this.flushTimer = setInterval(() => {\n        this.flush();\n      }, this.config.flushInterval);\n    }\n  }\n\n  // ===========================================================================\n  // Recording Methods\n  // ===========================================================================\n\n  /**\n   * Record a request metric.\n   *\n   * @param metric - Metric to record\n   */\n  record(metric: RequestMetric): void {\n    // Check exclusions\n    if (this.shouldExclude(metric.endpoint)) {\n      return;\n    }\n\n    // Store metric\n    if (this.config.enableDetailedMetrics) {\n      this.metrics.push(metric);\n\n      // Enforce max size\n      if (this.metrics.length > this.config.maxMetrics) {\n        this.metrics = this.metrics.slice(-this.config.maxMetrics);\n      }\n    }\n\n    // Update endpoint cache for quick aggregation\n    const cacheKey = this.getEndpointKey(metric.endpoint, metric.method);\n    const durations = this.endpointCache.get(cacheKey) ?? [];\n    durations.push(metric.duration);\n\n    // Keep only recent durations\n    if (durations.length > 1000) {\n      durations.splice(0, durations.length - 1000);\n    }\n\n    this.endpointCache.set(cacheKey, durations);\n\n    // Report to reporter\n    this.config.reporter.report(metric);\n  }\n\n  /**\n   * Create a timing wrapper for requests.\n   *\n   * @param endpoint - Request endpoint\n   * @param method - HTTP method\n   * @param tags - Custom tags\n   * @returns Timing functions\n   */\n  startTiming(\n    endpoint: string,\n    method: string,\n    tags?: Record<string, string>\n  ): {\n    success: (status: number, responseSize?: number) => void;\n    error: (error: Error, status?: number) => void;\n  } {\n    const startTime = Date.now();\n    const correlationId = crypto.randomUUID();\n\n    return {\n      success: (status: number, responseSize?: number) => {\n        this.record({\n          endpoint,\n          method,\n          status,\n          duration: Date.now() - startTime,\n          timestamp: startTime,\n          success: true,\n          responseSize,\n          correlationId,\n          tags,\n        });\n      },\n      error: (error: Error, status = 0) => {\n        this.record({\n          endpoint,\n          method,\n          status,\n          duration: Date.now() - startTime,\n          timestamp: startTime,\n          success: false,\n          error: error.message,\n          correlationId,\n          tags,\n        });\n      },\n    };\n  }\n\n  // ===========================================================================\n  // Aggregation Methods\n  // ===========================================================================\n\n  /**\n   * Get metrics for a specific endpoint.\n   *\n   * @param endpoint - Endpoint path\n   * @param method - Optional HTTP method filter\n   * @returns Aggregated endpoint metrics\n   */\n  getEndpointMetrics(endpoint: string, method?: string): EndpointMetrics {\n    const windowStart = Date.now() - this.config.windowMs;\n\n    const relevantMetrics = this.metrics.filter(\n      (m) =>\n        m.endpoint === endpoint &&\n        (method == null || method === '' || m.method === method) &&\n        m.timestamp >= windowStart\n    );\n\n    return this.aggregateMetrics(endpoint, relevantMetrics);\n  }\n\n  /**\n   * Get overall API metrics.\n   */\n  getOverallMetrics(): OverallMetrics {\n    const windowStart = Date.now() - this.config.windowMs;\n    const now = Date.now();\n\n    const relevantMetrics = this.metrics.filter((m) => m.timestamp >= windowStart);\n\n    const durations = relevantMetrics.map((m) => m.duration).sort((a, b) => a - b);\n    const successCount = relevantMetrics.filter((m) => m.success).length;\n    const endpoints = new Set(relevantMetrics.map((m) => m.endpoint));\n\n    const windowSeconds = (now - windowStart) / 1000;\n\n    return {\n      totalRequests: relevantMetrics.length,\n      totalSuccess: successCount,\n      totalErrors: relevantMetrics.length - successCount,\n      successRate: relevantMetrics.length > 0 ? successCount / relevantMetrics.length : 1,\n      avgDuration:\n        durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0,\n      p95Latency: this.percentile(durations, 95),\n      requestsPerSecond: windowSeconds > 0 ? relevantMetrics.length / windowSeconds : 0,\n      endpointCount: endpoints.size,\n      collectionStartedAt: this.collectionStartedAt,\n      windowMs: this.config.windowMs,\n    };\n  }\n\n  /**\n   * Get metrics for all endpoints.\n   */\n  getAllEndpointMetrics(): EndpointMetrics[] {\n    const endpoints = new Set(this.metrics.map((m) => `${m.method}:${m.endpoint}`));\n    const results: EndpointMetrics[] = [];\n\n    for (const key of endpoints) {\n      const [method, ...endpointParts] = key.split(':');\n      const endpoint = endpointParts.join(':');\n      results.push(this.getEndpointMetrics(endpoint, method));\n    }\n\n    return results.sort((a, b) => b.totalRequests - a.totalRequests);\n  }\n\n  /**\n   * Get slow requests.\n   *\n   * @param threshold - Duration threshold in ms\n   * @param limit - Maximum results\n   */\n  getSlowRequests(threshold: number, limit = 100): RequestMetric[] {\n    return this.metrics\n      .filter((m) => m.duration >= threshold)\n      .sort((a, b) => b.duration - a.duration)\n      .slice(0, limit);\n  }\n\n  /**\n   * Get recent errors.\n   *\n   * @param limit - Maximum results\n   */\n  getRecentErrors(limit = 100): RequestMetric[] {\n    return this.metrics\n      .filter((m) => !m.success)\n      .sort((a, b) => b.timestamp - a.timestamp)\n      .slice(0, limit);\n  }\n\n  /**\n   * Get error distribution.\n   */\n  getErrorDistribution(): Record<string, number> {\n    const distribution: Record<string, number> = {};\n\n    for (const metric of this.metrics.filter((m) => !m.success)) {\n      const key = metric.error ?? `HTTP ${metric.status}`;\n      distribution[key] = (distribution[key] ?? 0) + 1;\n    }\n\n    return distribution;\n  }\n\n  // ===========================================================================\n  // Export & Reporting\n  // ===========================================================================\n\n  /**\n   * Flush metrics to reporter.\n   */\n  flush(): void {\n    if (this.metrics.length === 0) return;\n\n    const metricsToFlush = [...this.metrics];\n    this.config.reporter.flush(metricsToFlush);\n\n    if (this.config.reporter.reportAggregated) {\n      this.config.reporter.reportAggregated(this.getOverallMetrics());\n    }\n  }\n\n  /**\n   * Export metrics as JSON.\n   */\n  exportJSON(): string {\n    return JSON.stringify({\n      overall: this.getOverallMetrics(),\n      endpoints: this.getAllEndpointMetrics(),\n      metrics: this.config.enableDetailedMetrics ? this.metrics : [],\n    });\n  }\n\n  /**\n   * Export metrics as CSV.\n   */\n  exportCSV(): string {\n    const headers = ['timestamp', 'endpoint', 'method', 'status', 'duration', 'success', 'error'];\n\n    const rows = this.metrics.map((m) => [\n      new Date(m.timestamp).toISOString(),\n      m.endpoint,\n      m.method,\n      m.status,\n      m.duration,\n      m.success,\n      m.error ?? '',\n    ]);\n\n    return [headers.join(','), ...rows.map((r) => r.join(','))].join('\\n');\n  }\n\n  /**\n   * Clear all metrics.\n   */\n  clear(): void {\n    this.metrics = [];\n    this.endpointCache.clear();\n    this.collectionStartedAt = Date.now();\n  }\n\n  /**\n   * Dispose of the collector.\n   */\n  dispose(): void {\n    if (this.flushTimer) {\n      clearInterval(this.flushTimer);\n    }\n    this.flush();\n    this.clear();\n  }\n\n  // ===========================================================================\n  // Private Methods\n  // ===========================================================================\n\n  /**\n   * Check if endpoint should be excluded.\n   */\n  private shouldExclude(endpoint: string): boolean {\n    return this.config.excludeEndpoints.some(\n      (pattern) => endpoint.includes(pattern) || new RegExp(pattern).test(endpoint)\n    );\n  }\n\n  /**\n   * Get cache key for endpoint.\n   */\n  private getEndpointKey(endpoint: string, method: string): string {\n    return `${method}:${endpoint}`;\n  }\n\n  /**\n   * Aggregate metrics for an endpoint.\n   */\n  private aggregateMetrics(endpoint: string, metrics: RequestMetric[]): EndpointMetrics {\n    if (metrics.length === 0) {\n      return this.emptyEndpointMetrics(endpoint);\n    }\n\n    const durations = metrics.map((m) => m.duration).sort((a, b) => a - b);\n    const successCount = metrics.filter((m) => m.success).length;\n    const statusCodes: Record<number, number> = {};\n    const errors: Record<string, number> = {};\n\n    for (const m of metrics) {\n      statusCodes[m.status] = (statusCodes[m.status] ?? 0) + 1;\n      if (!m.success && m.error != null && m.error !== '') {\n        errors[m.error] = (errors[m.error] ?? 0) + 1;\n      }\n    }\n\n    const windowStart = Date.now() - this.config.windowMs;\n    const recentMetrics = metrics.filter((m) => m.timestamp >= windowStart);\n    const windowSeconds = this.config.windowMs / 1000;\n\n    const [minDuration] = durations;\n    const maxDuration = durations[durations.length - 1];\n\n    return {\n      endpoint,\n      totalRequests: metrics.length,\n      successCount,\n      errorCount: metrics.length - successCount,\n      successRate: successCount / metrics.length,\n      avgDuration: durations.reduce((a, b) => a + b, 0) / durations.length,\n      minDuration: minDuration ?? 0,\n      maxDuration: maxDuration ?? 0,\n      p50Latency: this.percentile(durations, 50),\n      p90Latency: this.percentile(durations, 90),\n      p95Latency: this.percentile(durations, 95),\n      p99Latency: this.percentile(durations, 99),\n      statusCodes,\n      errors,\n      lastRequestAt: Math.max(...metrics.map((m) => m.timestamp)),\n      requestsPerSecond: recentMetrics.length / windowSeconds,\n    };\n  }\n\n  /**\n   * Create empty endpoint metrics.\n   */\n  private emptyEndpointMetrics(endpoint: string): EndpointMetrics {\n    return {\n      endpoint,\n      totalRequests: 0,\n      successCount: 0,\n      errorCount: 0,\n      successRate: 1,\n      avgDuration: 0,\n      minDuration: 0,\n      maxDuration: 0,\n      p50Latency: 0,\n      p90Latency: 0,\n      p95Latency: 0,\n      p99Latency: 0,\n      statusCodes: {},\n      errors: {},\n      lastRequestAt: 0,\n      requestsPerSecond: 0,\n    };\n  }\n\n  /**\n   * Calculate percentile.\n   */\n  private percentile(sortedValues: number[], p: number): number {\n    if (sortedValues.length === 0) return 0;\n\n    const index = Math.ceil((p / 100) * sortedValues.length) - 1;\n    const value = sortedValues[Math.max(0, index)];\n    return value ?? 0;\n  }\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Create a new metrics collector.\n *\n * @param config - Collector configuration\n * @returns APIMetricsCollector instance\n */\nexport function createMetricsCollector(config?: MetricsConfig): APIMetricsCollector {\n  return new APIMetricsCollector(config);\n}\n\n// =============================================================================\n// Built-in Reporters\n// =============================================================================\n\n/**\n * Console reporter for debugging.\n */\nexport const consoleReporter: MetricsReporter = {\n  report: (metric) => {\n    const status = metric.success ? 'OK' : 'ERR';\n    // eslint-disable-next-line no-console\n    console.log(`[API] ${metric.method} ${metric.endpoint} ${status} ${metric.duration}ms`);\n  },\n  flush: (metrics) => {\n    // eslint-disable-next-line no-console\n    console.log(`[API Metrics] Flushing ${metrics.length} metrics`);\n  },\n  reportAggregated: (metrics) => {\n    // eslint-disable-next-line no-console\n    console.log('[API Metrics] Aggregated:', {\n      requests: metrics.totalRequests,\n      successRate: `${(metrics.successRate * 100).toFixed(1)}%`,\n      avgDuration: `${metrics.avgDuration.toFixed(0)}ms`,\n      p95: `${metrics.p95Latency.toFixed(0)}ms`,\n      rps: metrics.requestsPerSecond.toFixed(2),\n    });\n  },\n};\n\n/**\n * Create a batched reporter that accumulates metrics.\n */\nexport function createBatchedReporter(\n  onBatch: (metrics: RequestMetric[]) => void,\n  options?: { batchSize?: number; maxWait?: number }\n): MetricsReporter {\n  const { batchSize = 100, maxWait = 10000 } = options ?? {};\n  let batch: RequestMetric[] = [];\n  let timer: ReturnType<typeof setTimeout> | null = null;\n\n  const sendBatch = (): void => {\n    if (batch.length > 0) {\n      onBatch([...batch]);\n      batch = [];\n    }\n    if (timer != null) {\n      clearTimeout(timer);\n      timer = null;\n    }\n  };\n\n  return {\n    report: (metric) => {\n      batch.push(metric);\n\n      if (batch.length >= batchSize) {\n        sendBatch();\n      } else {\n        timer ??= setTimeout(sendBatch, maxWait);\n      }\n    },\n    flush: () => {\n      sendBatch();\n    },\n  };\n}\n"],"names":["APIMetricsCollector","config","metric","cacheKey","durations","endpoint","method","tags","startTime","correlationId","status","responseSize","error","windowStart","relevantMetrics","m","now","b","successCount","endpoints","windowSeconds","results","key","endpointParts","a","threshold","limit","distribution","metricsToFlush","headers","rows","r","pattern","metrics","statusCodes","errors","recentMetrics","minDuration","maxDuration","sortedValues","p","index","createMetricsCollector","consoleReporter","createBatchedReporter","onBatch","options","batchSize","maxWait","batch","timer","sendBatch"],"mappings":"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"}