UNPKG

@vfarcic/dot-ai

Version:

AI-powered development productivity platform that enhances software development workflows through intelligent automation and AI-driven assistance

103 lines (102 loc) 3.93 kB
"use strict"; /** * Qdrant Vector Database Tracing * * Provides distributed tracing instrumentation for Qdrant vector database operations. * Creates CLIENT spans with database semantic conventions and vector-specific attributes. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.withQdrantTracing = withQdrantTracing; const api_1 = require("@opentelemetry/api"); const tracer = api_1.trace.getTracer('dot-ai-mcp-qdrant'); /** * Generic Qdrant operation tracing wrapper * * @param operationContext - Qdrant operation metadata * @param handler - Async operation to trace * @returns Result from handler * * @example * ```typescript * // Trace vector search * const results = await withQdrantTracing( * { * operation: 'vector.search', * collectionName: 'capabilities', * vectorSize: 1536, * limit: 10, * scoreThreshold: 0.5, * serverUrl: 'http://localhost:6333' * }, * async () => await this.client.search(...) * ); * * // Trace document upsert * await withQdrantTracing( * { * operation: 'vector.upsert', * collectionName: 'patterns', * documentId: 'pattern-123', * vectorSize: 384, * serverUrl: 'http://localhost:6333' * }, * async () => await this.client.upsert(...) * ); * ``` */ async function withQdrantTracing(operationContext, handler) { const { operation, collectionName, ...metadata } = operationContext; // Create span name: "qdrant.{operation} {collection}" // Examples: "qdrant.vector.search capabilities", "qdrant.vector.upsert patterns" const spanName = `qdrant.${operation} ${collectionName}`; return tracer.startActiveSpan(spanName, { kind: 2, // CLIENT span attributes: { // Database semantic conventions 'db.system': 'qdrant', 'db.operation.name': operation, 'db.collection.name': collectionName, // Vector-specific attributes ...(metadata.vectorSize && { 'db.vector.dimensions': metadata.vectorSize }), ...(metadata.limit && { 'db.query.limit': metadata.limit }), ...(metadata.scoreThreshold && { 'db.vector.score_threshold': metadata.scoreThreshold }), ...(metadata.keywordCount && { 'db.query.keyword_count': metadata.keywordCount }), ...(metadata.documentId && { 'db.document.id': metadata.documentId }), ...(metadata.serverUrl && { 'server.address': metadata.serverUrl }) } }, async (span) => { try { // Execute operation const result = await handler(); // Add result metadata for search operations if (operation === 'vector.search' || operation === 'vector.search_keywords') { if (Array.isArray(result)) { span.setAttribute('db.query.result_count', result.length); // For search results with scores, track top score if (result.length > 0 && 'score' in result[0]) { span.setAttribute('db.vector.top_score', result[0].score); } } } // Add result metadata for list operations if (operation === 'vector.list' && Array.isArray(result)) { span.setAttribute('db.query.result_count', result.length); } // Mark span as successful span.setStatus({ code: api_1.SpanStatusCode.OK }); return result; } catch (error) { // Record error in span span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error instanceof Error ? error.message : String(error) }); span.recordException(error instanceof Error ? error : new Error(String(error))); throw error; } finally { span.end(); } }); }