@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
JavaScript
;
/**
* 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();
}
});
}