{"version":3,"file":"sampling.cjs","names":["TraceFlags"],"sources":["../src/sampling.ts"],"sourcesContent":["/**\n * Sampling Strategies\n *\n * Provides intelligent sampling beyond simple random rates.\n * Helps reduce telemetry costs while capturing critical data.\n *\n * Key strategies:\n * - Always trace errors and slow requests (critical for debugging)\n * - Sample by user ID for consistent request tracing\n * - Adaptive sampling based on load\n * - Sample by feature flags for A/B testing correlation\n *\n * @example\n * ```typescript\n * import { AlwaysOnErrorSampler, UserIdSampler } from './sampling'\n *\n * @Instrumented({\n *   serviceName: 'user',\n *   sampler: new AlwaysOnErrorSampler(0.1) // 10% baseline, 100% on errors\n * })\n * class UserService { }\n * ```\n */\n\nimport type { Link, Attributes } from '@opentelemetry/api';\nimport { TraceFlags } from '@opentelemetry/api';\nimport { type Logger } from './logger';\n\n/**\n * Tail sampling attribute keys (autotel-internal, not OTel semconv)\n */\nexport const AUTOTEL_SAMPLING_TAIL_KEEP = 'autotel.sampling.tail.keep';\nexport const AUTOTEL_SAMPLING_TAIL_EVALUATED =\n  'autotel.sampling.tail.evaluated';\n\n/**\n * Sampler interface - return true to trace, false to skip\n */\nexport interface Sampler {\n  /**\n   * Decide whether to trace this operation\n   *\n   * @param context - Sampling context\n   * @returns true to trace, false to skip\n   */\n  shouldSample(context: SamplingContext): boolean;\n\n  /**\n   * Whether this sampler needs tail sampling (post-execution decision)\n   * If true, spans are always created and shouldKeepTrace() is called after execution\n   *\n   * @returns true if this sampler needs to evaluate after operation completes\n   */\n  needsTailSampling?(): boolean;\n\n  /**\n   * Re-evaluate sampling decision after operation completes (tail sampling)\n   * Only called if needsTailSampling() returns true\n   *\n   * @param context - Sampling context\n   * @param result - Operation result\n   * @returns true if this trace should be kept, false to drop it\n   */\n  shouldKeepTrace?(context: SamplingContext, result: OperationResult): boolean;\n}\n\n/**\n * Context information for sampling decisions\n */\nexport interface SamplingContext {\n  /** Operation name */\n  operationName: string;\n  /** Method arguments (for extracting user IDs, etc.) */\n  args: unknown[];\n  /** Optional metadata (e.g., feature flags, request headers) */\n  metadata?: Record<string, unknown>;\n  /** Optional span links for links-based sampling */\n  links?: Link[];\n}\n\n/**\n * Result of a trace operation (for post-execution sampling)\n */\nexport interface OperationResult {\n  /** Whether the operation succeeded */\n  success: boolean;\n  /** Duration in milliseconds */\n  duration: number;\n  /** Error if operation failed */\n  error?: Error;\n}\n\n/**\n * Simple random sampler\n *\n * @example\n * ```typescript\n * new RandomSampler(0.1) // Sample 10% of requests\n * ```\n */\nexport class RandomSampler implements Sampler {\n  constructor(private readonly sampleRate: number) {\n    if (sampleRate < 0 || sampleRate > 1) {\n      throw new Error('Sample rate must be between 0 and 1');\n    }\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  shouldSample(_context: SamplingContext): boolean {\n    return Math.random() < this.sampleRate;\n  }\n}\n\n/**\n * Always sample (100% tracing)\n */\nexport class AlwaysSampler implements Sampler {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  shouldSample(_context: SamplingContext): boolean {\n    return true;\n  }\n}\n\n/**\n * Never sample (0% tracing)\n */\nexport class NeverSampler implements Sampler {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  shouldSample(_context: SamplingContext): boolean {\n    return false;\n  }\n}\n\n/**\n * Adaptive sampler that always traces errors and slow requests\n *\n * This is the recommended sampler for production use.\n * It ensures you never miss critical issues while keeping costs down.\n *\n * Strategy:\n * - Always trace errors (critical for debugging)\n * - Always trace slow requests (performance issues)\n * - Use baseline sample rate for successful fast requests\n *\n * **IMPORTANT - Tail Sampling Requirement:**\n * This sampler uses tail sampling (makes decisions AFTER execution).\n * You MUST use TailSamplingSpanProcessor for it to work correctly:\n *\n * - If using initInstrumentation(): TailSamplingSpanProcessor is auto-configured\n * - If using custom TracerProvider: You MUST manually register TailSamplingSpanProcessor\n *\n * Without TailSamplingSpanProcessor, ALL spans are exported (defeating the cost savings).\n *\n * @see TailSamplingSpanProcessor\n * @see README.md \"Tail Sampling with Custom Providers\" section\n *\n * @example\n * ```typescript\n * new AdaptiveSampler({\n *   baselineSampleRate: 0.1,    // 10% of normal requests\n *   slowThresholdMs: 1000,       // Requests > 1s are \"slow\"\n *   alwaysSampleErrors: true,    // Always trace errors\n *   alwaysSampleSlow: true       // Always trace slow requests\n * })\n * ```\n */\nexport class AdaptiveSampler implements Sampler {\n  private baselineSampleRate: number;\n  private slowThresholdMs: number;\n  private alwaysSampleErrors: boolean;\n  private alwaysSampleSlow: boolean;\n  private linksBased: boolean;\n  private linksRate: number;\n  private logger?: Logger;\n\n  // Track whether we should sample this request\n  private readonly samplingDecisions = new WeakMap<unknown[], boolean>();\n  // Track operation results to enable post-execution decision\n  private readonly operationResults = new WeakMap<unknown[], OperationResult>();\n\n  constructor(\n    options: {\n      baselineSampleRate?: number;\n      slowThresholdMs?: number;\n      alwaysSampleErrors?: boolean;\n      alwaysSampleSlow?: boolean;\n      /** Enable links-based sampling for event-driven architectures */\n      linksBased?: boolean;\n      /** Sampling rate for spans linked to sampled spans (0.0-1.0) */\n      linksRate?: number;\n      logger?: Logger;\n    } = {},\n  ) {\n    this.baselineSampleRate = options.baselineSampleRate ?? 0.1;\n    this.slowThresholdMs = options.slowThresholdMs ?? 1000;\n    this.alwaysSampleErrors = options.alwaysSampleErrors ?? true;\n    this.alwaysSampleSlow = options.alwaysSampleSlow ?? true;\n    this.linksBased = options.linksBased ?? false;\n    this.linksRate = options.linksRate ?? 1;\n    this.logger = options.logger;\n\n    if (this.baselineSampleRate < 0 || this.baselineSampleRate > 1) {\n      throw new Error('Baseline sample rate must be between 0 and 1');\n    }\n    if (this.linksRate < 0 || this.linksRate > 1) {\n      throw new Error('Links rate must be between 0 and 1');\n    }\n  }\n\n  needsTailSampling(): boolean {\n    // AdaptiveSampler ALWAYS needs tail sampling to implement error/slow capture\n    return true;\n  }\n\n  shouldSample(context: SamplingContext): boolean {\n    // For tail sampling, we optimistically create spans for all requests\n    // The real decision happens in shouldKeepTrace() after execution\n    // We still store the baseline decision for shouldKeepTrace() to use\n    const baselineDecision = Math.random() < this.baselineSampleRate;\n    this.samplingDecisions.set(context.args, baselineDecision);\n\n    // Always return true to create the span (tail sampling will decide if we keep it)\n    return true;\n  }\n\n  /**\n   * Check if any links point to sampled spans.\n   *\n   * A span is considered linked to a sampled span if any of its links\n   * have trace_flags with the sampled bit set (0x01).\n   *\n   * @param links - Array of span links to check\n   * @returns true if any linked span is sampled, false otherwise\n   */\n  hasSampledLink(links: Link[]): boolean {\n    if (!links || links.length === 0) {\n      return false;\n    }\n    return links.some(\n      (link) =>\n        link.context && (link.context.traceFlags & TraceFlags.SAMPLED) !== 0,\n    );\n  }\n\n  /**\n   * Re-evaluate sampling decision after operation completes\n   *\n   * This allows us to always capture errors and slow requests,\n   * even if they weren't initially sampled.\n   *\n   * @param context - Sampling context\n   * @param result - Operation result\n   * @returns true if this operation should be kept (not discarded)\n   */\n  shouldKeepTrace(context: SamplingContext, result: OperationResult): boolean {\n    const baselineDecision = this.samplingDecisions.get(context.args) ?? false;\n\n    // Always keep errors\n    if (this.alwaysSampleErrors && !result.success) {\n      if (!baselineDecision) {\n        this.logger?.debug(\n          {\n            operation: context.operationName,\n            error: result.error?.message,\n          },\n          'Adaptive sampling: Keeping error trace',\n        );\n      }\n      return true;\n    }\n\n    // Always keep slow requests\n    if (this.alwaysSampleSlow && result.duration >= this.slowThresholdMs) {\n      if (!baselineDecision) {\n        this.logger?.debug(\n          {\n            operation: context.operationName,\n            duration: result.duration,\n          },\n          'Adaptive sampling: Keeping slow trace',\n        );\n      }\n      return true;\n    }\n\n    // Check for sampled links (links-based sampling for event-driven systems)\n    if (\n      this.linksBased &&\n      context.links &&\n      this.hasSampledLink(context.links)\n    ) {\n      // Use linksRate to decide whether to keep the linked span\n      const keepLinked = Math.random() < this.linksRate;\n      if (keepLinked && !baselineDecision) {\n        this.logger?.debug(\n          {\n            operation: context.operationName,\n            linkCount: context.links.length,\n          },\n          'Adaptive sampling: Keeping trace due to sampled link',\n        );\n      }\n      return keepLinked;\n    }\n\n    // Otherwise, use baseline decision\n    return baselineDecision;\n  }\n}\n\n/**\n * User-based sampler for consistent tracing\n *\n * Always samples requests from specific user IDs.\n * Useful for debugging specific user issues or monitoring VIP users.\n *\n * @example\n * ```typescript\n * new UserIdSampler({\n *   baselineSampleRate: 0.01,      // 1% of normal users\n *   alwaysSampleUsers: ['vip_123'], // Always trace VIP users\n *   extractUserId: (args) => args[0]?.userId // Extract user ID from first arg\n * })\n * ```\n */\nexport class UserIdSampler implements Sampler {\n  private baselineSampleRate: number;\n  private alwaysSampleUsers: Set<string>;\n  private extractUserId: (args: unknown[]) => string | undefined;\n  private logger?: Logger;\n\n  constructor(options: {\n    baselineSampleRate?: number;\n    alwaysSampleUsers?: string[];\n    extractUserId: (args: unknown[]) => string | undefined;\n    logger?: Logger;\n  }) {\n    this.baselineSampleRate = options.baselineSampleRate ?? 0.1;\n    this.alwaysSampleUsers = new Set(options.alwaysSampleUsers || []);\n    this.extractUserId = options.extractUserId;\n    this.logger = options.logger;\n  }\n\n  shouldSample(context: SamplingContext): boolean {\n    const userId = this.extractUserId(context.args);\n\n    // Always sample specific users\n    if (userId && this.alwaysSampleUsers.has(userId)) {\n      this.logger?.debug(\n        {\n          operation: context.operationName,\n          userId,\n        },\n        'Sampling user request',\n      );\n      return true;\n    }\n\n    // For consistent per-user sampling, hash the user ID\n    if (userId) {\n      const hash = this.hashString(userId);\n      return hash < this.baselineSampleRate;\n    }\n\n    // Fallback to random sampling if no user ID\n    return Math.random() < this.baselineSampleRate;\n  }\n\n  /**\n   * Add user IDs to always-sample list\n   */\n  addAlwaysSampleUsers(...userIds: string[]): void {\n    for (const userId of userIds) {\n      this.alwaysSampleUsers.add(userId);\n    }\n  }\n\n  /**\n   * Remove user IDs from always-sample list\n   */\n  removeAlwaysSampleUsers(...userIds: string[]): void {\n    for (const userId of userIds) {\n      this.alwaysSampleUsers.delete(userId);\n    }\n  }\n\n  /**\n   * Simple hash function for consistent user sampling\n   */\n  private hashString(str: string): number {\n    let hash = 0;\n    for (let i = 0; i < str.length; i++) {\n      const char = str.codePointAt(i) ?? 0;\n      hash = (hash << 5) - hash + char;\n      hash = hash & hash; // Convert to 32-bit integer\n    }\n    return Math.abs(hash) / 2_147_483_647; // Normalize to 0-1\n  }\n}\n\n/**\n * Composite sampler that combines multiple samplers\n *\n * Samples if ANY of the child samplers returns true.\n *\n * @example\n * ```typescript\n * new CompositeSampler([\n *   new UserIdSampler({ extractUserId: (args) => args[0]?.userId }),\n *   new AdaptiveSampler({ baselineSampleRate: 0.1 })\n * ])\n * ```\n */\nexport class CompositeSampler implements Sampler {\n  constructor(private readonly samplers: Sampler[]) {\n    if (samplers.length === 0) {\n      throw new Error('CompositeSampler requires at least one child sampler');\n    }\n  }\n\n  shouldSample(context: SamplingContext): boolean {\n    return this.samplers.some((sampler) => sampler.shouldSample(context));\n  }\n}\n\n/**\n * Feature flag sampler\n *\n * Always samples requests with specific feature flags enabled.\n * Perfect for correlating A/B test experiments with metrics.\n *\n * @example\n * ```typescript\n * new FeatureFlagSampler({\n *   baselineSampleRate: 0.01,\n *   alwaysSampleFlags: ['new_checkout', 'experimental_ui'],\n *   extractFlags: (args, metadata) => metadata?.featureFlags\n * })\n * ```\n */\nexport class FeatureFlagSampler implements Sampler {\n  private baselineSampleRate: number;\n  private alwaysSampleFlags: Set<string>;\n  private extractFlags: (\n    args: unknown[],\n    metadata?: Record<string, unknown>,\n  ) => string[] | undefined;\n  private logger?: Logger;\n\n  constructor(options: {\n    baselineSampleRate?: number;\n    alwaysSampleFlags?: string[];\n    extractFlags: (\n      args: unknown[],\n      metadata?: Record<string, unknown>,\n    ) => string[] | undefined;\n    logger?: Logger;\n  }) {\n    this.baselineSampleRate = options.baselineSampleRate ?? 0.1;\n    this.alwaysSampleFlags = new Set(options.alwaysSampleFlags || []);\n    this.extractFlags = options.extractFlags;\n    this.logger = options.logger;\n  }\n\n  shouldSample(context: SamplingContext): boolean {\n    const flags = this.extractFlags(context.args, context.metadata);\n\n    // Always sample if any monitored flag is enabled\n    if (flags && flags.some((flag) => this.alwaysSampleFlags.has(flag))) {\n      this.logger?.debug(\n        {\n          operation: context.operationName,\n          flags,\n        },\n        'Sampling feature flag request',\n      );\n      return true;\n    }\n\n    // Fallback to random sampling\n    return Math.random() < this.baselineSampleRate;\n  }\n\n  /**\n   * Add feature flags to always-sample list\n   */\n  addAlwaysSampleFlags(...flags: string[]): void {\n    for (const flag of flags) {\n      this.alwaysSampleFlags.add(flag);\n    }\n  }\n\n  /**\n   * Remove feature flags from always-sample list\n   */\n  removeAlwaysSampleFlags(...flags: string[]): void {\n    for (const flag of flags) {\n      this.alwaysSampleFlags.delete(flag);\n    }\n  }\n}\n\n// ============================================================================\n// Sampling Presets\n// ============================================================================\n\n/**\n * Named sampling presets for common environments.\n * Use with `init({ sampling: 'production' })` or directly via factories.\n */\nexport type SamplingPreset =\n  | 'development'\n  | 'errors-only'\n  | 'production'\n  | 'off';\n\n/**\n * Sampling preset factories.\n *\n * For most users, the string shorthand on `init()` is simpler:\n * ```typescript\n * init({ service: 'my-app', sampling: 'production' })\n * ```\n *\n * Use factories when you need to customize:\n * ```typescript\n * init({ service: 'my-app', sampler: samplingPresets.production({ baselineSampleRate: 0.05 }) })\n * ```\n */\nexport const samplingPresets = {\n  /** Capture everything — best for local development and debugging */\n  development: () => new AlwaysSampler(),\n\n  /** Only bad outcomes — zero baseline, errors always kept */\n  errorsOnly: () =>\n    new AdaptiveSampler({\n      baselineSampleRate: 0,\n      alwaysSampleErrors: true,\n    }),\n\n  /**\n   * Balanced production defaults — 10% baseline + errors + slow traces.\n   * Pass overrides to tune (uses the same option names as AdaptiveSampler).\n   */\n  production: (overrides?: {\n    baselineSampleRate?: number;\n    slowThresholdMs?: number;\n    alwaysSampleErrors?: boolean;\n    alwaysSampleSlow?: boolean;\n  }) =>\n    new AdaptiveSampler({\n      baselineSampleRate: 0.1,\n      alwaysSampleErrors: true,\n      alwaysSampleSlow: true,\n      slowThresholdMs: 1000,\n      ...overrides,\n    }),\n\n  /** Disable sampling entirely */\n  off: () => new NeverSampler(),\n};\n\n/**\n * Resolve a preset string to a Sampler instance.\n * Used internally by `init()` when `sampling` string is provided.\n *\n * @throws Error if preset is not recognized\n */\nexport function resolveSamplingPreset(preset: SamplingPreset): Sampler {\n  switch (preset) {\n    case 'development':\n      return samplingPresets.development();\n    case 'errors-only':\n      return samplingPresets.errorsOnly();\n    case 'production':\n      return samplingPresets.production();\n    case 'off':\n      return samplingPresets.off();\n    default:\n      throw new Error(\n        `Unknown sampling preset: \"${preset}\". Valid presets: development, errors-only, production, off`,\n      );\n  }\n}\n\n// ============================================================================\n// Link Helper Functions\n// ============================================================================\n\n/**\n * Create a Link from W3C trace context headers (e.g., from a message queue).\n *\n * This is useful for message consumers that need to link to the producer span.\n * The headers should contain at least a `traceparent` header in W3C format.\n *\n * @param headers - Dictionary containing traceparent/tracestate headers\n * @param attributes - Optional attributes for the link\n * @returns Link object if context could be extracted, null otherwise\n *\n * @example\n * ```typescript\n * // In a Kafka consumer\n * const headers = { traceparent: '00-abc123...-def456...-01' };\n * const link = createLinkFromHeaders(headers);\n * if (link) {\n *   // Use with tracer.startActiveSpan options or ctx.addLink()\n *   tracer.startActiveSpan('process.message', { links: [link] }, span => { ... });\n * }\n * ```\n */\nexport function createLinkFromHeaders(\n  headers: Record<string, string>,\n  attributes?: Attributes,\n): Link | null {\n  // Parse W3C traceparent header directly for reliability\n  // Format: version-traceId-spanId-traceFlags (e.g., 00-abc123...-def456...-01)\n  const traceparent = headers.traceparent || headers['traceparent'];\n  if (!traceparent) {\n    return null;\n  }\n\n  const spanContext = parseTraceparent(traceparent);\n  if (!spanContext || !isValidSpanContext(spanContext)) {\n    return null;\n  }\n\n  return {\n    context: spanContext,\n    attributes: attributes ?? {},\n  };\n}\n\n/**\n * Extract Links from a batch of messages for fan-in scenarios.\n *\n * Useful for batch processing where multiple producer spans should be linked.\n * This enables tracing causality in event-driven architectures where a single\n * consumer processes messages from multiple producers.\n *\n * @param messages - List of message objects\n * @param headersKey - Key in each message containing trace headers (default: 'headers')\n * @returns List of Link objects for all valid trace contexts\n *\n * @example\n * ```typescript\n * // Processing a batch of SQS/Kafka messages\n * const messages = [\n *   { body: '...', headers: { traceparent: '...' } },\n *   { body: '...', headers: { traceparent: '...' } },\n * ];\n * const links = extractLinksFromBatch(messages);\n *\n * tracer.startActiveSpan('process.batch', { links }, span => {\n *   for (const msg of messages) {\n *     processMessage(msg);\n *   }\n * });\n * ```\n */\nexport function extractLinksFromBatch(\n  messages: Array<{ [key: string]: unknown }>,\n  headersKey: string = 'headers',\n): Link[] {\n  const links: Link[] = [];\n\n  for (const msg of messages) {\n    const msgHeaders = msg[headersKey];\n    if (msgHeaders && typeof msgHeaders === 'object' && msgHeaders !== null) {\n      const link = createLinkFromHeaders(msgHeaders as Record<string, string>, {\n        'messaging.batch.message_index': links.length,\n      });\n      if (link) {\n        links.push(link);\n      }\n    }\n  }\n\n  return links;\n}\n\n/**\n * Parse W3C traceparent header into SpanContext\n * Format: version-traceId-spanId-traceFlags (e.g., 00-abc123...-def456...-01)\n *\n * @see https://www.w3.org/TR/trace-context/#traceparent-header\n */\nfunction parseTraceparent(\n  traceparent: string,\n): import('@opentelemetry/api').SpanContext | null {\n  // W3C traceparent format: version-traceId-parentId-traceFlags\n  // Example: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01\n  const TRACEPARENT_REGEX =\n    /^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/i;\n\n  const match = traceparent.match(TRACEPARENT_REGEX);\n  if (!match || match.length < 5) {\n    return null;\n  }\n\n  const version = match[1];\n  const traceId = match[2];\n  const spanId = match[3];\n  const flags = match[4];\n\n  // Validate all parts are present (TypeScript narrowing)\n  if (!version || !traceId || !spanId || !flags) {\n    return null;\n  }\n\n  // Version 00 is currently the only version, but we should be forward compatible\n  if (version === 'ff') {\n    // Version ff is invalid according to spec\n    return null;\n  }\n\n  return {\n    traceId,\n    spanId,\n    traceFlags: Number.parseInt(flags, 16),\n    isRemote: true,\n  };\n}\n\n/**\n * Check if a SpanContext is valid (has non-zero trace and span IDs)\n */\nfunction isValidSpanContext(\n  spanContext: import('@opentelemetry/api').SpanContext | null,\n): spanContext is import('@opentelemetry/api').SpanContext {\n  if (!spanContext) return false;\n  // TraceId should not be all zeros (00000000000000000000000000000000)\n  // SpanId should not be all zeros (0000000000000000)\n  return (\n    spanContext.traceId !== '00000000000000000000000000000000' &&\n    spanContext.spanId !== '0000000000000000'\n  );\n}\n"],"mappings":"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"}