@vfarcic/dot-ai 0.125.0 → 0.127.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.
- package/dist/core/capability-scan-workflow.d.ts +4 -9
- package/dist/core/capability-scan-workflow.d.ts.map +1 -1
- package/dist/core/capability-scan-workflow.js +203 -455
- package/dist/core/discovery.d.ts.map +1 -1
- package/dist/core/discovery.js +4 -3
- package/dist/core/embedding-service.d.ts +9 -36
- package/dist/core/embedding-service.d.ts.map +1 -1
- package/dist/core/embedding-service.js +137 -253
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/kubernetes-utils.d.ts +1 -0
- package/dist/core/kubernetes-utils.d.ts.map +1 -1
- package/dist/core/kubernetes-utils.js +53 -48
- package/dist/core/providers/anthropic-provider.d.ts.map +1 -1
- package/dist/core/providers/anthropic-provider.js +352 -282
- package/dist/core/providers/vercel-provider.d.ts.map +1 -1
- package/dist/core/providers/vercel-provider.js +389 -351
- package/dist/core/tracing/ai-tracing.d.ts +80 -0
- package/dist/core/tracing/ai-tracing.d.ts.map +1 -0
- package/dist/core/tracing/ai-tracing.js +122 -0
- package/dist/core/tracing/config.d.ts +15 -0
- package/dist/core/tracing/config.d.ts.map +1 -0
- package/dist/core/tracing/config.js +133 -0
- package/dist/core/tracing/http-tracing.d.ts +28 -0
- package/dist/core/tracing/http-tracing.d.ts.map +1 -0
- package/dist/core/tracing/http-tracing.js +119 -0
- package/dist/core/tracing/index.d.ts +14 -0
- package/dist/core/tracing/index.d.ts.map +1 -0
- package/dist/core/tracing/index.js +40 -0
- package/dist/core/tracing/k8s-tracing.d.ts +57 -0
- package/dist/core/tracing/k8s-tracing.d.ts.map +1 -0
- package/dist/core/tracing/k8s-tracing.js +155 -0
- package/dist/core/tracing/qdrant-tracing.d.ts +68 -0
- package/dist/core/tracing/qdrant-tracing.d.ts.map +1 -0
- package/dist/core/tracing/qdrant-tracing.js +102 -0
- package/dist/core/tracing/tool-tracing.d.ts +31 -0
- package/dist/core/tracing/tool-tracing.d.ts.map +1 -0
- package/dist/core/tracing/tool-tracing.js +76 -0
- package/dist/core/tracing/tracer.d.ts +21 -0
- package/dist/core/tracing/tracer.d.ts.map +1 -0
- package/dist/core/tracing/tracer.js +215 -0
- package/dist/core/tracing/types.d.ts +86 -0
- package/dist/core/tracing/types.d.ts.map +1 -0
- package/dist/core/tracing/types.js +41 -0
- package/dist/core/vector-db-service.d.ts.map +1 -1
- package/dist/core/vector-db-service.js +238 -163
- package/dist/interfaces/mcp.d.ts.map +1 -1
- package/dist/interfaces/mcp.js +71 -43
- package/dist/mcp/server.js +12 -2
- package/dist/tools/organizational-data.d.ts.map +1 -1
- package/dist/tools/organizational-data.js +2 -4
- package/dist/tools/version.d.ts +12 -1
- package/dist/tools/version.d.ts.map +1 -1
- package/dist/tools/version.js +24 -4
- package/package.json +9 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Provider Tracing Utilities
|
|
3
|
+
*
|
|
4
|
+
* Generic wrapper for instrumenting AI provider calls with OpenTelemetry.
|
|
5
|
+
* Uses official GenAI semantic conventions for AI/LLM operations.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - chat operations (sendMessage)
|
|
9
|
+
* - tool_loop operations (toolLoop with agentic tool calling)
|
|
10
|
+
* - embeddings operations (generateEmbedding, generateEmbeddings)
|
|
11
|
+
*
|
|
12
|
+
* Reference: https://opentelemetry.io/docs/specs/semconv/gen-ai/
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Configuration for AI operation tracing
|
|
16
|
+
*/
|
|
17
|
+
export interface AITracingOptions {
|
|
18
|
+
/** AI provider name (e.g., 'anthropic', 'openai', 'google') */
|
|
19
|
+
provider: string;
|
|
20
|
+
/** Model identifier (e.g., 'claude-3-5-sonnet', 'gpt-4o', 'text-embedding-3-small') */
|
|
21
|
+
model: string;
|
|
22
|
+
/** Operation type: 'chat', 'tool_loop', 'embeddings' */
|
|
23
|
+
operation: 'chat' | 'tool_loop' | 'embeddings';
|
|
24
|
+
/** Optional max tokens parameter (only for chat/tool_loop operations) */
|
|
25
|
+
maxTokens?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Metrics extracted from AI operation result
|
|
29
|
+
* Fields vary by operation type:
|
|
30
|
+
* - chat/tool_loop: inputTokens, outputTokens, cache tokens
|
|
31
|
+
* - embeddings: embeddingCount, embeddingDimensions
|
|
32
|
+
*/
|
|
33
|
+
export interface AITracingResult {
|
|
34
|
+
/** Input tokens consumed (chat/tool_loop only) */
|
|
35
|
+
inputTokens?: number;
|
|
36
|
+
/** Output tokens generated (chat/tool_loop only) */
|
|
37
|
+
outputTokens?: number;
|
|
38
|
+
/** Cache read tokens (if provider supports caching) */
|
|
39
|
+
cacheReadTokens?: number;
|
|
40
|
+
/** Cache creation tokens (if provider supports caching) */
|
|
41
|
+
cacheCreationTokens?: number;
|
|
42
|
+
/** Number of embeddings generated (embeddings only) */
|
|
43
|
+
embeddingCount?: number;
|
|
44
|
+
/** Dimension size of embeddings (embeddings only) */
|
|
45
|
+
embeddingDimensions?: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Generic wrapper for AI provider calls
|
|
49
|
+
*
|
|
50
|
+
* Creates CLIENT spans with official gen_ai.* semantic conventions.
|
|
51
|
+
* The auto-instrumented HTTP span becomes a child of this span.
|
|
52
|
+
*
|
|
53
|
+
* @param options AI operation configuration
|
|
54
|
+
* @param handler Function that performs the actual AI call
|
|
55
|
+
* @param extractMetrics Function to extract metrics from the result
|
|
56
|
+
* @returns Result from the handler function
|
|
57
|
+
*
|
|
58
|
+
* @example Chat operation
|
|
59
|
+
* const response = await withAITracing(
|
|
60
|
+
* { provider: 'anthropic', model: 'claude-3-5-sonnet', operation: 'chat' },
|
|
61
|
+
* async () => await client.messages.create(...),
|
|
62
|
+
* (result) => ({ inputTokens: result.usage.input_tokens, outputTokens: result.usage.output_tokens })
|
|
63
|
+
* );
|
|
64
|
+
*
|
|
65
|
+
* @example Tool loop operation
|
|
66
|
+
* const result = await withAITracing(
|
|
67
|
+
* { provider: 'anthropic', model: 'claude-3-5-sonnet', operation: 'tool_loop' },
|
|
68
|
+
* async () => await provider.toolLoop(...),
|
|
69
|
+
* (result) => ({ inputTokens: result.totalTokens.input, outputTokens: result.totalTokens.output })
|
|
70
|
+
* );
|
|
71
|
+
*
|
|
72
|
+
* @example Embeddings operation
|
|
73
|
+
* const embedding = await withAITracing(
|
|
74
|
+
* { provider: 'openai', model: 'text-embedding-3-small', operation: 'embeddings' },
|
|
75
|
+
* async () => await client.embeddings.create(...),
|
|
76
|
+
* (result) => ({ embeddingCount: 1, embeddingDimensions: 1536 })
|
|
77
|
+
* );
|
|
78
|
+
*/
|
|
79
|
+
export declare function withAITracing<T>(options: AITracingOptions, handler: () => Promise<T>, extractMetrics: (result: T) => AITracingResult): Promise<T>;
|
|
80
|
+
//# sourceMappingURL=ai-tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-tracing.d.ts","sourceRoot":"","sources":["../../../src/core/tracing/ai-tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IAEjB,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IAEd,wDAAwD;IACxD,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,YAAY,CAAC;IAE/C,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,2DAA2D;IAC3D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,qDAAqD;IACrD,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,cAAc,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,eAAe,GAC7C,OAAO,CAAC,CAAC,CAAC,CAwFZ"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AI Provider Tracing Utilities
|
|
4
|
+
*
|
|
5
|
+
* Generic wrapper for instrumenting AI provider calls with OpenTelemetry.
|
|
6
|
+
* Uses official GenAI semantic conventions for AI/LLM operations.
|
|
7
|
+
*
|
|
8
|
+
* Supports:
|
|
9
|
+
* - chat operations (sendMessage)
|
|
10
|
+
* - tool_loop operations (toolLoop with agentic tool calling)
|
|
11
|
+
* - embeddings operations (generateEmbedding, generateEmbeddings)
|
|
12
|
+
*
|
|
13
|
+
* Reference: https://opentelemetry.io/docs/specs/semconv/gen-ai/
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.withAITracing = withAITracing;
|
|
17
|
+
const api_1 = require("@opentelemetry/api");
|
|
18
|
+
/**
|
|
19
|
+
* Generic wrapper for AI provider calls
|
|
20
|
+
*
|
|
21
|
+
* Creates CLIENT spans with official gen_ai.* semantic conventions.
|
|
22
|
+
* The auto-instrumented HTTP span becomes a child of this span.
|
|
23
|
+
*
|
|
24
|
+
* @param options AI operation configuration
|
|
25
|
+
* @param handler Function that performs the actual AI call
|
|
26
|
+
* @param extractMetrics Function to extract metrics from the result
|
|
27
|
+
* @returns Result from the handler function
|
|
28
|
+
*
|
|
29
|
+
* @example Chat operation
|
|
30
|
+
* const response = await withAITracing(
|
|
31
|
+
* { provider: 'anthropic', model: 'claude-3-5-sonnet', operation: 'chat' },
|
|
32
|
+
* async () => await client.messages.create(...),
|
|
33
|
+
* (result) => ({ inputTokens: result.usage.input_tokens, outputTokens: result.usage.output_tokens })
|
|
34
|
+
* );
|
|
35
|
+
*
|
|
36
|
+
* @example Tool loop operation
|
|
37
|
+
* const result = await withAITracing(
|
|
38
|
+
* { provider: 'anthropic', model: 'claude-3-5-sonnet', operation: 'tool_loop' },
|
|
39
|
+
* async () => await provider.toolLoop(...),
|
|
40
|
+
* (result) => ({ inputTokens: result.totalTokens.input, outputTokens: result.totalTokens.output })
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* @example Embeddings operation
|
|
44
|
+
* const embedding = await withAITracing(
|
|
45
|
+
* { provider: 'openai', model: 'text-embedding-3-small', operation: 'embeddings' },
|
|
46
|
+
* async () => await client.embeddings.create(...),
|
|
47
|
+
* (result) => ({ embeddingCount: 1, embeddingDimensions: 1536 })
|
|
48
|
+
* );
|
|
49
|
+
*/
|
|
50
|
+
async function withAITracing(options, handler, extractMetrics) {
|
|
51
|
+
// Get tracer (returns no-op if tracing disabled)
|
|
52
|
+
const tracer = api_1.trace.getTracer('dot-ai-mcp');
|
|
53
|
+
// Span name format: "{operation} {model}"
|
|
54
|
+
// Examples: "chat claude-3-5-sonnet", "tool_loop claude-3-5-sonnet", "embeddings text-embedding-3-small"
|
|
55
|
+
const spanName = `${options.operation} ${options.model}`;
|
|
56
|
+
return await tracer.startActiveSpan(spanName, {
|
|
57
|
+
kind: api_1.SpanKind.CLIENT,
|
|
58
|
+
attributes: {
|
|
59
|
+
// Required GenAI attributes (per OpenTelemetry spec)
|
|
60
|
+
'gen_ai.operation.name': options.operation,
|
|
61
|
+
'gen_ai.provider.name': options.provider,
|
|
62
|
+
'gen_ai.request.model': options.model,
|
|
63
|
+
// Optional request parameters (only for chat/tool_loop)
|
|
64
|
+
...(options.maxTokens !== undefined && {
|
|
65
|
+
'gen_ai.request.max_tokens': options.maxTokens,
|
|
66
|
+
}),
|
|
67
|
+
},
|
|
68
|
+
}, async (span) => {
|
|
69
|
+
const startTime = Date.now();
|
|
70
|
+
try {
|
|
71
|
+
// Execute the actual AI call within this span's context
|
|
72
|
+
// Auto-instrumented HTTP spans will be children of this span
|
|
73
|
+
const result = await api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), handler);
|
|
74
|
+
// Extract metrics from the result
|
|
75
|
+
const metrics = extractMetrics(result);
|
|
76
|
+
// Add response model (usually same as request)
|
|
77
|
+
span.setAttribute('gen_ai.response.model', options.model);
|
|
78
|
+
span.setAttribute('gen_ai.ai.duration_ms', Date.now() - startTime);
|
|
79
|
+
// Add operation-specific metrics
|
|
80
|
+
if (options.operation === 'chat' || options.operation === 'tool_loop') {
|
|
81
|
+
// Token-based metrics for chat/tool_loop operations
|
|
82
|
+
if (metrics.inputTokens !== undefined) {
|
|
83
|
+
span.setAttribute('gen_ai.usage.input_tokens', metrics.inputTokens);
|
|
84
|
+
}
|
|
85
|
+
if (metrics.outputTokens !== undefined) {
|
|
86
|
+
span.setAttribute('gen_ai.usage.output_tokens', metrics.outputTokens);
|
|
87
|
+
}
|
|
88
|
+
// Cache metrics (Anthropic-specific for chat operations)
|
|
89
|
+
if (metrics.cacheReadTokens !== undefined && metrics.cacheReadTokens > 0) {
|
|
90
|
+
span.setAttribute('gen_ai.usage.cache_read_tokens', metrics.cacheReadTokens);
|
|
91
|
+
}
|
|
92
|
+
if (metrics.cacheCreationTokens !== undefined && metrics.cacheCreationTokens > 0) {
|
|
93
|
+
span.setAttribute('gen_ai.usage.cache_creation_tokens', metrics.cacheCreationTokens);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if (options.operation === 'embeddings') {
|
|
97
|
+
// Embedding-specific metrics
|
|
98
|
+
if (metrics.embeddingCount !== undefined) {
|
|
99
|
+
span.setAttribute('gen_ai.embeddings.count', metrics.embeddingCount);
|
|
100
|
+
}
|
|
101
|
+
if (metrics.embeddingDimensions !== undefined) {
|
|
102
|
+
span.setAttribute('gen_ai.embeddings.dimensions', metrics.embeddingDimensions);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
// Record exception with full details
|
|
110
|
+
span.recordException(error);
|
|
111
|
+
span.setStatus({
|
|
112
|
+
code: api_1.SpanStatusCode.ERROR,
|
|
113
|
+
message: error instanceof Error ? error.message : String(error),
|
|
114
|
+
});
|
|
115
|
+
span.setAttribute('error.type', error instanceof Error ? error.constructor.name : 'unknown');
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
span.end();
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Tracing Configuration
|
|
3
|
+
*
|
|
4
|
+
* Manages tracing configuration from environment variables with sensible defaults.
|
|
5
|
+
*/
|
|
6
|
+
import { TracingConfig } from './types';
|
|
7
|
+
/**
|
|
8
|
+
* Load tracing configuration from environment variables
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadTracingConfig(): TracingConfig;
|
|
11
|
+
/**
|
|
12
|
+
* Validate tracing configuration
|
|
13
|
+
*/
|
|
14
|
+
export declare function validateTracingConfig(config: TracingConfig): void;
|
|
15
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/core/tracing/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA8FxC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,CAwBjD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAejE"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenTelemetry Tracing Configuration
|
|
4
|
+
*
|
|
5
|
+
* Manages tracing configuration from environment variables with sensible defaults.
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.loadTracingConfig = loadTracingConfig;
|
|
12
|
+
exports.validateTracingConfig = validateTracingConfig;
|
|
13
|
+
const fs_1 = require("fs");
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
15
|
+
/**
|
|
16
|
+
* Load service version from package.json
|
|
17
|
+
*/
|
|
18
|
+
function getServiceVersion() {
|
|
19
|
+
try {
|
|
20
|
+
const packageJsonPath = path_1.default.join(process.cwd(), 'package.json');
|
|
21
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, 'utf8'));
|
|
22
|
+
return packageJson.version || '0.0.0';
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.error('Failed to load service version from package.json:', error);
|
|
26
|
+
return '0.0.0';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Determine exporter type from environment variables
|
|
31
|
+
*/
|
|
32
|
+
function getExporterType() {
|
|
33
|
+
const exporterEnv = process.env.OTEL_EXPORTER_TYPE?.toLowerCase();
|
|
34
|
+
// Check for OTLP endpoint - if set, use OTLP exporter
|
|
35
|
+
if (process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {
|
|
36
|
+
return 'otlp';
|
|
37
|
+
}
|
|
38
|
+
// Explicit exporter type
|
|
39
|
+
switch (exporterEnv) {
|
|
40
|
+
case 'otlp':
|
|
41
|
+
return 'otlp';
|
|
42
|
+
case 'jaeger':
|
|
43
|
+
return 'jaeger';
|
|
44
|
+
case 'zipkin':
|
|
45
|
+
return 'zipkin';
|
|
46
|
+
case 'console':
|
|
47
|
+
return 'console';
|
|
48
|
+
default:
|
|
49
|
+
// Default to console for local development (zero-config)
|
|
50
|
+
return 'console';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get sampling probability from environment
|
|
55
|
+
*/
|
|
56
|
+
function getSamplingProbability() {
|
|
57
|
+
const samplingEnv = process.env.OTEL_SAMPLING_PROBABILITY;
|
|
58
|
+
if (!samplingEnv) {
|
|
59
|
+
return 1.0; // Always-on sampling by default
|
|
60
|
+
}
|
|
61
|
+
const probability = parseFloat(samplingEnv);
|
|
62
|
+
if (isNaN(probability) || probability < 0 || probability > 1) {
|
|
63
|
+
console.warn(`Invalid OTEL_SAMPLING_PROBABILITY: ${samplingEnv}, using 1.0`);
|
|
64
|
+
return 1.0;
|
|
65
|
+
}
|
|
66
|
+
return probability;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if tracing is enabled
|
|
70
|
+
*
|
|
71
|
+
* Default: disabled to avoid console noise.
|
|
72
|
+
* Users can enable with OTEL_TRACING_ENABLED=true when they want observability.
|
|
73
|
+
*/
|
|
74
|
+
function isTracingEnabled() {
|
|
75
|
+
const enabledEnv = process.env.OTEL_TRACING_ENABLED?.toLowerCase();
|
|
76
|
+
// Explicit enable
|
|
77
|
+
if (enabledEnv === 'true' || enabledEnv === '1' || enabledEnv === 'yes') {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
// Explicit disable
|
|
81
|
+
if (enabledEnv === 'false' || enabledEnv === '0' || enabledEnv === 'no') {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
// Default: disabled to keep logs clean
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if debug mode is enabled
|
|
89
|
+
*/
|
|
90
|
+
function isDebugMode() {
|
|
91
|
+
const debugEnv = process.env.OTEL_DEBUG?.toLowerCase();
|
|
92
|
+
return debugEnv === 'true' || debugEnv === '1' || debugEnv === 'yes';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Load tracing configuration from environment variables
|
|
96
|
+
*/
|
|
97
|
+
function loadTracingConfig() {
|
|
98
|
+
const config = {
|
|
99
|
+
serviceName: process.env.OTEL_SERVICE_NAME || 'dot-ai-mcp',
|
|
100
|
+
serviceVersion: getServiceVersion(),
|
|
101
|
+
exporterType: getExporterType(),
|
|
102
|
+
otlpEndpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
103
|
+
enabled: isTracingEnabled(),
|
|
104
|
+
samplingProbability: getSamplingProbability(),
|
|
105
|
+
debug: isDebugMode()
|
|
106
|
+
};
|
|
107
|
+
// Log configuration in debug mode
|
|
108
|
+
if (config.debug) {
|
|
109
|
+
console.log('[Tracing] Configuration loaded:', {
|
|
110
|
+
serviceName: config.serviceName,
|
|
111
|
+
serviceVersion: config.serviceVersion,
|
|
112
|
+
exporterType: config.exporterType,
|
|
113
|
+
otlpEndpoint: config.otlpEndpoint,
|
|
114
|
+
enabled: config.enabled,
|
|
115
|
+
samplingProbability: config.samplingProbability
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return config;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Validate tracing configuration
|
|
122
|
+
*/
|
|
123
|
+
function validateTracingConfig(config) {
|
|
124
|
+
// Validate OTLP endpoint if OTLP exporter is selected
|
|
125
|
+
if (config.exporterType === 'otlp' && !config.otlpEndpoint) {
|
|
126
|
+
throw new Error('OTLP exporter requires OTEL_EXPORTER_OTLP_ENDPOINT environment variable');
|
|
127
|
+
}
|
|
128
|
+
// Warn about production configurations
|
|
129
|
+
if (config.exporterType === 'console' && process.env.NODE_ENV === 'production') {
|
|
130
|
+
console.warn('[Tracing] Warning: Using console exporter in production. ' +
|
|
131
|
+
'Consider using OTLP, Jaeger, or Zipkin exporter for production deployments.');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Server Tracing Module
|
|
3
|
+
*
|
|
4
|
+
* Provides manual SERVER span creation for incoming HTTP requests.
|
|
5
|
+
* Follows OpenTelemetry HTTP semantic conventions.
|
|
6
|
+
*/
|
|
7
|
+
import { Span } from '@opentelemetry/api';
|
|
8
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
9
|
+
/**
|
|
10
|
+
* Create and manage HTTP SERVER span for incoming request
|
|
11
|
+
*
|
|
12
|
+
* Returns a function to end the span with response status code
|
|
13
|
+
*/
|
|
14
|
+
export declare function createHttpServerSpan(req: IncomingMessage): {
|
|
15
|
+
span: Span;
|
|
16
|
+
endSpan: (statusCode: number) => void;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Wrap HTTP request handler with tracing
|
|
20
|
+
*
|
|
21
|
+
* This is a higher-order function that wraps an existing HTTP request handler
|
|
22
|
+
* with automatic SERVER span creation and management.
|
|
23
|
+
*
|
|
24
|
+
* @param handler - Original HTTP request handler
|
|
25
|
+
* @returns Wrapped handler with tracing
|
|
26
|
+
*/
|
|
27
|
+
export declare function withHttpServerTracing(handler: (req: IncomingMessage, res: ServerResponse) => Promise<void>): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
28
|
+
//# sourceMappingURL=http-tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-tracing.d.ts","sourceRoot":"","sources":["../../../src/core/tracing/http-tracing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAML,IAAI,EACL,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAiE5D;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,eAAe,GACnB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAyCvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GACpE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAwB9D"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTTP Server Tracing Module
|
|
4
|
+
*
|
|
5
|
+
* Provides manual SERVER span creation for incoming HTTP requests.
|
|
6
|
+
* Follows OpenTelemetry HTTP semantic conventions.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createHttpServerSpan = createHttpServerSpan;
|
|
10
|
+
exports.withHttpServerTracing = withHttpServerTracing;
|
|
11
|
+
const api_1 = require("@opentelemetry/api");
|
|
12
|
+
/**
|
|
13
|
+
* Extract trace context from HTTP headers
|
|
14
|
+
* Follows W3C Trace Context specification
|
|
15
|
+
*/
|
|
16
|
+
function extractTraceContext(req) {
|
|
17
|
+
return api_1.propagation.extract(api_1.context.active(), req.headers);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Build span attributes from HTTP request
|
|
21
|
+
*/
|
|
22
|
+
function buildSpanAttributes(req) {
|
|
23
|
+
const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
|
|
24
|
+
const attributes = {
|
|
25
|
+
'http.request.method': req.method || 'UNKNOWN',
|
|
26
|
+
'url.path': url.pathname,
|
|
27
|
+
'url.scheme': url.protocol.replace(':', ''),
|
|
28
|
+
'http.route': url.pathname, // Can be enhanced with route templates
|
|
29
|
+
};
|
|
30
|
+
// Add optional attributes
|
|
31
|
+
if (req.headers.host) {
|
|
32
|
+
const [hostname, port] = req.headers.host.split(':');
|
|
33
|
+
attributes['server.address'] = hostname;
|
|
34
|
+
if (port) {
|
|
35
|
+
attributes['server.port'] = parseInt(port, 10);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Client address (from headers or socket)
|
|
39
|
+
const clientAddress = req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
|
|
40
|
+
req.socket.remoteAddress;
|
|
41
|
+
if (clientAddress) {
|
|
42
|
+
attributes['client.address'] = clientAddress;
|
|
43
|
+
}
|
|
44
|
+
// User agent
|
|
45
|
+
if (req.headers['user-agent']) {
|
|
46
|
+
attributes['user_agent.original'] = req.headers['user-agent'];
|
|
47
|
+
}
|
|
48
|
+
return attributes;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create and manage HTTP SERVER span for incoming request
|
|
52
|
+
*
|
|
53
|
+
* Returns a function to end the span with response status code
|
|
54
|
+
*/
|
|
55
|
+
function createHttpServerSpan(req) {
|
|
56
|
+
// Extract parent trace context from headers
|
|
57
|
+
const parentContext = extractTraceContext(req);
|
|
58
|
+
// Build span name: "{METHOD} {route}"
|
|
59
|
+
const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
|
|
60
|
+
const spanName = `${req.method} ${url.pathname}`;
|
|
61
|
+
// Get tracer instance (returns no-op if tracing disabled)
|
|
62
|
+
const tracer = api_1.trace.getTracer('dot-ai-mcp');
|
|
63
|
+
// Create SERVER span with parent context
|
|
64
|
+
const span = tracer.startSpan(spanName, {
|
|
65
|
+
kind: api_1.SpanKind.SERVER,
|
|
66
|
+
attributes: buildSpanAttributes(req),
|
|
67
|
+
}, parentContext);
|
|
68
|
+
// Return span and cleanup function
|
|
69
|
+
return {
|
|
70
|
+
span,
|
|
71
|
+
endSpan: (statusCode) => {
|
|
72
|
+
// Set response status code
|
|
73
|
+
span.setAttribute('http.response.status_code', statusCode);
|
|
74
|
+
// Set span status based on HTTP status code
|
|
75
|
+
if (statusCode >= 500) {
|
|
76
|
+
span.setStatus({
|
|
77
|
+
code: api_1.SpanStatusCode.ERROR,
|
|
78
|
+
message: `HTTP ${statusCode}`,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
span.setStatus({ code: api_1.SpanStatusCode.OK });
|
|
83
|
+
}
|
|
84
|
+
span.end();
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Wrap HTTP request handler with tracing
|
|
90
|
+
*
|
|
91
|
+
* This is a higher-order function that wraps an existing HTTP request handler
|
|
92
|
+
* with automatic SERVER span creation and management.
|
|
93
|
+
*
|
|
94
|
+
* @param handler - Original HTTP request handler
|
|
95
|
+
* @returns Wrapped handler with tracing
|
|
96
|
+
*/
|
|
97
|
+
function withHttpServerTracing(handler) {
|
|
98
|
+
return async (req, res) => {
|
|
99
|
+
const { span, endSpan } = createHttpServerSpan(req);
|
|
100
|
+
try {
|
|
101
|
+
// Set span as active context
|
|
102
|
+
await api_1.context.with(api_1.trace.setSpan(api_1.context.active(), span), async () => {
|
|
103
|
+
await handler(req, res);
|
|
104
|
+
});
|
|
105
|
+
// End span with actual response status code
|
|
106
|
+
endSpan(res.statusCode);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
// Record exception and end span with error
|
|
110
|
+
span.recordException(error);
|
|
111
|
+
span.setStatus({
|
|
112
|
+
code: api_1.SpanStatusCode.ERROR,
|
|
113
|
+
message: error.message,
|
|
114
|
+
});
|
|
115
|
+
span.end();
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry Tracing Module
|
|
3
|
+
*
|
|
4
|
+
* Public API for distributed tracing functionality.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types';
|
|
7
|
+
export * from './config';
|
|
8
|
+
export { getTracer, shutdownTracer, withSpan } from './tracer';
|
|
9
|
+
export { createHttpServerSpan, withHttpServerTracing } from './http-tracing';
|
|
10
|
+
export { withToolTracing } from './tool-tracing';
|
|
11
|
+
export { withAITracing } from './ai-tracing';
|
|
12
|
+
export { createTracedK8sClient, withKubectlTracing } from './k8s-tracing';
|
|
13
|
+
export { withQdrantTracing } from './qdrant-tracing';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/tracing/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenTelemetry Tracing Module
|
|
4
|
+
*
|
|
5
|
+
* Public API for distributed tracing functionality.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.withQdrantTracing = exports.withKubectlTracing = exports.createTracedK8sClient = exports.withAITracing = exports.withToolTracing = exports.withHttpServerTracing = exports.createHttpServerSpan = exports.withSpan = exports.shutdownTracer = exports.getTracer = void 0;
|
|
23
|
+
__exportStar(require("./types"), exports);
|
|
24
|
+
__exportStar(require("./config"), exports);
|
|
25
|
+
var tracer_1 = require("./tracer");
|
|
26
|
+
Object.defineProperty(exports, "getTracer", { enumerable: true, get: function () { return tracer_1.getTracer; } });
|
|
27
|
+
Object.defineProperty(exports, "shutdownTracer", { enumerable: true, get: function () { return tracer_1.shutdownTracer; } });
|
|
28
|
+
Object.defineProperty(exports, "withSpan", { enumerable: true, get: function () { return tracer_1.withSpan; } });
|
|
29
|
+
var http_tracing_1 = require("./http-tracing");
|
|
30
|
+
Object.defineProperty(exports, "createHttpServerSpan", { enumerable: true, get: function () { return http_tracing_1.createHttpServerSpan; } });
|
|
31
|
+
Object.defineProperty(exports, "withHttpServerTracing", { enumerable: true, get: function () { return http_tracing_1.withHttpServerTracing; } });
|
|
32
|
+
var tool_tracing_1 = require("./tool-tracing");
|
|
33
|
+
Object.defineProperty(exports, "withToolTracing", { enumerable: true, get: function () { return tool_tracing_1.withToolTracing; } });
|
|
34
|
+
var ai_tracing_1 = require("./ai-tracing");
|
|
35
|
+
Object.defineProperty(exports, "withAITracing", { enumerable: true, get: function () { return ai_tracing_1.withAITracing; } });
|
|
36
|
+
var k8s_tracing_1 = require("./k8s-tracing");
|
|
37
|
+
Object.defineProperty(exports, "createTracedK8sClient", { enumerable: true, get: function () { return k8s_tracing_1.createTracedK8sClient; } });
|
|
38
|
+
Object.defineProperty(exports, "withKubectlTracing", { enumerable: true, get: function () { return k8s_tracing_1.withKubectlTracing; } });
|
|
39
|
+
var qdrant_tracing_1 = require("./qdrant-tracing");
|
|
40
|
+
Object.defineProperty(exports, "withQdrantTracing", { enumerable: true, get: function () { return qdrant_tracing_1.withQdrantTracing; } });
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kubernetes Client Tracing Utilities
|
|
3
|
+
*
|
|
4
|
+
* Generic tracing wrappers for Kubernetes operations:
|
|
5
|
+
* 1. Transparent proxy for @kubernetes/client-node API clients
|
|
6
|
+
* 2. Wrapper for kubectl CLI command execution
|
|
7
|
+
*
|
|
8
|
+
* Uses CLIENT span kind with k8s.* semantic conventions
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for kubectl command tracing
|
|
12
|
+
*/
|
|
13
|
+
export interface KubectlConfig {
|
|
14
|
+
context?: string;
|
|
15
|
+
namespace?: string;
|
|
16
|
+
kubeconfig?: string;
|
|
17
|
+
timeout?: number;
|
|
18
|
+
stdin?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create traced Kubernetes API client using JavaScript Proxy
|
|
22
|
+
*
|
|
23
|
+
* Transparently wraps ANY Kubernetes API client method with tracing.
|
|
24
|
+
* No code changes needed in calling code - just wrap the client once.
|
|
25
|
+
*
|
|
26
|
+
* @param apiClient Original K8s API client instance
|
|
27
|
+
* @param apiType API client type (e.g., 'CoreV1Api', 'AppsV1Api')
|
|
28
|
+
* @returns Proxied client with automatic tracing for all methods
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const coreApi = createTracedK8sClient(
|
|
32
|
+
* kc.makeApiClient(k8s.CoreV1Api),
|
|
33
|
+
* 'CoreV1Api'
|
|
34
|
+
* );
|
|
35
|
+
* await coreApi.listNamespace(); // Automatically traced as "k8s.listNamespace"
|
|
36
|
+
*/
|
|
37
|
+
export declare function createTracedK8sClient<T extends object>(apiClient: T, apiType: string): T;
|
|
38
|
+
/**
|
|
39
|
+
* Tracing wrapper for kubectl CLI command execution
|
|
40
|
+
*
|
|
41
|
+
* Wraps kubectl command execution with OpenTelemetry tracing spans.
|
|
42
|
+
* Captures command details, operation type, and execution results.
|
|
43
|
+
*
|
|
44
|
+
* @param args kubectl command arguments (e.g., ['get', 'pods', '-n', 'default'])
|
|
45
|
+
* @param config kubectl execution configuration
|
|
46
|
+
* @param handler Function that executes the actual kubectl command
|
|
47
|
+
* @returns kubectl command output
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* const output = await withKubectlTracing(
|
|
51
|
+
* ['get', 'crd', '-o', 'json'],
|
|
52
|
+
* { kubeconfig: '/path/to/config' },
|
|
53
|
+
* async () => execAsync('kubectl get crd -o json')
|
|
54
|
+
* );
|
|
55
|
+
*/
|
|
56
|
+
export declare function withKubectlTracing(args: string[], config: KubectlConfig | undefined, handler: () => Promise<string>): Promise<string>;
|
|
57
|
+
//# sourceMappingURL=k8s-tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"k8s-tracing.d.ts","sourceRoot":"","sources":["../../../src/core/tracing/k8s-tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,EACpD,SAAS,EAAE,CAAC,EACZ,OAAO,EAAE,MAAM,GACd,CAAC,CAoEH;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,aAAa,GAAG,SAAS,EACjC,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,MAAM,CAAC,CAgEjB"}
|