@vfarcic/dot-ai 0.125.0 → 0.126.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/core/capability-scan-workflow.d.ts +4 -9
  2. package/dist/core/capability-scan-workflow.d.ts.map +1 -1
  3. package/dist/core/capability-scan-workflow.js +203 -455
  4. package/dist/core/discovery.d.ts.map +1 -1
  5. package/dist/core/discovery.js +4 -3
  6. package/dist/core/embedding-service.d.ts +9 -36
  7. package/dist/core/embedding-service.d.ts.map +1 -1
  8. package/dist/core/embedding-service.js +137 -253
  9. package/dist/core/index.d.ts +1 -1
  10. package/dist/core/index.js +2 -2
  11. package/dist/core/kubernetes-utils.d.ts +1 -0
  12. package/dist/core/kubernetes-utils.d.ts.map +1 -1
  13. package/dist/core/kubernetes-utils.js +53 -48
  14. package/dist/core/providers/anthropic-provider.d.ts.map +1 -1
  15. package/dist/core/providers/anthropic-provider.js +352 -282
  16. package/dist/core/providers/vercel-provider.d.ts.map +1 -1
  17. package/dist/core/providers/vercel-provider.js +389 -351
  18. package/dist/core/tracing/ai-tracing.d.ts +80 -0
  19. package/dist/core/tracing/ai-tracing.d.ts.map +1 -0
  20. package/dist/core/tracing/ai-tracing.js +122 -0
  21. package/dist/core/tracing/config.d.ts +15 -0
  22. package/dist/core/tracing/config.d.ts.map +1 -0
  23. package/dist/core/tracing/config.js +133 -0
  24. package/dist/core/tracing/http-tracing.d.ts +28 -0
  25. package/dist/core/tracing/http-tracing.d.ts.map +1 -0
  26. package/dist/core/tracing/http-tracing.js +119 -0
  27. package/dist/core/tracing/index.d.ts +14 -0
  28. package/dist/core/tracing/index.d.ts.map +1 -0
  29. package/dist/core/tracing/index.js +40 -0
  30. package/dist/core/tracing/k8s-tracing.d.ts +57 -0
  31. package/dist/core/tracing/k8s-tracing.d.ts.map +1 -0
  32. package/dist/core/tracing/k8s-tracing.js +155 -0
  33. package/dist/core/tracing/qdrant-tracing.d.ts +68 -0
  34. package/dist/core/tracing/qdrant-tracing.d.ts.map +1 -0
  35. package/dist/core/tracing/qdrant-tracing.js +102 -0
  36. package/dist/core/tracing/tool-tracing.d.ts +31 -0
  37. package/dist/core/tracing/tool-tracing.d.ts.map +1 -0
  38. package/dist/core/tracing/tool-tracing.js +76 -0
  39. package/dist/core/tracing/tracer.d.ts +21 -0
  40. package/dist/core/tracing/tracer.d.ts.map +1 -0
  41. package/dist/core/tracing/tracer.js +215 -0
  42. package/dist/core/tracing/types.d.ts +86 -0
  43. package/dist/core/tracing/types.d.ts.map +1 -0
  44. package/dist/core/tracing/types.js +41 -0
  45. package/dist/core/vector-db-service.d.ts.map +1 -1
  46. package/dist/core/vector-db-service.js +238 -163
  47. package/dist/interfaces/mcp.d.ts.map +1 -1
  48. package/dist/interfaces/mcp.js +71 -43
  49. package/dist/mcp/server.js +12 -2
  50. package/dist/tools/organizational-data.d.ts.map +1 -1
  51. package/dist/tools/organizational-data.js +2 -4
  52. package/dist/tools/version.d.ts +12 -1
  53. package/dist/tools/version.d.ts.map +1 -1
  54. package/dist/tools/version.js +24 -4
  55. package/package.json +9 -1
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ /**
3
+ * Kubernetes Client Tracing Utilities
4
+ *
5
+ * Generic tracing wrappers for Kubernetes operations:
6
+ * 1. Transparent proxy for @kubernetes/client-node API clients
7
+ * 2. Wrapper for kubectl CLI command execution
8
+ *
9
+ * Uses CLIENT span kind with k8s.* semantic conventions
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.createTracedK8sClient = createTracedK8sClient;
13
+ exports.withKubectlTracing = withKubectlTracing;
14
+ const api_1 = require("@opentelemetry/api");
15
+ /**
16
+ * Create traced Kubernetes API client using JavaScript Proxy
17
+ *
18
+ * Transparently wraps ANY Kubernetes API client method with tracing.
19
+ * No code changes needed in calling code - just wrap the client once.
20
+ *
21
+ * @param apiClient Original K8s API client instance
22
+ * @param apiType API client type (e.g., 'CoreV1Api', 'AppsV1Api')
23
+ * @returns Proxied client with automatic tracing for all methods
24
+ *
25
+ * @example
26
+ * const coreApi = createTracedK8sClient(
27
+ * kc.makeApiClient(k8s.CoreV1Api),
28
+ * 'CoreV1Api'
29
+ * );
30
+ * await coreApi.listNamespace(); // Automatically traced as "k8s.listNamespace"
31
+ */
32
+ function createTracedK8sClient(apiClient, apiType) {
33
+ const tracer = api_1.trace.getTracer('dot-ai-mcp');
34
+ return new Proxy(apiClient, {
35
+ get(target, prop, receiver) {
36
+ const original = Reflect.get(target, prop, receiver);
37
+ // Only wrap functions (API methods), not properties
38
+ if (typeof original !== 'function') {
39
+ return original;
40
+ }
41
+ // Return wrapped function with tracing
42
+ return function (...args) {
43
+ const methodName = String(prop);
44
+ const spanName = `k8s.${methodName}`;
45
+ return tracer.startActiveSpan(spanName, {
46
+ kind: api_1.SpanKind.CLIENT,
47
+ attributes: {
48
+ 'k8s.client': 'kubernetes-client-node',
49
+ 'k8s.api': apiType,
50
+ 'k8s.method': methodName,
51
+ },
52
+ }, async (span) => {
53
+ try {
54
+ // Execute the original K8s API method
55
+ const result = await original.apply(target, args);
56
+ // Add response metadata if available
57
+ if (result?.response?.statusCode) {
58
+ span.setAttribute('http.response.status_code', result.response.statusCode);
59
+ }
60
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
61
+ return result;
62
+ }
63
+ catch (error) {
64
+ // Record K8s API error
65
+ span.recordException(error);
66
+ span.setStatus({
67
+ code: api_1.SpanStatusCode.ERROR,
68
+ message: error instanceof Error ? error.message : String(error),
69
+ });
70
+ // Add K8s-specific error attributes
71
+ if (error instanceof Error && 'statusCode' in error) {
72
+ span.setAttribute('k8s.error.status_code', error.statusCode);
73
+ }
74
+ throw error;
75
+ }
76
+ finally {
77
+ span.end();
78
+ }
79
+ });
80
+ };
81
+ },
82
+ });
83
+ }
84
+ /**
85
+ * Tracing wrapper for kubectl CLI command execution
86
+ *
87
+ * Wraps kubectl command execution with OpenTelemetry tracing spans.
88
+ * Captures command details, operation type, and execution results.
89
+ *
90
+ * @param args kubectl command arguments (e.g., ['get', 'pods', '-n', 'default'])
91
+ * @param config kubectl execution configuration
92
+ * @param handler Function that executes the actual kubectl command
93
+ * @returns kubectl command output
94
+ *
95
+ * @example
96
+ * const output = await withKubectlTracing(
97
+ * ['get', 'crd', '-o', 'json'],
98
+ * { kubeconfig: '/path/to/config' },
99
+ * async () => execAsync('kubectl get crd -o json')
100
+ * );
101
+ */
102
+ async function withKubectlTracing(args, config, handler) {
103
+ const tracer = api_1.trace.getTracer('dot-ai-mcp');
104
+ // Parse operation and resource from args
105
+ const operation = args[0] || 'unknown'; // 'get', 'apply', 'delete', etc.
106
+ const resource = args[1] || 'unknown'; // 'pods', 'crd', 'deployments', etc.
107
+ const spanName = `kubectl ${operation} ${resource}`;
108
+ return await tracer.startActiveSpan(spanName, {
109
+ kind: api_1.SpanKind.CLIENT,
110
+ attributes: {
111
+ 'k8s.client': 'kubectl',
112
+ 'k8s.command': 'kubectl',
113
+ 'k8s.operation': operation,
114
+ 'k8s.resource': resource,
115
+ 'k8s.args': args.join(' '),
116
+ ...(config?.namespace && { 'k8s.namespace': config.namespace }),
117
+ ...(config?.context && { 'k8s.context': config.context }),
118
+ ...(config?.kubeconfig && { 'k8s.kubeconfig': config.kubeconfig }),
119
+ },
120
+ }, async (span) => {
121
+ const startTime = Date.now();
122
+ try {
123
+ // Execute the kubectl command
124
+ const result = await api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), handler);
125
+ // Add execution metrics
126
+ span.setAttribute('k8s.duration_ms', Date.now() - startTime);
127
+ span.setAttribute('k8s.output_size_bytes', result.length);
128
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
129
+ return result;
130
+ }
131
+ catch (error) {
132
+ // Record kubectl error with details
133
+ span.recordException(error);
134
+ span.setStatus({
135
+ code: api_1.SpanStatusCode.ERROR,
136
+ message: error instanceof Error ? error.message : String(error),
137
+ });
138
+ // Parse kubectl error for additional context
139
+ const errorMessage = error instanceof Error ? error.message : String(error);
140
+ if (errorMessage.includes('not found')) {
141
+ span.setAttribute('k8s.error.type', 'NotFound');
142
+ }
143
+ else if (errorMessage.includes('forbidden')) {
144
+ span.setAttribute('k8s.error.type', 'Forbidden');
145
+ }
146
+ else if (errorMessage.includes('timeout')) {
147
+ span.setAttribute('k8s.error.type', 'Timeout');
148
+ }
149
+ throw error;
150
+ }
151
+ finally {
152
+ span.end();
153
+ }
154
+ });
155
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Qdrant Vector Database Tracing
3
+ *
4
+ * Provides distributed tracing instrumentation for Qdrant vector database operations.
5
+ * Creates CLIENT spans with database semantic conventions and vector-specific attributes.
6
+ */
7
+ /**
8
+ * Vector database operation types
9
+ */
10
+ export type VectorDBOperation = 'collection.create' | 'collection.get' | 'collection.list' | 'collection.delete' | 'collection.initialize' | 'vector.upsert' | 'vector.search' | 'vector.search_keywords' | 'vector.retrieve' | 'vector.delete' | 'vector.delete_all' | 'vector.list' | 'health_check';
11
+ /**
12
+ * Qdrant operation metadata for tracing
13
+ */
14
+ export interface QdrantOperationContext {
15
+ /** Operation type */
16
+ operation: VectorDBOperation;
17
+ /** Collection name */
18
+ collectionName: string;
19
+ /** Vector dimensions (for upsert, search operations) */
20
+ vectorSize?: number;
21
+ /** Search limit (for search operations) */
22
+ limit?: number;
23
+ /** Score threshold (for similarity search) */
24
+ scoreThreshold?: number;
25
+ /** Number of keywords (for keyword search) */
26
+ keywordCount?: number;
27
+ /** Document ID (for single document operations) */
28
+ documentId?: string;
29
+ /** Qdrant server URL */
30
+ serverUrl?: string;
31
+ }
32
+ /**
33
+ * Generic Qdrant operation tracing wrapper
34
+ *
35
+ * @param operationContext - Qdrant operation metadata
36
+ * @param handler - Async operation to trace
37
+ * @returns Result from handler
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Trace vector search
42
+ * const results = await withQdrantTracing(
43
+ * {
44
+ * operation: 'vector.search',
45
+ * collectionName: 'capabilities',
46
+ * vectorSize: 1536,
47
+ * limit: 10,
48
+ * scoreThreshold: 0.5,
49
+ * serverUrl: 'http://localhost:6333'
50
+ * },
51
+ * async () => await this.client.search(...)
52
+ * );
53
+ *
54
+ * // Trace document upsert
55
+ * await withQdrantTracing(
56
+ * {
57
+ * operation: 'vector.upsert',
58
+ * collectionName: 'patterns',
59
+ * documentId: 'pattern-123',
60
+ * vectorSize: 384,
61
+ * serverUrl: 'http://localhost:6333'
62
+ * },
63
+ * async () => await this.client.upsert(...)
64
+ * );
65
+ * ```
66
+ */
67
+ export declare function withQdrantTracing<T>(operationContext: QdrantOperationContext, handler: () => Promise<T>): Promise<T>;
68
+ //# sourceMappingURL=qdrant-tracing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qdrant-tracing.d.ts","sourceRoot":"","sources":["../../../src/core/tracing/qdrant-tracing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,mBAAmB,GACnB,gBAAgB,GAChB,iBAAiB,GACjB,mBAAmB,GACnB,uBAAuB,GACvB,eAAe,GACf,eAAe,GACf,wBAAwB,GACxB,iBAAiB,GACjB,eAAe,GACf,mBAAmB,GACnB,aAAa,GACb,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,qBAAqB;IACrB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,gBAAgB,EAAE,sBAAsB,EACxC,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,CAAC,CAAC,CAgEZ"}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ /**
3
+ * Qdrant Vector Database Tracing
4
+ *
5
+ * Provides distributed tracing instrumentation for Qdrant vector database operations.
6
+ * Creates CLIENT spans with database semantic conventions and vector-specific attributes.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.withQdrantTracing = withQdrantTracing;
10
+ const api_1 = require("@opentelemetry/api");
11
+ const tracer = api_1.trace.getTracer('dot-ai-mcp-qdrant');
12
+ /**
13
+ * Generic Qdrant operation tracing wrapper
14
+ *
15
+ * @param operationContext - Qdrant operation metadata
16
+ * @param handler - Async operation to trace
17
+ * @returns Result from handler
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Trace vector search
22
+ * const results = await withQdrantTracing(
23
+ * {
24
+ * operation: 'vector.search',
25
+ * collectionName: 'capabilities',
26
+ * vectorSize: 1536,
27
+ * limit: 10,
28
+ * scoreThreshold: 0.5,
29
+ * serverUrl: 'http://localhost:6333'
30
+ * },
31
+ * async () => await this.client.search(...)
32
+ * );
33
+ *
34
+ * // Trace document upsert
35
+ * await withQdrantTracing(
36
+ * {
37
+ * operation: 'vector.upsert',
38
+ * collectionName: 'patterns',
39
+ * documentId: 'pattern-123',
40
+ * vectorSize: 384,
41
+ * serverUrl: 'http://localhost:6333'
42
+ * },
43
+ * async () => await this.client.upsert(...)
44
+ * );
45
+ * ```
46
+ */
47
+ async function withQdrantTracing(operationContext, handler) {
48
+ const { operation, collectionName, ...metadata } = operationContext;
49
+ // Create span name: "qdrant.{operation} {collection}"
50
+ // Examples: "qdrant.vector.search capabilities", "qdrant.vector.upsert patterns"
51
+ const spanName = `qdrant.${operation} ${collectionName}`;
52
+ return tracer.startActiveSpan(spanName, {
53
+ kind: 2, // CLIENT span
54
+ attributes: {
55
+ // Database semantic conventions
56
+ 'db.system': 'qdrant',
57
+ 'db.operation.name': operation,
58
+ 'db.collection.name': collectionName,
59
+ // Vector-specific attributes
60
+ ...(metadata.vectorSize && { 'db.vector.dimensions': metadata.vectorSize }),
61
+ ...(metadata.limit && { 'db.query.limit': metadata.limit }),
62
+ ...(metadata.scoreThreshold && { 'db.vector.score_threshold': metadata.scoreThreshold }),
63
+ ...(metadata.keywordCount && { 'db.query.keyword_count': metadata.keywordCount }),
64
+ ...(metadata.documentId && { 'db.document.id': metadata.documentId }),
65
+ ...(metadata.serverUrl && { 'server.address': metadata.serverUrl })
66
+ }
67
+ }, async (span) => {
68
+ try {
69
+ // Execute operation
70
+ const result = await handler();
71
+ // Add result metadata for search operations
72
+ if (operation === 'vector.search' || operation === 'vector.search_keywords') {
73
+ if (Array.isArray(result)) {
74
+ span.setAttribute('db.query.result_count', result.length);
75
+ // For search results with scores, track top score
76
+ if (result.length > 0 && 'score' in result[0]) {
77
+ span.setAttribute('db.vector.top_score', result[0].score);
78
+ }
79
+ }
80
+ }
81
+ // Add result metadata for list operations
82
+ if (operation === 'vector.list' && Array.isArray(result)) {
83
+ span.setAttribute('db.query.result_count', result.length);
84
+ }
85
+ // Mark span as successful
86
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
87
+ return result;
88
+ }
89
+ catch (error) {
90
+ // Record error in span
91
+ span.setStatus({
92
+ code: api_1.SpanStatusCode.ERROR,
93
+ message: error instanceof Error ? error.message : String(error)
94
+ });
95
+ span.recordException(error instanceof Error ? error : new Error(String(error)));
96
+ throw error;
97
+ }
98
+ finally {
99
+ span.end();
100
+ }
101
+ });
102
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Tool Execution Tracing for MCP Tools
3
+ *
4
+ * Provides generic tracing wrapper for all MCP tool executions,
5
+ * creating INTERNAL spans with GenAI semantic conventions.
6
+ *
7
+ * Supports both STDIO (MCP) and HTTP (REST) transports transparently.
8
+ */
9
+ /**
10
+ * Wraps a tool handler with OpenTelemetry tracing
11
+ *
12
+ * Creates an INTERNAL span for tool execution with:
13
+ * - Tool name and input arguments
14
+ * - Execution duration and success status
15
+ * - Exception tracking for errors
16
+ * - GenAI semantic conventions (gen_ai.tool.*)
17
+ *
18
+ * @param toolName - Name of the MCP tool being executed
19
+ * @param args - Tool input arguments (will be serialized to JSON)
20
+ * @param handler - Async function that implements the tool logic
21
+ * @returns Promise resolving to the tool handler result
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const result = await withToolTracing('recommend', { intent: 'deploy postgres' }, async (args) => {
26
+ * return await handleRecommendTool(args);
27
+ * });
28
+ * ```
29
+ */
30
+ export declare function withToolTracing<T>(toolName: string, args: any, handler: (args: any) => Promise<T>): Promise<T>;
31
+ //# sourceMappingURL=tool-tracing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-tracing.d.ts","sourceRoot":"","sources":["../../../src/core/tracing/tool-tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GACjC,OAAO,CAAC,CAAC,CAAC,CAgDZ"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * Tool Execution Tracing for MCP Tools
4
+ *
5
+ * Provides generic tracing wrapper for all MCP tool executions,
6
+ * creating INTERNAL spans with GenAI semantic conventions.
7
+ *
8
+ * Supports both STDIO (MCP) and HTTP (REST) transports transparently.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.withToolTracing = withToolTracing;
12
+ const api_1 = require("@opentelemetry/api");
13
+ /**
14
+ * Wraps a tool handler with OpenTelemetry tracing
15
+ *
16
+ * Creates an INTERNAL span for tool execution with:
17
+ * - Tool name and input arguments
18
+ * - Execution duration and success status
19
+ * - Exception tracking for errors
20
+ * - GenAI semantic conventions (gen_ai.tool.*)
21
+ *
22
+ * @param toolName - Name of the MCP tool being executed
23
+ * @param args - Tool input arguments (will be serialized to JSON)
24
+ * @param handler - Async function that implements the tool logic
25
+ * @returns Promise resolving to the tool handler result
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const result = await withToolTracing('recommend', { intent: 'deploy postgres' }, async (args) => {
30
+ * return await handleRecommendTool(args);
31
+ * });
32
+ * ```
33
+ */
34
+ async function withToolTracing(toolName, args, handler) {
35
+ const tracer = api_1.trace.getTracer('dot-ai-mcp');
36
+ // Create INTERNAL span for tool execution
37
+ // Using INTERNAL kind since this is business logic within the server process
38
+ const span = tracer.startSpan(`execute_tool ${toolName}`, {
39
+ kind: api_1.SpanKind.INTERNAL,
40
+ attributes: {
41
+ // GenAI semantic conventions for tool execution
42
+ 'gen_ai.tool.name': toolName,
43
+ 'gen_ai.tool.input': JSON.stringify(args, null, 2),
44
+ },
45
+ });
46
+ // Execute handler within active span context
47
+ // This ensures any child spans (AI calls, K8s operations) become children of this span
48
+ return await api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), async () => {
49
+ try {
50
+ const startTime = Date.now();
51
+ const result = await handler(args);
52
+ const duration = Date.now() - startTime;
53
+ // Record success metrics
54
+ span.setAttributes({
55
+ 'gen_ai.tool.duration_ms': duration,
56
+ 'gen_ai.tool.success': true,
57
+ });
58
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
59
+ return result;
60
+ }
61
+ catch (error) {
62
+ // Record error details without disrupting original error flow
63
+ span.recordException(error);
64
+ span.setStatus({
65
+ code: api_1.SpanStatusCode.ERROR,
66
+ message: error.message,
67
+ });
68
+ // Re-throw to preserve original error handling behavior
69
+ throw error;
70
+ }
71
+ finally {
72
+ // Always end span regardless of success/failure
73
+ span.end();
74
+ }
75
+ });
76
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * OpenTelemetry Tracer Service
3
+ *
4
+ * Provides lazy initialization and management of distributed tracing.
5
+ * Follows OpenTelemetry best practices with support for multiple exporters.
6
+ */
7
+ import { SpanOptions } from '@opentelemetry/api';
8
+ import { TracedSpan, TracerService } from './types';
9
+ /**
10
+ * Get or create the global tracer instance
11
+ */
12
+ export declare function getTracer(): TracerService;
13
+ /**
14
+ * Shutdown the global tracer instance
15
+ */
16
+ export declare function shutdownTracer(): Promise<void>;
17
+ /**
18
+ * Helper function to wrap async operations with tracing
19
+ */
20
+ export declare function withSpan<T>(name: string, fn: (span: TracedSpan) => Promise<T>, options?: SpanOptions): Promise<T>;
21
+ //# sourceMappingURL=tracer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../../src/core/tracing/tracer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,EAKL,WAAW,EAEZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAiB,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAiMnE;;GAEG;AACH,wBAAgB,SAAS,IAAI,aAAa,CAMzC;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAKpD;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,EACpC,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,CAAC,CAAC,CAYZ"}
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ /**
3
+ * OpenTelemetry Tracer Service
4
+ *
5
+ * Provides lazy initialization and management of distributed tracing.
6
+ * Follows OpenTelemetry best practices with support for multiple exporters.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.getTracer = getTracer;
10
+ exports.shutdownTracer = shutdownTracer;
11
+ exports.withSpan = withSpan;
12
+ const sdk_node_1 = require("@opentelemetry/sdk-node");
13
+ const resources_1 = require("@opentelemetry/resources");
14
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
15
+ const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
16
+ const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
17
+ const api_1 = require("@opentelemetry/api");
18
+ const config_1 = require("./config");
19
+ /**
20
+ * Global tracer instance (singleton pattern with lazy initialization)
21
+ */
22
+ let tracerInstance = null;
23
+ /**
24
+ * OpenTelemetry Tracer implementation
25
+ */
26
+ class OpenTelemetryTracer {
27
+ sdk = null;
28
+ config;
29
+ initialized = false;
30
+ constructor(config) {
31
+ this.config = config;
32
+ }
33
+ /**
34
+ * Initialize the OpenTelemetry SDK (called lazily on first use)
35
+ */
36
+ initialize() {
37
+ if (this.initialized) {
38
+ return; // Already initialized
39
+ }
40
+ if (!this.config.enabled) {
41
+ if (this.config.debug) {
42
+ console.log('[Tracing] Tracing is disabled, skipping initialization');
43
+ }
44
+ return;
45
+ }
46
+ try {
47
+ // Validate configuration
48
+ (0, config_1.validateTracingConfig)(this.config);
49
+ // Create resource with service identification
50
+ const serviceResource = (0, resources_1.resourceFromAttributes)({
51
+ [semantic_conventions_1.ATTR_SERVICE_NAME]: this.config.serviceName,
52
+ [semantic_conventions_1.ATTR_SERVICE_VERSION]: this.config.serviceVersion,
53
+ });
54
+ const resource = (0, resources_1.defaultResource)().merge(serviceResource);
55
+ // Create exporter based on configuration
56
+ const traceExporter = this.createExporter();
57
+ // Initialize Node SDK without auto-instrumentation
58
+ // All operations are manually instrumented with descriptive spans
59
+ this.sdk = new sdk_node_1.NodeSDK({
60
+ resource,
61
+ traceExporter,
62
+ instrumentations: [], // No auto-instrumentation needed
63
+ });
64
+ // Start the SDK
65
+ this.sdk.start();
66
+ this.initialized = true;
67
+ if (this.config.debug) {
68
+ console.log('[Tracing] OpenTelemetry initialized successfully', {
69
+ serviceName: this.config.serviceName,
70
+ serviceVersion: this.config.serviceVersion,
71
+ exporterType: this.config.exporterType,
72
+ });
73
+ }
74
+ }
75
+ catch (error) {
76
+ console.error('[Tracing] Failed to initialize OpenTelemetry:', error);
77
+ throw error;
78
+ }
79
+ }
80
+ /**
81
+ * Create exporter based on configuration
82
+ */
83
+ createExporter() {
84
+ switch (this.config.exporterType) {
85
+ case 'console':
86
+ if (this.config.debug) {
87
+ console.log('[Tracing] Using console exporter (outputs to stderr)');
88
+ }
89
+ return new sdk_trace_node_1.ConsoleSpanExporter();
90
+ case 'otlp':
91
+ if (this.config.debug) {
92
+ console.log('[Tracing] Using OTLP exporter', {
93
+ endpoint: this.config.otlpEndpoint || 'http://localhost:4318/v1/traces'
94
+ });
95
+ }
96
+ return new exporter_trace_otlp_http_1.OTLPTraceExporter({
97
+ url: this.config.otlpEndpoint || 'http://localhost:4318/v1/traces',
98
+ });
99
+ case 'jaeger':
100
+ // Jaeger exporter will be added in Phase 3
101
+ throw new Error('Jaeger exporter not yet implemented - coming in Phase 3');
102
+ case 'zipkin':
103
+ // Zipkin exporter will be added in Phase 3
104
+ throw new Error('Zipkin exporter not yet implemented - coming in Phase 3');
105
+ default:
106
+ throw new Error(`Unknown exporter type: ${this.config.exporterType}`);
107
+ }
108
+ }
109
+ /**
110
+ * Check if tracing is enabled
111
+ */
112
+ isEnabled() {
113
+ return this.config.enabled;
114
+ }
115
+ /**
116
+ * Create a new span with utility methods
117
+ */
118
+ startSpan(name, options, parentContext) {
119
+ if (!this.config.enabled) {
120
+ // Return a no-op span if tracing is disabled
121
+ return this.createNoOpSpan();
122
+ }
123
+ // Lazy initialization on first span creation
124
+ if (!this.initialized) {
125
+ this.initialize();
126
+ }
127
+ const tracer = api_1.trace.getTracer(this.config.serviceName, this.config.serviceVersion);
128
+ const ctx = parentContext || api_1.context.active();
129
+ const span = tracer.startSpan(name, options, ctx);
130
+ return this.wrapSpan(span);
131
+ }
132
+ /**
133
+ * Wrap an OpenTelemetry span with utility methods
134
+ */
135
+ wrapSpan(span) {
136
+ return {
137
+ span,
138
+ end() {
139
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
140
+ span.end();
141
+ },
142
+ endWithError(error) {
143
+ span.recordException(error);
144
+ span.setStatus({
145
+ code: api_1.SpanStatusCode.ERROR,
146
+ message: error.message,
147
+ });
148
+ span.end();
149
+ },
150
+ setAttributes(attributes) {
151
+ span.setAttributes(attributes);
152
+ },
153
+ addEvent(name, attributes) {
154
+ span.addEvent(name, attributes);
155
+ },
156
+ };
157
+ }
158
+ /**
159
+ * Create a no-op span for when tracing is disabled
160
+ */
161
+ createNoOpSpan() {
162
+ const noopSpan = api_1.trace.getTracer('noop').startSpan('noop');
163
+ return this.wrapSpan(noopSpan);
164
+ }
165
+ /**
166
+ * Shutdown the tracer gracefully
167
+ */
168
+ async shutdown() {
169
+ if (this.sdk && this.initialized) {
170
+ if (this.config.debug) {
171
+ console.log('[Tracing] Shutting down OpenTelemetry SDK...');
172
+ }
173
+ await this.sdk.shutdown();
174
+ this.initialized = false;
175
+ if (this.config.debug) {
176
+ console.log('[Tracing] OpenTelemetry SDK shut down successfully');
177
+ }
178
+ }
179
+ }
180
+ }
181
+ /**
182
+ * Get or create the global tracer instance
183
+ */
184
+ function getTracer() {
185
+ if (!tracerInstance) {
186
+ const config = (0, config_1.loadTracingConfig)();
187
+ tracerInstance = new OpenTelemetryTracer(config);
188
+ }
189
+ return tracerInstance;
190
+ }
191
+ /**
192
+ * Shutdown the global tracer instance
193
+ */
194
+ async function shutdownTracer() {
195
+ if (tracerInstance) {
196
+ await tracerInstance.shutdown();
197
+ tracerInstance = null;
198
+ }
199
+ }
200
+ /**
201
+ * Helper function to wrap async operations with tracing
202
+ */
203
+ async function withSpan(name, fn, options) {
204
+ const tracer = getTracer();
205
+ const span = tracer.startSpan(name, options);
206
+ try {
207
+ const result = await fn(span);
208
+ span.end();
209
+ return result;
210
+ }
211
+ catch (error) {
212
+ span.endWithError(error);
213
+ throw error;
214
+ }
215
+ }