{"version":3,"sources":["../src/http.ts"],"names":["args","getConfig","SpanStatusCode","getActiveContextWithBaggage","propagation","context"],"mappings":"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","file":"http.cjs","sourcesContent":["/**\n * HTTP Instrumentation Helpers\n *\n * Optional import: Not included in main bundle\n * Import from: 'autotel/http'\n *\n * Provides decorators and utilities for HTTP client instrumentation.\n * Works with fetch, axios, and other HTTP clients.\n *\n * @example\n * ```typescript\n * import { HttpInstrumented } from 'autotel/http'\n *\n * @HttpInstrumented()\n * class ApiClient {\n *   async getUser(id: string) {\n *     return fetch(`/api/users/${id}`)\n *   }\n * }\n * ```\n */\n\nimport { SpanStatusCode, context, propagation } from '@opentelemetry/api';\nimport { getConfig } from './config';\nimport { getActiveContextWithBaggage } from './trace-context';\n\nexport interface HttpInstrumentedOptions {\n  /** Service name for HTTP calls (default: 'http-client') */\n  serviceName?: string;\n  /** Extract URL from method arguments (default: first arg) */\n  urlExtractor?: (args: unknown[]) => string | undefined;\n  /** Extract HTTP method from method name or args */\n  methodExtractor?: (methodName: string, args: unknown[]) => string;\n  /** Add custom attributes to spans */\n  attributesFromArgs?: (args: unknown[]) => Record<string, string | number>;\n  /** Slow request threshold in milliseconds (adds warning attribute) - default: 3000ms */\n  slowRequestThresholdMs?: number;\n}\n\n/**\n * Decorator for auto-instrumenting HTTP client methods\n *\n * @example Basic usage\n * ```typescript\n * @HttpInstrumented()\n * class ApiClient {\n *   async fetchUser(userId: string) {\n *     const res = await fetch(`https://api.example.com/users/${userId}`)\n *     return res.json()\n *   }\n *\n *   async createOrder(order: Order) {\n *     const res = await fetch('https://api.example.com/orders', {\n *       method: 'POST',\n *       body: JSON.stringify(order)\n *     })\n *     return res.json()\n *   }\n * }\n * ```\n *\n * @example Advanced usage with custom extractors\n * ```typescript\n * @HttpInstrumented({\n *   serviceName: 'payment-gateway',\n *   urlExtractor: (args) => {\n *     const config = args[0] as RequestConfig\n *     return config.url\n *   },\n *   attributesFromArgs: (args) => ({\n *     'http.request_id': args[0]?.requestId,\n *     'http.retry_count': args[0]?.retryCount || 0\n *   })\n * })\n * class PaymentClient {\n *   async charge(config: RequestConfig) {\n *     return axios(config)\n *   }\n * }\n * ```\n */\nexport function HttpInstrumented(options: HttpInstrumentedOptions = {}) {\n  const serviceName = options.serviceName || 'http-client';\n  const slowRequestThresholdMs = options.slowRequestThresholdMs ?? 3000;\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type\n  return function <T extends { new (...args: any[]): {} }>(\n    target: T,\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    _context: ClassDecoratorContext,\n  ) {\n    return class extends target {\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      constructor(...args: any[]) {\n        super(...args);\n\n        const proto = target.prototype;\n        const methodNames = Object.getOwnPropertyNames(proto).filter(\n          (name) =>\n            name !== 'constructor' &&\n            typeof proto[name] === 'function' &&\n            !name.startsWith('_'),\n        );\n\n        for (const methodName of methodNames) {\n          const originalMethod = proto[methodName];\n\n          if (\n            originalMethod.constructor.name === 'AsyncFunction' ||\n            originalMethod.toString().startsWith('async ')\n          ) {\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            const wrappedMethod = async (...args: any[]) => {\n              const config = getConfig();\n              const tracer = config.tracer;\n\n              const url = options.urlExtractor\n                ? options.urlExtractor(args)\n                : (args[0] as string | undefined);\n\n              const method = options.methodExtractor\n                ? options.methodExtractor(methodName, args)\n                : inferHttpMethod(methodName);\n\n              const spanName = url\n                ? `HTTP ${method} ${extractPath(url)}`\n                : `HTTP ${method}`;\n\n              return tracer.startActiveSpan(spanName, async (span) => {\n                const startTime = performance.now();\n\n                try {\n                  span.setAttributes({\n                    'http.method': method,\n                    'http.url': url || 'unknown',\n                    'service.name': serviceName,\n                    'operation.name': `${serviceName}.${methodName}`,\n                  });\n\n                  if (url) {\n                    const urlObj = parseUrl(url);\n                    span.setAttributes({\n                      'http.scheme': urlObj.protocol,\n                      'http.host': urlObj.host,\n                      'http.target': urlObj.path,\n                    });\n                  }\n\n                  if (options.attributesFromArgs) {\n                    span.setAttributes(options.attributesFromArgs(args));\n                  }\n\n                  const result = await originalMethod.apply(this, args);\n\n                  const duration = performance.now() - startTime;\n\n                  // Extract status code from response\n                  const statusCode = extractStatusCode(result);\n                  if (statusCode) {\n                    span.setAttribute('http.status_code', statusCode);\n\n                    if (statusCode >= 400) {\n                      span.setStatus({\n                        code: SpanStatusCode.ERROR,\n                        message: `HTTP ${statusCode}`,\n                      });\n                    } else {\n                      span.setStatus({ code: SpanStatusCode.OK });\n                    }\n                  } else {\n                    span.setStatus({ code: SpanStatusCode.OK });\n                  }\n\n                  span.setAttributes({\n                    'http.duration_ms': duration,\n                  });\n\n                  // Mark slow requests for investigation\n                  if (duration > slowRequestThresholdMs) {\n                    span.setAttribute('http.slow_request', true);\n                    span.setAttribute(\n                      'http.slow_request_threshold_ms',\n                      slowRequestThresholdMs,\n                    );\n                  }\n\n                  return result;\n                } catch (error) {\n                  const duration = performance.now() - startTime;\n\n                  span.setStatus({\n                    code: SpanStatusCode.ERROR,\n                    message:\n                      error instanceof Error ? error.message : 'Unknown error',\n                  });\n\n                  span.setAttributes({\n                    'http.duration_ms': duration,\n                    'error.type':\n                      error instanceof Error\n                        ? error.constructor.name\n                        : 'Unknown',\n                    'error.message':\n                      error instanceof Error ? error.message : 'Unknown error',\n                  });\n\n                  throw error;\n                } finally {\n                  span.end();\n                }\n              });\n            };\n\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            (this as any)[methodName] = wrappedMethod;\n          }\n        }\n      }\n    };\n  };\n}\n\n/**\n * Helper: Trace a single HTTP request\n *\n * @example\n * ```typescript\n * import { traceHttpRequest } from 'autotel/http'\n *\n * const data = await traceHttpRequest(\n *   'GET /api/users',\n *   () => fetch('https://api.example.com/users')\n * )\n * ```\n */\nexport async function traceHttpRequest<T>(\n  spanName: string,\n  fn: () => Promise<T>,\n  attributes?: Record<string, string | number>,\n): Promise<T> {\n  const config = getConfig();\n  const tracer = config.tracer;\n\n  return tracer.startActiveSpan(spanName, async (span) => {\n    try {\n      if (attributes) {\n        span.setAttributes(attributes);\n      }\n\n      const result = await fn();\n      span.setStatus({ code: SpanStatusCode.OK });\n      return result;\n    } catch (error) {\n      span.setStatus({\n        code: SpanStatusCode.ERROR,\n        message: error instanceof Error ? error.message : 'Unknown error',\n      });\n      throw error;\n    } finally {\n      span.end();\n    }\n  });\n}\n\n// Helper functions\n\nfunction inferHttpMethod(methodName: string): string {\n  const lower = methodName.toLowerCase();\n  if (\n    lower.includes('get') ||\n    lower.includes('fetch') ||\n    lower.includes('list')\n  )\n    return 'GET';\n  if (lower.includes('post') || lower.includes('create')) return 'POST';\n  if (lower.includes('put') || lower.includes('update')) return 'PUT';\n  if (lower.includes('delete') || lower.includes('remove')) return 'DELETE';\n  if (lower.includes('patch')) return 'PATCH';\n  return 'GET'; // Default\n}\n\nfunction extractPath(url: string): string {\n  try {\n    const urlObj = new URL(url);\n    return urlObj.pathname;\n  } catch {\n    // Relative URL or invalid\n    return url.split('?')[0] || url;\n  }\n}\n\nfunction parseUrl(url: string): {\n  protocol: string;\n  host: string;\n  path: string;\n} {\n  try {\n    const urlObj = new URL(url);\n    return {\n      protocol: urlObj.protocol.replace(':', ''),\n      host: urlObj.host,\n      path: urlObj.pathname + urlObj.search,\n    };\n  } catch {\n    return {\n      protocol: 'http',\n      host: 'unknown',\n      path: url,\n    };\n  }\n}\n\nfunction extractStatusCode(result: unknown): number | undefined {\n  if (result && typeof result === 'object') {\n    // Check for Response.status (fetch API)\n    if ('status' in result && typeof result.status === 'number') {\n      return result.status;\n    }\n    // Check for statusCode (axios, node http)\n    if ('statusCode' in result && typeof result.statusCode === 'number') {\n      return result.statusCode;\n    }\n  }\n  return undefined;\n}\n\n/**\n * Inject trace context into HTTP headers (for distributed tracing)\n *\n * This includes W3C Trace Context (traceparent, tracestate) and W3C Baggage headers.\n * Uses OpenTelemetry's propagation system for full compatibility.\n *\n * @example\n * ```typescript\n * import { injectTraceContext } from 'autotel/http'\n *\n * const headers = injectTraceContext({\n *   'Content-Type': 'application/json'\n * })\n *\n * fetch('/api/users', { headers })\n * ```\n *\n * @example With baggage\n * ```typescript\n * import { trace, withBaggage, injectTraceContext } from 'autotel'\n *\n * export const createOrder = trace((ctx) => async (order: Order) => {\n *   return await withBaggage({\n *     baggage: { 'tenant.id': order.tenantId },\n *     fn: async () => {\n *       const headers = injectTraceContext();\n *       // Headers now include 'baggage' header with tenant.id\n *       await fetch('/api/charge', { headers });\n *     },\n *   });\n * });\n * ```\n */\nexport function injectTraceContext(\n  headers: Record<string, string> = {},\n): Record<string, string> {\n  // Use getActiveContextWithBaggage to check stored context (from baggage setters)\n  // This ensures ctx.setBaggage() changes are included in injected headers\n  const currentContext = getActiveContextWithBaggage();\n\n  // Use OpenTelemetry's propagation.inject for full W3C support\n  // This includes traceparent, tracestate, and baggage headers\n  propagation.inject(currentContext, headers);\n\n  return headers;\n}\n\n/**\n * Extract trace context from HTTP headers (for distributed tracing)\n *\n * This extracts W3C Trace Context (traceparent, tracestate) and W3C Baggage headers.\n * Uses OpenTelemetry's propagation system for full compatibility.\n *\n * Returns a context that can be used with context.with() to run code\n * with the extracted trace context and baggage.\n *\n * @example\n * ```typescript\n * import { extractTraceContext, trace } from 'autotel'\n * import { context } from 'autotel'\n *\n * // In Express middleware\n * app.use((req, res, next) => {\n *   const extractedContext = extractTraceContext(req.headers);\n *   context.with(extractedContext, () => {\n *     next();\n *   });\n * });\n * ```\n *\n * @example In a traced function\n * ```typescript\n * export const handleWebhook = trace((ctx) => async (req: Request) => {\n *   const extractedContext = extractTraceContext(req.headers);\n *   return await context.with(extractedContext, async () => {\n *     // Now ctx.getBaggage() will return baggage from the incoming request\n *     const tenantId = ctx.getBaggage('tenant.id');\n *     await processWebhook(req.body);\n *   });\n * });\n * ```\n */\nexport function extractTraceContext(\n  headers: Record<string, string | string[] | undefined>,\n): ReturnType<typeof context.active> {\n  const carrier: Record<string, string> = {};\n\n  // Convert headers to flat string format expected by propagation\n  for (const [key, value] of Object.entries(headers)) {\n    if (value !== undefined) {\n      carrier[key] = Array.isArray(value) ? (value[0] ?? '') : value;\n    }\n  }\n\n  // Extract context using OpenTelemetry's propagation system\n  // Returns a Context that can be used with context.with()\n  return propagation.extract(context.active(), carrier);\n}\n"]}