{"version":3,"file":"flag-analytics.mjs","sources":["../../../../src/lib/flags/analytics/flag-analytics.ts"],"sourcesContent":["/**\n * @fileoverview Feature flag analytics collection and reporting.\n *\n * Provides comprehensive analytics for feature flags:\n * - Evaluation tracking\n * - Usage metrics\n * - Performance monitoring\n * - Error tracking\n *\n * @module flags/analytics/flag-analytics\n *\n * @example\n * ```typescript\n * const analytics = new FlagAnalytics({\n *   batchSize: 100,\n *   flushInterval: 30000,\n *   endpoint: 'https://api.example.com/analytics',\n * });\n *\n * analytics.trackEvaluation({\n *   flagKey: 'new-feature',\n *   variantId: 'enabled',\n *   userId: 'user-123',\n * });\n *\n * const report = analytics.getReport();\n * ```\n */\n\nimport type {\n  // FlagId,\n  VariantId,\n  UserId,\n  EvaluationReason,\n  JsonValue,\n} from '../advanced/types';\n// import type { Mutable } from '../../utils/types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Evaluation event for analytics.\n */\nexport interface EvaluationEvent {\n  /** Flag key */\n  readonly flagKey: string;\n  /** Variant ID */\n  readonly variantId: VariantId;\n  /** User ID */\n  readonly userId?: UserId;\n  /** Session ID */\n  readonly sessionId?: string;\n  /** Evaluation reason */\n  readonly reason?: EvaluationReason;\n  /** Evaluation time in ms */\n  readonly durationMs?: number;\n  /** Timestamp */\n  readonly timestamp: Date;\n  /** Whether value was from cache */\n  readonly cached?: boolean;\n  /** Additional metadata */\n  readonly metadata?: Record<string, JsonValue>;\n}\n\n/**\n * Aggregated metrics for a flag.\n */\nexport interface FlagMetrics {\n  /** Flag key */\n  readonly flagKey: string;\n  /** Total evaluations */\n  readonly evaluationCount: number;\n  /** Evaluations per variant */\n  readonly variantCounts: Record<VariantId, number>;\n  /** Unique users */\n  readonly uniqueUsers: number;\n  /** Unique sessions */\n  readonly uniqueSessions: number;\n  /** Average evaluation time */\n  readonly avgDurationMs: number;\n  /** Cache hit rate */\n  readonly cacheHitRate: number;\n  /** Errors count */\n  readonly errorCount: number;\n  /** First evaluation */\n  readonly firstSeen: Date;\n  /** Last evaluation */\n  readonly lastSeen: Date;\n}\n\n/**\n * Analytics configuration.\n */\nexport interface FlagAnalyticsConfig {\n  /** Enable analytics collection */\n  readonly enabled?: boolean;\n  /** Batch size before flushing */\n  readonly batchSize?: number;\n  /** Flush interval in ms */\n  readonly flushInterval?: number;\n  /** Analytics endpoint URL */\n  readonly endpoint?: string;\n  /** API key for endpoint */\n  readonly apiKey?: string;\n  /** Custom flush handler */\n  readonly onFlush?: (events: EvaluationEvent[]) => Promise<void>;\n  /** Error handler */\n  readonly onError?: (error: Error) => void;\n  /** Enable debug logging */\n  readonly debug?: boolean;\n  /** Sample rate (0-1) */\n  readonly sampleRate?: number;\n  /** Max events to store */\n  readonly maxEvents?: number;\n}\n\n/**\n * Analytics report.\n */\nexport interface AnalyticsReport {\n  /** Report generation time */\n  readonly generatedAt: Date;\n  /** Time period start */\n  readonly periodStart: Date;\n  /** Time period end */\n  readonly periodEnd: Date;\n  /** Total evaluations */\n  readonly totalEvaluations: number;\n  /** Unique flags evaluated */\n  readonly uniqueFlags: number;\n  /** Unique users */\n  readonly uniqueUsers: number;\n  /** Metrics per flag */\n  readonly flagMetrics: FlagMetrics[];\n  /** Top flags by evaluation count */\n  readonly topFlags: Array<{ flagKey: string; count: number }>;\n  /** Error rate */\n  readonly errorRate: number;\n}\n\n// ============================================================================\n// Flag Analytics\n// ============================================================================\n\n/**\n * Analytics collector for feature flags.\n */\nexport class FlagAnalytics {\n  private events: EvaluationEvent[] = [];\n  private flushTimer: ReturnType<typeof setInterval> | null = null;\n  private config: Required<FlagAnalyticsConfig>;\n  private flagMetrics = new Map<string, {\n    evaluationCount: number;\n    variantCounts: Map<VariantId, number>;\n    uniqueUsers: Set<string>;\n    uniqueSessions: Set<string>;\n    totalDuration: number;\n    cacheHits: number;\n    errorCount: number;\n    firstSeen: Date;\n    lastSeen: Date;\n  }>();\n  private listeners = new Set<(events: EvaluationEvent[]) => void>();\n  private periodStart = new Date();\n\n  constructor(config: FlagAnalyticsConfig = {}) {\n    this.config = {\n      enabled: config.enabled ?? true,\n      batchSize: config.batchSize ?? 100,\n      flushInterval: config.flushInterval ?? 30000,\n      endpoint: config.endpoint ?? '',\n      apiKey: config.apiKey ?? '',\n      onFlush: config.onFlush ?? this.defaultFlush.bind(this),\n      onError: config.onError ?? console.error,\n      debug: config.debug ?? false,\n      sampleRate: config.sampleRate ?? 1,\n      maxEvents: config.maxEvents ?? 10000,\n    };\n\n    this.startFlushTimer();\n  }\n\n  // ==========================================================================\n  // Event Tracking\n  // ==========================================================================\n\n  /**\n   * Track a flag evaluation event.\n   */\n  trackEvaluation(event: Omit<EvaluationEvent, 'timestamp'>): void {\n    if (!this.config.enabled) {\n      return;\n    }\n\n    // Apply sampling\n    if (this.config.sampleRate < 1 && Math.random() > this.config.sampleRate) {\n      return;\n    }\n\n    const fullEvent: EvaluationEvent = {\n      ...event,\n      timestamp: new Date(),\n    };\n\n    this.events.push(fullEvent);\n    this.updateMetrics(fullEvent);\n\n    // Check if we should flush\n    if (this.events.length >= this.config.batchSize) {\n      void this.flush();\n    }\n\n    // Enforce max events\n    if (this.events.length > this.config.maxEvents) {\n      this.events = this.events.slice(-this.config.maxEvents);\n    }\n\n    this.log(`Tracked evaluation: ${event.flagKey} -> ${event.variantId}`);\n  }\n\n  /**\n   * Track an error during evaluation.\n   */\n  trackError(flagKey: string, error: Error, metadata?: Record<string, JsonValue>): void {\n    const metrics = this.getOrCreateMetrics(flagKey);\n    metrics.errorCount++;\n    metrics.lastSeen = new Date();\n\n    this.trackEvaluation({\n      flagKey,\n      variantId: 'error',\n      reason: 'ERROR',\n      metadata: {\n        error: error.message,\n        ...metadata,\n      },\n    });\n  }\n\n  /**\n   * Flush pending events.\n   */\n  async flush(): Promise<void> {\n    if (this.events.length === 0) {\n      return;\n    }\n\n    const eventsToFlush = [...this.events];\n    this.events = [];\n\n    try {\n      await this.config.onFlush(eventsToFlush);\n      this.notifyListeners(eventsToFlush);\n      this.log(`Flushed ${eventsToFlush.length} events`);\n    } catch (error) {\n      // Put events back on failure\n      this.events = [...eventsToFlush, ...this.events];\n      this.config.onError(error instanceof Error ? error : new Error(String(error)));\n    }\n  }\n\n  /**\n   * Get metrics for a specific flag.\n   */\n  getMetrics(flagKey: string): FlagMetrics | null {\n    const metrics = this.flagMetrics.get(flagKey);\n    if (!metrics) {\n      return null;\n    }\n\n    return {\n      flagKey,\n      evaluationCount: metrics.evaluationCount,\n      variantCounts: Object.fromEntries(metrics.variantCounts),\n      uniqueUsers: metrics.uniqueUsers.size,\n      uniqueSessions: metrics.uniqueSessions.size,\n      avgDurationMs:\n        metrics.evaluationCount > 0\n          ? metrics.totalDuration / metrics.evaluationCount\n          : 0,\n      cacheHitRate:\n        metrics.evaluationCount > 0\n          ? metrics.cacheHits / metrics.evaluationCount\n          : 0,\n      errorCount: metrics.errorCount,\n      firstSeen: metrics.firstSeen,\n      lastSeen: metrics.lastSeen,\n    };\n  }\n\n  // ==========================================================================\n  // Flushing\n  // ==========================================================================\n\n  /**\n   * Get all flag metrics.\n   */\n  getAllMetrics(): FlagMetrics[] {\n    const results: FlagMetrics[] = [];\n    for (const flagKey of this.flagMetrics.keys()) {\n      const metrics = this.getMetrics(flagKey);\n      if (metrics) {\n        results.push(metrics);\n      }\n    }\n    return results;\n  }\n\n  /**\n   * Generate an analytics report.\n   */\n  getReport(): AnalyticsReport {\n    const allMetrics = this.getAllMetrics();\n    const now = new Date();\n\n    const uniqueUsers = new Set<string>();\n    let totalEvaluations = 0;\n    let totalErrors = 0;\n\n    for (const metrics of allMetrics) {\n      totalEvaluations += metrics.evaluationCount;\n      totalErrors += metrics.errorCount;\n    }\n\n    // Collect unique users across all flags\n    for (const metrics of this.flagMetrics.values()) {\n      for (const userId of metrics.uniqueUsers) {\n        uniqueUsers.add(userId);\n      }\n    }\n\n    // Sort flags by evaluation count\n    const topFlags = allMetrics\n      .map((m) => ({ flagKey: m.flagKey, count: m.evaluationCount }))\n      .sort((a, b) => b.count - a.count)\n      .slice(0, 10);\n\n    return {\n      generatedAt: now,\n      periodStart: this.periodStart,\n      periodEnd: now,\n      totalEvaluations,\n      uniqueFlags: allMetrics.length,\n      uniqueUsers: uniqueUsers.size,\n      flagMetrics: allMetrics,\n      topFlags,\n      errorRate: totalEvaluations > 0 ? totalErrors / totalEvaluations : 0,\n    };\n  }\n\n  /**\n   * Subscribe to flush events.\n   */\n  subscribe(listener: (events: EvaluationEvent[]) => void): () => void {\n    this.listeners.add(listener);\n    return () => {\n      this.listeners.delete(listener);\n    };\n  }\n\n  /**\n   * Reset all metrics and events.\n   */\n  reset(): void {\n    this.events = [];\n    this.flagMetrics.clear();\n    this.periodStart = new Date();\n    this.log('Analytics reset');\n  }\n\n  // ==========================================================================\n  // Metrics and Reporting\n  // ==========================================================================\n\n  /**\n   * Shutdown the analytics collector.\n   */\n  async shutdown(): Promise<void> {\n    this.stopFlushTimer();\n    await this.flush();\n    this.listeners.clear();\n    this.log('Analytics shutdown');\n  }\n\n  /**\n   * Enable or disable analytics.\n   */\n  setEnabled(enabled: boolean): void {\n    (this.config as { enabled: boolean }).enabled = enabled;\n    if (enabled) {\n      this.startFlushTimer();\n    } else {\n      this.stopFlushTimer();\n    }\n  }\n\n  private updateMetrics(event: EvaluationEvent): void {\n    const metrics = this.getOrCreateMetrics(event.flagKey);\n\n    metrics.evaluationCount++;\n    metrics.lastSeen = event.timestamp;\n\n    // Update variant counts\n\n    const currentCount = metrics.variantCounts.get(event.variantId) ?? 0;\n    metrics.variantCounts.set(event.variantId, currentCount + 1);\n\n    // Track unique users\n    if (event.userId != null && event.userId !== '') {\n\n      metrics.uniqueUsers.add(event.userId);\n    }\n\n    // Track unique sessions\n    if (event.sessionId != null && event.sessionId !== '') {\n\n      metrics.uniqueSessions.add(event.sessionId);\n    }\n\n    // Track duration\n    if (event.durationMs !== undefined) {\n      metrics.totalDuration += event.durationMs;\n    }\n\n    // Track cache hits\n    if (event.cached === true) {\n      metrics.cacheHits++;\n    }\n  }\n\n  // ==========================================================================\n  // Subscriptions\n  // ==========================================================================\n\n  private getOrCreateMetrics(flagKey: string): {\n    evaluationCount: number;\n    variantCounts: Map<VariantId, number>;\n    uniqueUsers: Set<string>;\n    uniqueSessions: Set<string>;\n    totalDuration: number;\n    cacheHits: number;\n    errorCount: number;\n    firstSeen: Date;\n    lastSeen: Date;\n  } {\n    let metrics = this.flagMetrics.get(flagKey);\n    if (metrics == null) {\n      metrics = {\n        evaluationCount: 0,\n        variantCounts: new Map(),\n        uniqueUsers: new Set(),\n        uniqueSessions: new Set(),\n        totalDuration: 0,\n        cacheHits: 0,\n        errorCount: 0,\n        firstSeen: new Date(),\n        lastSeen: new Date(),\n      };\n      this.flagMetrics.set(flagKey, metrics);\n    }\n    return metrics;\n  }\n\n  /**\n   * Default flush handler that sends events to the configured endpoint.\n   *\n   * Note: This method intentionally uses raw fetch() rather than apiClient because:\n   * 1. Analytics should be independent of the main API client to avoid circular dependencies\n   * 2. Analytics endpoints may be on a different domain/service\n   * 3. This should work even if the main API client fails\n   *\n   * @see {@link @/lib/api/api-client} for the main API client\n   */\n  private async defaultFlush(events: EvaluationEvent[]): Promise<void> {\n    if (!this.config.endpoint) {\n      return;\n    }\n\n    // Raw fetch is intentional - analytics should be independent of apiClient\n    const response = await fetch(this.config.endpoint, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        ...(this.config.apiKey\n          ? { Authorization: `Bearer ${this.config.apiKey}` }\n          : {}),\n      },\n      body: JSON.stringify({ events }),\n    });\n\n    if (!response.ok) {\n      throw new Error(`Analytics flush failed: ${response.status}`);\n    }\n  }\n\n  // ==========================================================================\n  // Lifecycle\n  // ==========================================================================\n\n  private startFlushTimer(): void {\n    if (this.flushTimer) {\n      return;\n    }\n\n    this.flushTimer = setInterval(() => {\n      void this.flush();\n    }, this.config.flushInterval);\n  }\n\n  private stopFlushTimer(): void {\n    if (this.flushTimer) {\n      clearInterval(this.flushTimer);\n      this.flushTimer = null;\n    }\n  }\n\n  private notifyListeners(events: EvaluationEvent[]): void {\n    for (const listener of this.listeners) {\n      try {\n        listener(events);\n      } catch (error) {\n        this.log('Error in listener:', error);\n      }\n    }\n  }\n\n  // ==========================================================================\n  // Utilities\n  // ==========================================================================\n\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      // eslint-disable-next-line no-console\n      console.log(`[FlagAnalytics] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet instance: FlagAnalytics | null = null;\n\n/**\n * Get the singleton analytics instance.\n */\nexport function getFlagAnalytics(): FlagAnalytics {\n  instance ??= new FlagAnalytics();\n  return instance;\n}\n\n/**\n * Initialize the singleton with configuration.\n */\nexport function initFlagAnalytics(config: FlagAnalyticsConfig): FlagAnalytics {\n  instance = new FlagAnalytics(config);\n  return instance;\n}\n\n/**\n * Reset the singleton instance.\n */\nexport function resetFlagAnalytics(): void {\n  if (instance) {\n    void instance.shutdown();\n  }\n  instance = null;\n}\n"],"names":["FlagAnalytics","config","event","fullEvent","flagKey","error","metadata","metrics","eventsToFlush","results","allMetrics","now","uniqueUsers","totalEvaluations","totalErrors","userId","topFlags","m","a","b","listener","enabled","currentCount","events","response","message","args","instance","getFlagAnalytics","initFlagAnalytics","resetFlagAnalytics"],"mappings":"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"}