{"version":3,"file":"canonical-log-line-processor--RlFDHhm.cjs","names":["logs","SeverityNumber"],"sources":["../src/pretty-log-formatter.ts","../src/processors/canonical-log-line-processor.ts"],"sourcesContent":["import type { CanonicalLogLineEvent } from './processors/canonical-log-line-processor';\n\nconst RESET = '\\x1b[0m';\nconst DIM = '\\x1b[2m';\nconst BOLD = '\\x1b[1m';\nconst RED = '\\x1b[31m';\nconst YELLOW = '\\x1b[33m';\nconst GREEN = '\\x1b[32m';\nconst CYAN = '\\x1b[36m';\nconst GRAY = '\\x1b[90m';\n\nconst LEVEL_COLORS: Record<string, string> = {\n  debug: GRAY,\n  info: GREEN,\n  warn: YELLOW,\n  error: RED,\n};\n\n/** Internal OTel attributes to skip in pretty output. */\nconst SKIP_PREFIXES = [\n  'telemetry.',\n  'otel.',\n  'process.',\n  'os.',\n  'host.',\n  'service.',\n  'autotel.',\n];\n\nconst SKIP_KEYS = new Set([\n  'operation',\n  'traceId',\n  'spanId',\n  'correlationId',\n  'duration_ms',\n  'duration',\n  'status_code',\n  'status_message',\n  'timestamp',\n  'http.request.method',\n  'url.path',\n  'http.route',\n  'http.response.status_code',\n]);\n\nfunction useColor(): boolean {\n  if (typeof process !== 'undefined') {\n    if (process.env.NO_COLOR) return false;\n    if (process.env.FORCE_COLOR) return true;\n    if (process.stdout?.isTTY) return true;\n  }\n  return false;\n}\n\nfunction c(color: string, text: string): string {\n  return useColor() ? `${color}${text}${RESET}` : text;\n}\n\n/**\n * Format milliseconds into a human-readable duration string.\n *\n * @example\n * formatDuration(45)     // \"45ms\"\n * formatDuration(1234)   // \"1.2s\"\n * formatDuration(65000)  // \"1m 5s\"\n */\nexport function formatDuration(ms: number): string {\n  if (ms < 1000) return `${Math.round(ms)}ms`;\n  if (ms < 60_000) {\n    const seconds = ms / 1000;\n    return seconds < 10 ? `${seconds.toFixed(1)}s` : `${Math.round(seconds)}s`;\n  }\n  const minutes = Math.floor(ms / 60_000);\n  const seconds = Math.round((ms % 60_000) / 1000);\n  return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n}\n\nfunction formatTime(iso: string): string {\n  try {\n    const d = new Date(iso);\n    return d.toLocaleTimeString('en-GB', { hour12: false });\n  } catch {\n    return iso.slice(11, 19);\n  }\n}\n\nfunction formatValue(value: unknown): string {\n  if (typeof value === 'string') return value;\n  if (typeof value === 'number' || typeof value === 'boolean')\n    return String(value);\n  if (value == null) return '';\n  try {\n    return JSON.stringify(value);\n  } catch {\n    return String(value);\n  }\n}\n\n/**\n * Group flat dot-notation attributes into a nested tree for pretty display.\n * e.g. { 'user.id': '1', 'user.plan': 'pro' } → { user: { id: '1', plan: 'pro' } }\n */\nfunction groupAttributes(\n  event: Record<string, unknown>,\n): Record<string, unknown> {\n  const tree: Record<string, unknown> = {};\n\n  for (const [key, value] of Object.entries(event)) {\n    if (SKIP_KEYS.has(key)) continue;\n    if (SKIP_PREFIXES.some((p) => key.startsWith(p))) continue;\n    if (value == null || value === '') continue;\n\n    const parts = key.split('.');\n    if (parts.length === 1) {\n      tree[key] = value;\n    } else {\n      let current = tree;\n      for (let i = 0; i < parts.length - 1; i++) {\n        const part = parts[i]!;\n        if (!(part in current) || typeof current[part] !== 'object') {\n          current[part] = {};\n        }\n        current = current[part] as Record<string, unknown>;\n      }\n      current[parts[parts.length - 1]!] = value;\n    }\n  }\n\n  return tree;\n}\n\nfunction renderTree(\n  obj: Record<string, unknown>,\n  indent: string,\n  isLast: boolean[],\n): string[] {\n  const lines: string[] = [];\n  const entries = Object.entries(obj);\n\n  entries.forEach(([key, value], idx) => {\n    const last = idx === entries.length - 1;\n    const connector = last ? '\\u2514\\u2500' : '\\u251c\\u2500';\n    const prefix = indent + connector + ' ';\n\n    if (value && typeof value === 'object' && !Array.isArray(value)) {\n      const nested = value as Record<string, unknown>;\n      const flatValues = Object.entries(nested).filter(\n        ([, v]) => typeof v !== 'object' || v === null,\n      );\n      const nestedObjs = Object.entries(nested).filter(\n        ([, v]) => typeof v === 'object' && v !== null && !Array.isArray(v),\n      );\n\n      if (nestedObjs.length === 0) {\n        const inline = flatValues\n          .map(([k, v]) => `${c(CYAN, k)}=${formatValue(v)}`)\n          .join(' ');\n        lines.push(`${prefix}${c(BOLD, key)}: ${inline}`);\n      } else {\n        lines.push(`${prefix}${c(BOLD, key)}:`);\n        const nextIndent = indent + (last ? '   ' : '\\u2502  ');\n        lines.push(...renderTree(nested, nextIndent, [...isLast, last]));\n      }\n    } else {\n      lines.push(`${prefix}${c(CYAN, key)}: ${c(DIM, formatValue(value))}`);\n    }\n  });\n\n  return lines;\n}\n\n/**\n * Format a canonical log line event as a pretty tree for development output.\n */\nexport function formatPrettyLogLine(ctx: CanonicalLogLineEvent): string {\n  const { event, level, message } = ctx;\n\n  const timestamp = formatTime(String(event.timestamp ?? ''));\n  const service = event['service.name'] || event.service || '';\n  const method = event['http.request.method'] || '';\n  const path = event['http.route'] || event['url.path'] || '';\n  const status = event['http.response.status_code'] || event.status_code || '';\n  const durationMs = Number(event.duration_ms ?? 0);\n  const duration = formatDuration(durationMs);\n\n  const levelColor = LEVEL_COLORS[level] ?? '';\n  const levelStr = c(levelColor, level.toUpperCase().padEnd(5));\n\n  const parts = [c(DIM, timestamp), levelStr];\n  if (service) parts.push(c(DIM, `[${service}]`));\n  if (method) parts.push(c(BOLD, String(method)));\n  if (path) parts.push(String(path));\n  if (status) {\n    const statusNum = Number(status);\n    const statusColor =\n      statusNum >= 500 ? RED : statusNum >= 400 ? YELLOW : GREEN;\n    parts.push(c(statusColor, String(status)));\n  }\n  parts.push(c(DIM, `in ${duration}`));\n\n  const header = parts.join(' ');\n\n  const tree = groupAttributes(event);\n  if (Object.keys(tree).length === 0) {\n    return header;\n  }\n\n  const treeLines = renderTree(tree, '  ', []);\n  return [header, ...treeLines].join('\\n');\n}\n","/**\n * Canonical Log Line Processor\n *\n * Automatically emits spans as canonical log lines (wide events) when they end.\n * Implements canonical log line\" pattern: one comprehensive\n * event per request with all context.\n *\n * When a span ends, this processor creates a log record with ALL span attributes,\n * making the span itself the canonical log line that can be queried like structured data.\n *\n * @example\n * ```typescript\n * import { init } from 'autotel';\n *\n * init({\n *   service: 'my-app',\n *   canonicalLogLines: {\n *     enabled: true,\n *     rootSpansOnly: true, // One canonical log line per request\n *   },\n * });\n * ```\n */\n\nimport type {\n  SpanProcessor,\n  ReadableSpan,\n} from '@opentelemetry/sdk-trace-base';\nimport type { Attributes, AttributeValue } from '@opentelemetry/api';\nimport { logs, SeverityNumber } from '@opentelemetry/api-logs';\nimport type { Logger } from '../logger';\nimport { formatPrettyLogLine, formatDuration } from '../pretty-log-formatter';\n\n/**\n * Function to redact sensitive attribute values\n */\nexport type AttributeRedactorFn = (\n  key: string,\n  value: AttributeValue,\n) => AttributeValue;\n\nexport interface CanonicalLogLineEvent {\n  span: ReadableSpan;\n  level: 'debug' | 'info' | 'warn' | 'error';\n  message: string;\n  event: Record<string, unknown>;\n}\n\nexport interface KeepCondition {\n  /** Keep events where HTTP status >= this value. */\n  status?: number;\n  /** Keep events where duration_ms >= this value. */\n  durationMs?: number;\n  /** Keep events matching this path pattern (simple prefix match). */\n  path?: string;\n}\n\nexport interface CanonicalLogLineOptions {\n  /** Logger to use for emitting canonical log lines (defaults to OTel Logs API) */\n  logger?: Logger;\n  /** Only emit canonical log lines for root spans (default: false) */\n  rootSpansOnly?: boolean;\n  /** Minimum log level for canonical log lines (default: 'info') */\n  minLevel?: 'debug' | 'info' | 'warn' | 'error';\n  /** Custom message format (default: uses span name) */\n  messageFormat?: (span: ReadableSpan) => string;\n  /** Whether to include resource attributes (default: true) */\n  includeResourceAttributes?: boolean;\n  /**\n   * Attribute redactor function to apply before logging.\n   * This ensures sensitive data is redacted in canonical log lines,\n   * matching the behavior of attributeRedactor in init().\n   */\n  attributeRedactor?: AttributeRedactorFn;\n  /** Predicate to decide whether to emit (runs after event is built). */\n  shouldEmit?: (ctx: CanonicalLogLineEvent) => boolean;\n  /**\n   * Declarative tail sampling conditions (OR logic). If any condition matches,\n   * the event is kept. Ignored when `shouldEmit` is provided.\n   *\n   * @example\n   * keep: [{ status: 500 }, { durationMs: 1000 }]\n   */\n  keep?: KeepCondition[];\n  /** Callback invoked after emit for custom fan-out. */\n  drain?: (ctx: CanonicalLogLineEvent) => void | Promise<void>;\n  /** Handler for drain failures. */\n  onDrainError?: (error: unknown, ctx: CanonicalLogLineEvent) => void;\n  /**\n   * Pretty-print canonical log lines to console in a tree format.\n   * Defaults to true when NODE_ENV is 'development'.\n   */\n  pretty?: boolean;\n}\n\n/**\n * Span processor that automatically emits spans as canonical log lines\n *\n * When a span ends, this processor creates a log record with ALL span attributes.\n * This implements the \"canonical log line\" pattern: one comprehensive event\n * per request with all context, queryable as structured data.\n *\n * **Key Benefits:**\n * - One log line per request with all context (wide event)\n * - High-cardinality, high-dimensionality data for powerful queries\n * - Automatic - no manual logging needed\n * - Works with any logger or OTel Logs API\n *\n * @example Basic usage\n * ```typescript\n * import { init } from 'autotel';\n *\n * init({\n *   service: 'checkout-api',\n *   canonicalLogLines: {\n *     enabled: true,\n *     rootSpansOnly: true, // One canonical log line per request\n *   },\n * });\n * ```\n *\n * @example With custom logger\n * ```typescript\n * import pino from 'pino';\n * import { init } from 'autotel';\n *\n * const logger = pino();\n * init({\n *   service: 'my-app',\n *   logger,\n *   canonicalLogLines: {\n *     enabled: true,\n *     logger, // Use Pino for canonical log lines\n *     rootSpansOnly: true,\n *   },\n * });\n * ```\n *\n * @example Custom message format\n * ```typescript\n * init({\n *   service: 'my-app',\n *   canonicalLogLines: {\n *     enabled: true,\n *     messageFormat: (span) => {\n *       const status = span.status.code === 2 ? 'ERROR' : 'SUCCESS';\n *       return `${span.name} [${status}]`;\n *     },\n *   },\n * });\n * ```\n */\nexport class CanonicalLogLineProcessor implements SpanProcessor {\n  private logger?: Logger;\n  private rootSpansOnly: boolean;\n  private minLevel: 'debug' | 'info' | 'warn' | 'error';\n  private messageFormat: (span: ReadableSpan) => string;\n  private includeResourceAttributes: boolean;\n  private attributeRedactor?: AttributeRedactorFn;\n  private shouldEmit?: (ctx: CanonicalLogLineEvent) => boolean;\n  private drain?: (ctx: CanonicalLogLineEvent) => void | Promise<void>;\n  private onDrainError?: (error: unknown, ctx: CanonicalLogLineEvent) => void;\n  private pretty: boolean;\n  private getOTelLogger: (() => ReturnType<typeof logs.getLogger>) | null =\n    null;\n\n  constructor(options: CanonicalLogLineOptions = {}) {\n    this.logger = options.logger;\n    this.rootSpansOnly = options.rootSpansOnly ?? false;\n    this.minLevel = options.minLevel ?? 'info';\n    this.messageFormat =\n      options.messageFormat ?? ((span) => `[${span.name}] Request completed`);\n    this.includeResourceAttributes = options.includeResourceAttributes ?? true;\n    this.attributeRedactor = options.attributeRedactor;\n    this.shouldEmit =\n      options.shouldEmit ?? this.buildKeepPredicate(options.keep);\n    this.drain = options.drain;\n    this.onDrainError = options.onDrainError;\n    this.pretty =\n      options.pretty ??\n      (typeof process !== 'undefined' &&\n        process.env.NODE_ENV === 'development');\n\n    if (!this.logger) {\n      this.getOTelLogger = () => logs.getLogger('autotel.canonical-log-line');\n    }\n  }\n\n  private buildKeepPredicate(\n    keep?: KeepCondition[],\n  ): ((ctx: CanonicalLogLineEvent) => boolean) | undefined {\n    if (!keep || keep.length === 0) return undefined;\n\n    return (ctx: CanonicalLogLineEvent) => {\n      return keep.some((condition) => {\n        if (condition.status !== undefined) {\n          const httpStatus = Number(\n            ctx.event['http.response.status_code'] ?? 0,\n          );\n          if (httpStatus >= condition.status) return true;\n        }\n        if (\n          condition.durationMs !== undefined &&\n          Number(ctx.event.duration_ms ?? 0) >= condition.durationMs\n        ) {\n          return true;\n        }\n        if (condition.path !== undefined) {\n          const route = String(\n            ctx.event['http.route'] ?? ctx.event['url.path'] ?? '',\n          );\n          if (route.startsWith(condition.path)) return true;\n        }\n        return false;\n      });\n    };\n  }\n\n  onStart(): void {\n    // No-op\n  }\n\n  onEnd(span: ReadableSpan): void {\n    if (\n      this.rootSpansOnly &&\n      span.parentSpanContext?.spanId &&\n      !span.parentSpanContext.isRemote\n    ) {\n      return;\n    }\n\n    const level = this.getLogLevel(span);\n    if (!this.shouldLog(level)) {\n      return;\n    }\n\n    const canonicalLogLine = this.buildCanonicalLogLine(span);\n    const message = this.messageFormat(span);\n    const eventContext: CanonicalLogLineEvent = {\n      span,\n      level,\n      message,\n      event: canonicalLogLine,\n    };\n\n    if (this.shouldEmit && !this.shouldEmit(eventContext)) return;\n\n    if (this.pretty) {\n      console.log(formatPrettyLogLine(eventContext));\n    }\n\n    if (this.logger) {\n      this.emitViaLogger(level, message, canonicalLogLine);\n    } else if (this.getOTelLogger) {\n      const otelLogger = this.getOTelLogger();\n      this.emitViaOTel(level, message, canonicalLogLine, otelLogger);\n    }\n\n    if (this.drain) {\n      Promise.resolve(this.drain(eventContext)).catch((error) => {\n        if (this.onDrainError) {\n          this.onDrainError(error, eventContext);\n          return;\n        }\n        this.reportInternalWarning('canonicalLogLines.drain failed', error);\n      });\n    }\n  }\n\n  private buildCanonicalLogLine(span: ReadableSpan): Record<string, unknown> {\n    const durationMs = span.duration[0] * 1000 + span.duration[1] / 1_000_000;\n    const timestamp = new Date(\n      span.startTime[0] * 1000 + span.startTime[1] / 1_000_000,\n    ).toISOString();\n\n    // Span attributes first so core metadata fields below take precedence\n    const canonicalLogLine: Record<string, unknown> = {};\n    const attributes = this.redactAttributes(span.attributes);\n    Object.assign(canonicalLogLine, attributes);\n\n    if (this.includeResourceAttributes) {\n      const resourceAttrs = this.redactAttributes(\n        span.resource.attributes as Attributes,\n      );\n      Object.assign(canonicalLogLine, resourceAttrs);\n    }\n\n    canonicalLogLine.operation = span.name;\n    canonicalLogLine.traceId = span.spanContext().traceId;\n    canonicalLogLine.spanId = span.spanContext().spanId;\n    canonicalLogLine.correlationId = span.spanContext().traceId.slice(0, 16);\n    canonicalLogLine.duration_ms = Math.round(durationMs * 100) / 100;\n    canonicalLogLine.duration = formatDuration(durationMs);\n    canonicalLogLine.status_code = span.status.code;\n    canonicalLogLine.status_message = span.status.message || undefined;\n    canonicalLogLine.timestamp = timestamp;\n\n    return canonicalLogLine;\n  }\n\n  private redactAttributes(attributes: Attributes): Record<string, unknown> {\n    if (!this.attributeRedactor) {\n      return { ...attributes };\n    }\n\n    const redacted: Record<string, unknown> = {};\n    for (const [key, value] of Object.entries(attributes)) {\n      if (value !== undefined) {\n        redacted[key] = this.attributeRedactor(key, value);\n      }\n    }\n    return redacted;\n  }\n\n  private emitViaLogger(\n    level: 'debug' | 'info' | 'warn' | 'error',\n    message: string,\n    canonicalLogLine: Record<string, unknown>,\n  ): void {\n    this.logger![level](canonicalLogLine, message);\n  }\n\n  private emitViaOTel(\n    level: 'debug' | 'info' | 'warn' | 'error',\n    message: string,\n    canonicalLogLine: Record<string, unknown>,\n    otelLogger: ReturnType<typeof logs.getLogger>,\n  ): void {\n    const otelAttributes: Record<string, string | number | boolean> = {};\n    for (const [key, value] of Object.entries(canonicalLogLine)) {\n      if (\n        typeof value === 'string' ||\n        typeof value === 'number' ||\n        typeof value === 'boolean'\n      ) {\n        otelAttributes[key] = value;\n      } else if (value !== null && value !== undefined) {\n        otelAttributes[key] = String(value);\n      }\n    }\n    otelLogger.emit({\n      severityNumber: this.getSeverityNumber(level),\n      severityText: level.toUpperCase(),\n      body: message,\n      attributes: otelAttributes,\n    });\n  }\n\n  private getLogLevel(span: ReadableSpan): 'debug' | 'info' | 'warn' | 'error' {\n    const explicitLevel = span.attributes['autotel.log.level'];\n    if (\n      explicitLevel === 'debug' ||\n      explicitLevel === 'info' ||\n      explicitLevel === 'warn' ||\n      explicitLevel === 'error'\n    ) {\n      return explicitLevel;\n    }\n\n    if (span.status.code === 2) return 'error';\n    return 'info';\n  }\n\n  private shouldLog(level: string): boolean {\n    const levels = ['debug', 'info', 'warn', 'error'];\n    return levels.indexOf(level) >= levels.indexOf(this.minLevel);\n  }\n\n  private getSeverityNumber(level: string): SeverityNumber {\n    const mapping: Record<string, SeverityNumber> = {\n      debug: SeverityNumber.DEBUG,\n      info: SeverityNumber.INFO,\n      warn: SeverityNumber.WARN,\n      error: SeverityNumber.ERROR,\n    };\n    return mapping[level] ?? SeverityNumber.INFO;\n  }\n\n  private reportInternalWarning(message: string, error: unknown): void {\n    const err =\n      error instanceof Error ? error.message : String(error ?? 'unknown error');\n    if (this.logger) {\n      this.logger.warn({ error: err }, `[autotel] ${message}`);\n      return;\n    }\n    console.warn(`[autotel] ${message}: ${err}`);\n  }\n\n  async forceFlush(): Promise<void> {\n    // No-op\n  }\n\n  async shutdown(): Promise<void> {\n    // No-op\n  }\n}\n"],"mappings":"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"}