{"version":3,"sources":["../src/semantic-helpers.ts"],"names":["trace"],"mappings":"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","file":"chunk-YEVCD6DR.cjs","sourcesContent":["/**\n * Semantic convention helpers for OpenTelemetry\n *\n * Pre-configured trace helpers that follow OpenTelemetry semantic conventions\n * for common operation types. Reduces boilerplate and ensures consistency.\n *\n * Based on: https://opentelemetry.io/docs/specs/semconv/\n */\n\nimport { trace } from './functional';\nimport type { TraceContext } from './trace-context';\nimport type { Attributes } from '@opentelemetry/api';\n\n/**\n * Configuration for LLM (Large Language Model) operations\n *\n * Follows Gen AI semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/gen-ai/\n */\nexport interface LLMConfig {\n  /** Model name (e.g., 'gpt-4', 'claude-3-opus') */\n  model: string;\n  /** Operation type */\n  operation?: 'chat' | 'completion' | 'embedding';\n  /** Model provider (e.g., 'openai', 'anthropic', 'cohere') - maps to gen.ai.system */\n  provider?: string;\n  /** Additional attributes to add to the span */\n  attributes?: Attributes;\n}\n\n/**\n * Configuration for database operations\n *\n * Follows DB semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/database/\n */\nexport interface DBConfig {\n  /** Database system (e.g., 'postgresql', 'mongodb', 'redis') */\n  system: string;\n  /** Operation type (e.g., 'SELECT', 'INSERT', 'find', 'get') */\n  operation?: string;\n  /** Database name */\n  database?: string;\n  /** Collection/table name */\n  collection?: string;\n  /** Additional attributes to add to the span */\n  attributes?: Attributes;\n}\n\n/**\n * Configuration for HTTP client operations\n *\n * Follows HTTP semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/http/\n */\nexport interface HTTPConfig {\n  /** HTTP method (e.g., 'GET', 'POST') */\n  method?: string;\n  /** Target URL or URL template */\n  url?: string;\n  /** Additional attributes to add to the span */\n  attributes?: Attributes;\n}\n\n/**\n * Configuration for messaging operations\n *\n * Follows Messaging semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/messaging/\n */\nexport interface MessagingConfig {\n  /** Messaging system (e.g., 'kafka', 'rabbitmq', 'sqs') */\n  system: string;\n  /** Operation type */\n  operation?: 'publish' | 'receive' | 'process';\n  /** Destination name (queue/topic) */\n  destination?: string;\n  /** Additional attributes to add to the span */\n  attributes?: Attributes;\n}\n\n/**\n * Trace LLM operations with Gen AI semantic conventions\n *\n * Automatically adds standard attributes for LLM operations:\n * - gen.ai.request.model\n * - gen.ai.operation.name\n * - gen.ai.system\n *\n * **Use Cases:**\n * - Chat completions\n * - Text generation\n * - Embeddings\n * - Multi-step LLM workflows\n *\n * @param config - LLM operation configuration\n * @returns Traced function factory with Gen AI attributes\n *\n * @example Chat completion with OpenAI\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import OpenAI from 'openai'\n *\n * const openai = new OpenAI()\n *\n * export const generateResponse = traceLLM({\n *   model: 'gpt-4-turbo',\n *   operation: 'chat',\n *   provider: 'openai'\n * })(ctx => async (prompt: string) => {\n *   const response = await openai.chat.completions.create({\n *     model: 'gpt-4-turbo',\n *     messages: [{ role: 'user', content: prompt }]\n *   })\n *\n *   // Add usage metrics to span\n *   ctx.setAttribute('gen.ai.usage.completion_tokens', response.usage?.completion_tokens)\n *   ctx.setAttribute('gen.ai.usage.prompt_tokens', response.usage?.prompt_tokens)\n *\n *   return response.choices[0].message.content\n * })\n * ```\n *\n * @example Anthropic Claude with streaming\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import Anthropic from '@anthropic-ai/sdk'\n *\n * const anthropic = new Anthropic()\n *\n * export const streamResponse = traceLLM({\n *   model: 'claude-3-opus-20240229',\n *   operation: 'chat',\n *   provider: 'anthropic'\n * })(ctx => async function* (prompt: string) {\n *   const stream = await anthropic.messages.create({\n *     model: 'claude-3-opus-20240229',\n *     messages: [{ role: 'user', content: prompt }],\n *     stream: true,\n *     max_tokens: 1024\n *   })\n *\n *   let totalTokens = 0\n *   for await (const event of stream) {\n *     if (event.type === 'content_block_delta') {\n *       yield event.delta.text\n *     }\n *     if (event.type === 'message_stop') {\n *       ctx.setAttribute('gen.ai.usage.completion_tokens', event.message.usage.output_tokens)\n *       totalTokens = event.message.usage.output_tokens\n *     }\n *   }\n *\n *   return totalTokens\n * })\n * ```\n *\n * @example Embeddings\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import { OpenAIEmbeddings } from '@langchain/openai'\n *\n * const embeddings = new OpenAIEmbeddings()\n *\n * export const embed = traceLLM({\n *   model: 'text-embedding-3-small',\n *   operation: 'embedding',\n *   provider: 'openai'\n * })(ctx => async (text: string) => {\n *   const result = await embeddings.embedQuery(text)\n *   ctx.setAttribute('gen.ai.response.embedding_length', result.length)\n *   return result\n * })\n * ```\n *\n * @public\n */\nexport function traceLLM<TArgs extends unknown[], TReturn>(config: LLMConfig) {\n  return (\n    fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n  ): ((...args: TArgs) => Promise<TReturn>) => {\n    return trace<TArgs, TReturn>((ctx) => {\n      // Set semantic convention attributes\n      ctx.setAttribute('gen.ai.request.model', config.model);\n      ctx.setAttribute('gen.ai.operation.name', config.operation || 'chat');\n      if (config.provider) {\n        ctx.setAttribute('gen.ai.system', config.provider);\n      }\n      if (config.attributes) {\n        for (const [key, value] of Object.entries(config.attributes)) {\n          if (value !== undefined && value !== null) {\n            // setAttribute only accepts primitives (string | number | boolean)\n            // Arrays and objects should be serialized\n            const attrValue =\n              typeof value === 'string' ||\n              typeof value === 'number' ||\n              typeof value === 'boolean'\n                ? value\n                : JSON.stringify(value);\n            ctx.setAttribute(key, attrValue);\n          }\n        }\n      }\n\n      // Call the user's factory to get their function and return it\n      return fnFactory(ctx);\n    });\n  };\n}\n\n/**\n * Trace database operations with DB semantic conventions\n *\n * Automatically adds standard attributes for database operations:\n * - db.system\n * - db.operation\n * - db.name\n * - db.collection.name (for NoSQL)\n *\n * **Use Cases:**\n * - SQL queries (PostgreSQL, MySQL, SQLite)\n * - NoSQL operations (MongoDB, DynamoDB, Redis)\n * - ORM queries (Prisma, TypeORM, Drizzle)\n *\n * @param config - Database operation configuration\n * @returns Traced function factory with DB attributes\n *\n * @example PostgreSQL query\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { pool } from './db'\n *\n * export const getUser = traceDB({\n *   system: 'postgresql',\n *   operation: 'SELECT',\n *   database: 'app_db',\n *   collection: 'users'\n * })(ctx => async (userId: string) => {\n *   const query = 'SELECT * FROM users WHERE id = $1'\n *   ctx.setAttribute('db.statement', query)\n *\n *   const result = await pool.query(query, [userId])\n *   ctx.setAttribute('db.rows_affected', result.rowCount)\n *\n *   return result.rows[0]\n * })\n * ```\n *\n * @example MongoDB with Mongoose\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { User } from './models/User'\n *\n * export const findUsers = traceDB({\n *   system: 'mongodb',\n *   operation: 'find',\n *   database: 'app_db',\n *   collection: 'users'\n * })(ctx => async (filter: object) => {\n *   ctx.setAttribute('db.mongodb.filter', JSON.stringify(filter))\n *\n *   const users = await User.find(filter).limit(100)\n *   ctx.setAttribute('db.response.count', users.length)\n *\n *   return users\n * })\n * ```\n *\n * @example Redis operations\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { redis } from './redis'\n *\n * export const cacheGet = traceDB({\n *   system: 'redis',\n *   operation: 'GET'\n * })(ctx => async (key: string) => {\n *   ctx.setAttribute('db.redis.key', key)\n *\n *   const value = await redis.get(key)\n *   ctx.setAttribute('db.response.cache_hit', value !== null)\n *\n *   return value\n * })\n * ```\n *\n * @example Prisma with detailed query info\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { prisma } from './prisma'\n *\n * export const createPost = traceDB({\n *   system: 'postgresql',\n *   operation: 'INSERT',\n *   database: 'app_db',\n *   collection: 'posts'\n * })(ctx => async (data: { title: string; content: string; authorId: string }) => {\n *   ctx.setAttribute('db.prisma.model', 'Post')\n *   ctx.setAttribute('db.prisma.action', 'create')\n *\n *   const post = await prisma.post.create({ data })\n *\n *   ctx.setAttribute('db.response.id', post.id)\n *   return post\n * })\n * ```\n *\n * @public\n */\nexport function traceDB<TArgs extends unknown[], TReturn>(config: DBConfig) {\n  return (\n    fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n  ): ((...args: TArgs) => Promise<TReturn>) => {\n    return trace<TArgs, TReturn>((ctx) => {\n      // Set semantic convention attributes\n      ctx.setAttribute('db.system', config.system);\n      if (config.operation) {\n        ctx.setAttribute('db.operation', config.operation);\n      }\n      if (config.database) {\n        ctx.setAttribute('db.name', config.database);\n      }\n      if (config.collection) {\n        ctx.setAttribute('db.collection.name', config.collection);\n      }\n      if (config.attributes) {\n        for (const [key, value] of Object.entries(config.attributes)) {\n          if (value !== undefined && value !== null) {\n            // setAttribute only accepts primitives (string | number | boolean)\n            // Arrays and objects should be serialized\n            const attrValue =\n              typeof value === 'string' ||\n              typeof value === 'number' ||\n              typeof value === 'boolean'\n                ? value\n                : JSON.stringify(value);\n            ctx.setAttribute(key, attrValue);\n          }\n        }\n      }\n\n      // Call the user's factory to get their function and return it\n      return fnFactory(ctx);\n    });\n  };\n}\n\n/**\n * Trace HTTP client operations with HTTP semantic conventions\n *\n * Automatically adds standard attributes for HTTP requests:\n * - http.request.method\n * - url.full\n *\n * **Use Cases:**\n * - External API calls\n * - Microservice communication\n * - Third-party integrations\n *\n * @param config - HTTP operation configuration\n * @returns Traced function factory with HTTP attributes\n *\n * @example Fetch API\n * ```typescript\n * import { traceHTTP } from 'autotel/semantic-helpers'\n *\n * export const fetchUser = traceHTTP({\n *   method: 'GET',\n *   url: 'https://api.example.com/users/:id'\n * })(ctx => async (userId: string) => {\n *   const url = `https://api.example.com/users/${userId}`\n *   ctx.setAttribute('url.full', url)\n *\n *   const response = await fetch(url)\n *   ctx.setAttribute('http.response.status_code', response.status)\n *\n *   if (!response.ok) {\n *     ctx.setAttribute('error', true)\n *     throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n *   }\n *\n *   return response.json()\n * })\n * ```\n *\n * @example Axios with retry logic\n * ```typescript\n * import { traceHTTP } from 'autotel/semantic-helpers'\n * import axios from 'axios'\n *\n * export const sendWebhook = traceHTTP({\n *   method: 'POST',\n *   url: 'https://webhook.example.com/events'\n * })(ctx => async (payload: object) => {\n *   let attempts = 0\n *   const maxAttempts = 3\n *\n *   while (attempts < maxAttempts) {\n *     try {\n *       attempts++\n *       ctx.setAttribute('http.request.resend_count', attempts - 1)\n *\n *       const response = await axios.post('https://webhook.example.com/events', payload)\n *       ctx.setAttribute('http.response.status_code', response.status)\n *       return response.data\n *     } catch (error) {\n *       if (attempts >= maxAttempts) throw error\n *       await new Promise(resolve => setTimeout(resolve, 1000 * attempts))\n *     }\n *   }\n * })\n * ```\n *\n * @public\n */\nexport function traceHTTP<TArgs extends unknown[], TReturn>(\n  config: HTTPConfig,\n) {\n  return (\n    fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n  ): ((...args: TArgs) => Promise<TReturn>) => {\n    return trace<TArgs, TReturn>((ctx) => {\n      // Set semantic convention attributes\n      if (config.method) {\n        ctx.setAttribute('http.request.method', config.method);\n      }\n      if (config.url) {\n        ctx.setAttribute('url.full', config.url);\n      }\n      if (config.attributes) {\n        for (const [key, value] of Object.entries(config.attributes)) {\n          if (value !== undefined && value !== null) {\n            // setAttribute only accepts primitives (string | number | boolean)\n            // Arrays and objects should be serialized\n            const attrValue =\n              typeof value === 'string' ||\n              typeof value === 'number' ||\n              typeof value === 'boolean'\n                ? value\n                : JSON.stringify(value);\n            ctx.setAttribute(key, attrValue);\n          }\n        }\n      }\n\n      // Call the user's factory to get their function and return it\n      return fnFactory(ctx);\n    });\n  };\n}\n\n/**\n * Trace messaging operations with Messaging semantic conventions\n *\n * Automatically adds standard attributes for messaging:\n * - messaging.system\n * - messaging.operation\n * - messaging.destination.name\n *\n * **Use Cases:**\n * - Publishing messages to queues/topics\n * - Consuming messages from queues/topics\n * - Event-driven architectures\n *\n * @param config - Messaging operation configuration\n * @returns Traced function factory with Messaging attributes\n *\n * @example Publishing to Kafka\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { kafka } from './kafka'\n *\n * const producer = kafka.producer()\n *\n * export const publishEvent = traceMessaging({\n *   system: 'kafka',\n *   operation: 'publish',\n *   destination: 'user-events'\n * })(ctx => async (event: { type: string; userId: string; data: object }) => {\n *   ctx.setAttribute('messaging.message.type', event.type)\n *   ctx.setAttribute('messaging.kafka.partition', 0)\n *\n *   await producer.send({\n *     topic: 'user-events',\n *     messages: [\n *       {\n *         key: event.userId,\n *         value: JSON.stringify(event.data)\n *       }\n *     ]\n *   })\n *\n *   ctx.setAttribute('messaging.message.id', event.userId)\n * })\n * ```\n *\n * @example Consuming from RabbitMQ\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { channel } from './rabbitmq'\n *\n * export const processOrder = traceMessaging({\n *   system: 'rabbitmq',\n *   operation: 'process',\n *   destination: 'orders'\n * })(ctx => async (message: { orderId: string; items: object[] }) => {\n *   ctx.setAttribute('messaging.message.id', message.orderId)\n *   ctx.setAttribute('messaging.message.body.size', JSON.stringify(message).length)\n *\n *   // Process order logic\n *   const result = await processOrderInternal(message)\n *\n *   ctx.setAttribute('messaging.operation.result', 'success')\n *   return result\n * })\n * ```\n *\n * @example AWS SQS with batch processing\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { SQS } from '@aws-sdk/client-sqs'\n *\n * const sqs = new SQS()\n *\n * export const sendBatch = traceMessaging({\n *   system: 'aws_sqs',\n *   operation: 'publish',\n *   destination: 'notifications-queue'\n * })(ctx => async (messages: Array<{ id: string; body: object }>) => {\n *   ctx.setAttribute('messaging.batch.message_count', messages.length)\n *\n *   const result = await sqs.sendMessageBatch({\n *     QueueUrl: process.env.QUEUE_URL,\n *     Entries: messages.map(msg => ({\n *       Id: msg.id,\n *       MessageBody: JSON.stringify(msg.body)\n *     }))\n *   })\n *\n *   ctx.setAttribute('messaging.operation.success_count', result.Successful?.length || 0)\n *   ctx.setAttribute('messaging.operation.failed_count', result.Failed?.length || 0)\n *\n *   return result\n * })\n * ```\n *\n * @public\n */\nexport function traceMessaging<TArgs extends unknown[], TReturn>(\n  config: MessagingConfig,\n) {\n  return (\n    fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n  ): ((...args: TArgs) => Promise<TReturn>) => {\n    return trace<TArgs, TReturn>((ctx) => {\n      // Set semantic convention attributes\n      ctx.setAttribute('messaging.system', config.system);\n      if (config.operation) {\n        ctx.setAttribute('messaging.operation', config.operation);\n      }\n      if (config.destination) {\n        ctx.setAttribute('messaging.destination.name', config.destination);\n      }\n      if (config.attributes) {\n        for (const [key, value] of Object.entries(config.attributes)) {\n          if (value !== undefined && value !== null) {\n            // setAttribute only accepts primitives (string | number | boolean)\n            // Arrays and objects should be serialized\n            const attrValue =\n              typeof value === 'string' ||\n              typeof value === 'number' ||\n              typeof value === 'boolean'\n                ? value\n                : JSON.stringify(value);\n            ctx.setAttribute(key, attrValue);\n          }\n        }\n      }\n\n      // Call the user's factory to get their function and return it\n      return fnFactory(ctx);\n    });\n  };\n}\n"]}