ai.matey.middleware 0.2.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/LICENSE +21 -0
- package/dist/cjs/caching.js +226 -0
- package/dist/cjs/caching.js.map +1 -0
- package/dist/cjs/conversation-history.js +213 -0
- package/dist/cjs/conversation-history.js.map +1 -0
- package/dist/cjs/cost-tracking.js +355 -0
- package/dist/cjs/cost-tracking.js.map +1 -0
- package/dist/cjs/index.js +37 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/logging.js +174 -0
- package/dist/cjs/logging.js.map +1 -0
- package/dist/cjs/opentelemetry.js +499 -0
- package/dist/cjs/opentelemetry.js.map +1 -0
- package/dist/cjs/retry.js +205 -0
- package/dist/cjs/retry.js.map +1 -0
- package/dist/cjs/security.js +175 -0
- package/dist/cjs/security.js.map +1 -0
- package/dist/cjs/telemetry.js +216 -0
- package/dist/cjs/telemetry.js.map +1 -0
- package/dist/cjs/transform.js +284 -0
- package/dist/cjs/transform.js.map +1 -0
- package/dist/cjs/validation.js +506 -0
- package/dist/cjs/validation.js.map +1 -0
- package/dist/esm/caching.js +221 -0
- package/dist/esm/caching.js.map +1 -0
- package/dist/esm/conversation-history.js +207 -0
- package/dist/esm/conversation-history.js.map +1 -0
- package/dist/esm/cost-tracking.js +347 -0
- package/dist/esm/cost-tracking.js.map +1 -0
- package/dist/esm/index.js +21 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/logging.js +171 -0
- package/dist/esm/logging.js.map +1 -0
- package/dist/esm/opentelemetry.js +458 -0
- package/dist/esm/opentelemetry.js.map +1 -0
- package/dist/esm/retry.js +198 -0
- package/dist/esm/retry.js.map +1 -0
- package/dist/esm/security.js +169 -0
- package/dist/esm/security.js.map +1 -0
- package/dist/esm/telemetry.js +210 -0
- package/dist/esm/telemetry.js.map +1 -0
- package/dist/esm/transform.js +272 -0
- package/dist/esm/transform.js.map +1 -0
- package/dist/esm/validation.js +494 -0
- package/dist/esm/validation.js.map +1 -0
- package/dist/types/caching.d.ts +98 -0
- package/dist/types/caching.d.ts.map +1 -0
- package/dist/types/conversation-history.d.ts +188 -0
- package/dist/types/conversation-history.d.ts.map +1 -0
- package/dist/types/cost-tracking.d.ts +262 -0
- package/dist/types/cost-tracking.d.ts.map +1 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/logging.d.ts +82 -0
- package/dist/types/logging.d.ts.map +1 -0
- package/dist/types/opentelemetry.d.ts +219 -0
- package/dist/types/opentelemetry.d.ts.map +1 -0
- package/dist/types/retry.d.ts +86 -0
- package/dist/types/retry.d.ts.map +1 -0
- package/dist/types/security.d.ts +120 -0
- package/dist/types/security.d.ts.map +1 -0
- package/dist/types/telemetry.d.ts +120 -0
- package/dist/types/telemetry.d.ts.map +1 -0
- package/dist/types/transform.d.ts +184 -0
- package/dist/types/transform.d.ts.map +1 -0
- package/dist/types/validation.d.ts +356 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/package.json +203 -0
- package/readme.md +103 -0
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenTelemetry Middleware
|
|
4
|
+
*
|
|
5
|
+
* Provides distributed tracing and metrics export using OpenTelemetry.
|
|
6
|
+
* OpenTelemetry packages are optional peer dependencies - this middleware
|
|
7
|
+
* will check for their availability at runtime.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.OpenTelemetryTelemetrySink = exports.OpenTelemetryAttributes = void 0;
|
|
46
|
+
exports.createOpenTelemetryMiddleware = createOpenTelemetryMiddleware;
|
|
47
|
+
exports.isOpenTelemetryAvailable = isOpenTelemetryAvailable;
|
|
48
|
+
exports.isOpenTelemetryLoaded = isOpenTelemetryLoaded;
|
|
49
|
+
exports.shutdownOpenTelemetry = shutdownOpenTelemetry;
|
|
50
|
+
// ============================================================================
|
|
51
|
+
// Runtime Availability Check
|
|
52
|
+
// ============================================================================
|
|
53
|
+
let otelAvailable = false;
|
|
54
|
+
let api = null;
|
|
55
|
+
let TracerProvider = null;
|
|
56
|
+
let OTLPTraceExporter = null;
|
|
57
|
+
let Resource = null;
|
|
58
|
+
let SEMRESATTRS_SERVICE_NAME = null;
|
|
59
|
+
let SEMRESATTRS_SERVICE_VERSION = null;
|
|
60
|
+
let BatchSpanProcessor = null;
|
|
61
|
+
/**
|
|
62
|
+
* Check if OpenTelemetry packages are available and load them.
|
|
63
|
+
*/
|
|
64
|
+
async function checkOpenTelemetryAvailability() {
|
|
65
|
+
if (otelAvailable) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
// Use dynamic import() for ESM/CJS compatibility
|
|
70
|
+
const [apiModule, sdkTraceBase, otlpExporter, resources, semanticConventions] = await Promise.all([
|
|
71
|
+
Promise.resolve().then(() => __importStar(require('@opentelemetry/api'))),
|
|
72
|
+
Promise.resolve().then(() => __importStar(require('@opentelemetry/sdk-trace-base'))),
|
|
73
|
+
Promise.resolve().then(() => __importStar(require('@opentelemetry/exporter-trace-otlp-http'))),
|
|
74
|
+
Promise.resolve().then(() => __importStar(require('@opentelemetry/resources'))),
|
|
75
|
+
Promise.resolve().then(() => __importStar(require('@opentelemetry/semantic-conventions'))),
|
|
76
|
+
]);
|
|
77
|
+
api = apiModule;
|
|
78
|
+
TracerProvider = sdkTraceBase.BasicTracerProvider;
|
|
79
|
+
BatchSpanProcessor = sdkTraceBase.BatchSpanProcessor;
|
|
80
|
+
OTLPTraceExporter = otlpExporter.OTLPTraceExporter;
|
|
81
|
+
Resource = resources.Resource;
|
|
82
|
+
SEMRESATTRS_SERVICE_NAME = semanticConventions.SEMRESATTRS_SERVICE_NAME;
|
|
83
|
+
SEMRESATTRS_SERVICE_VERSION = semanticConventions.SEMRESATTRS_SERVICE_VERSION;
|
|
84
|
+
otelAvailable = true;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Synchronous check if OpenTelemetry is already loaded.
|
|
93
|
+
* Use checkOpenTelemetryAvailability() for the full check.
|
|
94
|
+
*/
|
|
95
|
+
function isOtelLoaded() {
|
|
96
|
+
return otelAvailable;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* OpenTelemetry span attribute names.
|
|
100
|
+
*/
|
|
101
|
+
exports.OpenTelemetryAttributes = {
|
|
102
|
+
// Request attributes
|
|
103
|
+
REQUEST_ID: 'ai.request.id',
|
|
104
|
+
REQUEST_MODEL: 'ai.request.model',
|
|
105
|
+
REQUEST_STREAM: 'ai.request.stream',
|
|
106
|
+
REQUEST_MESSAGE_COUNT: 'ai.request.message_count',
|
|
107
|
+
REQUEST_MAX_TOKENS: 'ai.request.max_tokens',
|
|
108
|
+
// Response attributes
|
|
109
|
+
RESPONSE_BACKEND: 'ai.response.backend',
|
|
110
|
+
RESPONSE_FINISH_REASON: 'ai.response.finish_reason',
|
|
111
|
+
RESPONSE_MODEL: 'ai.response.model',
|
|
112
|
+
// Token usage attributes
|
|
113
|
+
TOKENS_PROMPT: 'ai.tokens.prompt',
|
|
114
|
+
TOKENS_COMPLETION: 'ai.tokens.completion',
|
|
115
|
+
TOKENS_TOTAL: 'ai.tokens.total',
|
|
116
|
+
// Provenance attributes
|
|
117
|
+
FRONTEND: 'ai.frontend',
|
|
118
|
+
BACKEND: 'ai.backend',
|
|
119
|
+
// Performance attributes
|
|
120
|
+
DURATION_MS: 'ai.duration.ms',
|
|
121
|
+
};
|
|
122
|
+
// ============================================================================
|
|
123
|
+
// Tracer Provider Singleton
|
|
124
|
+
// ============================================================================
|
|
125
|
+
let globalTracerProvider = null;
|
|
126
|
+
let globalTracerProviderConfig = null;
|
|
127
|
+
let providerInitializationPromise = null;
|
|
128
|
+
/**
|
|
129
|
+
* Get or create the global tracer provider.
|
|
130
|
+
*
|
|
131
|
+
* WARNING: This uses a singleton pattern. If you call this multiple times
|
|
132
|
+
* with different configs, only the first config will be used. To reset,
|
|
133
|
+
* call shutdownOpenTelemetry() first.
|
|
134
|
+
*
|
|
135
|
+
* This function is NOT thread-safe for concurrent calls, but uses a promise
|
|
136
|
+
* to prevent race conditions during initialization.
|
|
137
|
+
*/
|
|
138
|
+
async function getOrCreateTracerProvider(config) {
|
|
139
|
+
// Create a config hash to detect configuration changes
|
|
140
|
+
const configHash = JSON.stringify({
|
|
141
|
+
serviceName: config.serviceName,
|
|
142
|
+
serviceVersion: config.serviceVersion,
|
|
143
|
+
endpoint: config.endpoint,
|
|
144
|
+
exportSpans: config.exportSpans,
|
|
145
|
+
});
|
|
146
|
+
if (globalTracerProvider) {
|
|
147
|
+
// Warn if trying to create with different config
|
|
148
|
+
if (globalTracerProviderConfig && globalTracerProviderConfig !== configHash) {
|
|
149
|
+
console.warn('[OpenTelemetry] Tracer provider already initialized with different config. ' +
|
|
150
|
+
'Call shutdownOpenTelemetry() to reset before creating with new config.');
|
|
151
|
+
}
|
|
152
|
+
return globalTracerProvider;
|
|
153
|
+
}
|
|
154
|
+
// If initialization is in progress, wait for it
|
|
155
|
+
if (providerInitializationPromise) {
|
|
156
|
+
return providerInitializationPromise;
|
|
157
|
+
}
|
|
158
|
+
// Start initialization
|
|
159
|
+
providerInitializationPromise = (() => {
|
|
160
|
+
try {
|
|
161
|
+
const { serviceName = 'ai-matey', serviceVersion = '0.1.0', endpoint = 'http://localhost:4318/v1/traces', headers = {}, resourceAttributes = {}, exportSpans = true, batchSpanProcessorConfig = {}, exporterTimeoutMillis = 10000, } = config;
|
|
162
|
+
// Create resource with service information
|
|
163
|
+
const resource = new Resource({
|
|
164
|
+
[SEMRESATTRS_SERVICE_NAME]: serviceName,
|
|
165
|
+
[SEMRESATTRS_SERVICE_VERSION]: serviceVersion,
|
|
166
|
+
...resourceAttributes,
|
|
167
|
+
});
|
|
168
|
+
// Create tracer provider
|
|
169
|
+
const provider = new TracerProvider({
|
|
170
|
+
resource,
|
|
171
|
+
});
|
|
172
|
+
// Add span processor with OTLP exporter if spans should be exported
|
|
173
|
+
if (exportSpans) {
|
|
174
|
+
const exporter = new OTLPTraceExporter({
|
|
175
|
+
url: endpoint,
|
|
176
|
+
headers,
|
|
177
|
+
timeoutMillis: exporterTimeoutMillis,
|
|
178
|
+
});
|
|
179
|
+
const processorConfig = {
|
|
180
|
+
maxQueueSize: batchSpanProcessorConfig.maxQueueSize,
|
|
181
|
+
maxExportBatchSize: batchSpanProcessorConfig.maxExportBatchSize,
|
|
182
|
+
scheduledDelayMillis: batchSpanProcessorConfig.scheduledDelayMillis,
|
|
183
|
+
exportTimeoutMillis: batchSpanProcessorConfig.exportTimeoutMillis,
|
|
184
|
+
};
|
|
185
|
+
provider.addSpanProcessor(new BatchSpanProcessor(exporter, processorConfig));
|
|
186
|
+
}
|
|
187
|
+
// Register the provider
|
|
188
|
+
api.trace.setGlobalTracerProvider(provider);
|
|
189
|
+
globalTracerProvider = provider;
|
|
190
|
+
globalTracerProviderConfig = configHash;
|
|
191
|
+
return Promise.resolve(provider);
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
// Clear the initialization promise whether success or failure
|
|
195
|
+
providerInitializationPromise = null;
|
|
196
|
+
}
|
|
197
|
+
})();
|
|
198
|
+
return providerInitializationPromise;
|
|
199
|
+
}
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// Sampling
|
|
202
|
+
// ============================================================================
|
|
203
|
+
/**
|
|
204
|
+
* Determine if this request should be sampled.
|
|
205
|
+
*/
|
|
206
|
+
function shouldSample(samplingRate) {
|
|
207
|
+
return Math.random() < samplingRate;
|
|
208
|
+
}
|
|
209
|
+
// ============================================================================
|
|
210
|
+
// Middleware Factory
|
|
211
|
+
// ============================================================================
|
|
212
|
+
/**
|
|
213
|
+
* Create OpenTelemetry middleware.
|
|
214
|
+
*
|
|
215
|
+
* Provides distributed tracing with span creation, context propagation,
|
|
216
|
+
* and metrics export via OpenTelemetry.
|
|
217
|
+
*
|
|
218
|
+
* **Note:** This middleware requires optional OpenTelemetry packages to be installed:
|
|
219
|
+
* - `@opentelemetry/api`
|
|
220
|
+
* - `@opentelemetry/sdk-trace-base`
|
|
221
|
+
* - `@opentelemetry/exporter-trace-otlp-http`
|
|
222
|
+
* - `@opentelemetry/resources`
|
|
223
|
+
* - `@opentelemetry/semantic-conventions`
|
|
224
|
+
*
|
|
225
|
+
* Install with:
|
|
226
|
+
* ```bash
|
|
227
|
+
* npm install @opentelemetry/api @opentelemetry/sdk-trace-base \
|
|
228
|
+
* @opentelemetry/exporter-trace-otlp-http @opentelemetry/resources \
|
|
229
|
+
* @opentelemetry/semantic-conventions
|
|
230
|
+
* ```
|
|
231
|
+
*
|
|
232
|
+
* @param config OpenTelemetry configuration
|
|
233
|
+
* @returns Promise that resolves to OpenTelemetry middleware
|
|
234
|
+
* @throws Error if OpenTelemetry packages are not installed
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* import { createOpenTelemetryMiddleware } from 'ai.matey.middleware';
|
|
239
|
+
*
|
|
240
|
+
* const otel = await createOpenTelemetryMiddleware({
|
|
241
|
+
* serviceName: 'my-ai-service',
|
|
242
|
+
* endpoint: 'http://localhost:4318/v1/traces',
|
|
243
|
+
* samplingRate: 1.0
|
|
244
|
+
* });
|
|
245
|
+
*
|
|
246
|
+
* bridge.use(otel);
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
async function createOpenTelemetryMiddleware(config = {}) {
|
|
250
|
+
// Check if OpenTelemetry is available
|
|
251
|
+
const available = await checkOpenTelemetryAvailability();
|
|
252
|
+
if (!available) {
|
|
253
|
+
throw new Error('OpenTelemetry packages are not installed. Please install:\n' +
|
|
254
|
+
'npm install @opentelemetry/api @opentelemetry/sdk-trace-base ' +
|
|
255
|
+
'@opentelemetry/exporter-trace-otlp-http @opentelemetry/resources ' +
|
|
256
|
+
'@opentelemetry/semantic-conventions');
|
|
257
|
+
}
|
|
258
|
+
const { samplingRate = 1.0, tracerName = 'ai-matey-tracer' } = config;
|
|
259
|
+
// Initialize tracer provider (async to handle race conditions)
|
|
260
|
+
const provider = await getOrCreateTracerProvider(config);
|
|
261
|
+
const tracer = provider.getTracer(tracerName);
|
|
262
|
+
return async (context, next) => {
|
|
263
|
+
// Check if we should sample this request
|
|
264
|
+
const sampled = shouldSample(samplingRate);
|
|
265
|
+
if (!sampled) {
|
|
266
|
+
// Skip tracing for this request
|
|
267
|
+
return next();
|
|
268
|
+
}
|
|
269
|
+
const requestId = context.request.metadata.requestId;
|
|
270
|
+
// Create span for the request
|
|
271
|
+
const span = tracer.startSpan('ai.matey.request', {
|
|
272
|
+
attributes: {
|
|
273
|
+
[exports.OpenTelemetryAttributes.REQUEST_ID]: requestId,
|
|
274
|
+
[exports.OpenTelemetryAttributes.REQUEST_MODEL]: context.request.parameters?.model ?? 'unknown',
|
|
275
|
+
[exports.OpenTelemetryAttributes.REQUEST_STREAM]: String(context.request.stream ?? false),
|
|
276
|
+
[exports.OpenTelemetryAttributes.REQUEST_MESSAGE_COUNT]: context.request.messages.length,
|
|
277
|
+
[exports.OpenTelemetryAttributes.FRONTEND]: context.request.metadata.provenance?.frontend ?? 'unknown',
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
// Add max_tokens if present
|
|
281
|
+
if (context.request.parameters?.maxTokens) {
|
|
282
|
+
span.setAttribute(exports.OpenTelemetryAttributes.REQUEST_MAX_TOKENS, context.request.parameters.maxTokens);
|
|
283
|
+
}
|
|
284
|
+
const startTime = Date.now();
|
|
285
|
+
try {
|
|
286
|
+
// Execute within span context
|
|
287
|
+
const spanContext = api.trace.setSpan(api.context.active(), span);
|
|
288
|
+
// Call next middleware/handler in the span context
|
|
289
|
+
const response = await api.context.with(spanContext, async () => {
|
|
290
|
+
return await next();
|
|
291
|
+
});
|
|
292
|
+
const duration = Date.now() - startTime;
|
|
293
|
+
// Add response attributes to span
|
|
294
|
+
span.setAttribute(exports.OpenTelemetryAttributes.RESPONSE_BACKEND, response.metadata.provenance?.backend ?? 'unknown');
|
|
295
|
+
span.setAttribute(exports.OpenTelemetryAttributes.RESPONSE_FINISH_REASON, response.finishReason);
|
|
296
|
+
span.setAttribute(exports.OpenTelemetryAttributes.DURATION_MS, duration);
|
|
297
|
+
if (response.metadata.provenance?.backendModel) {
|
|
298
|
+
span.setAttribute(exports.OpenTelemetryAttributes.RESPONSE_MODEL, response.metadata.provenance.backendModel);
|
|
299
|
+
}
|
|
300
|
+
// Add token usage if present
|
|
301
|
+
if (response.usage) {
|
|
302
|
+
if (response.usage.promptTokens) {
|
|
303
|
+
span.setAttribute(exports.OpenTelemetryAttributes.TOKENS_PROMPT, response.usage.promptTokens);
|
|
304
|
+
}
|
|
305
|
+
if (response.usage.completionTokens) {
|
|
306
|
+
span.setAttribute(exports.OpenTelemetryAttributes.TOKENS_COMPLETION, response.usage.completionTokens);
|
|
307
|
+
}
|
|
308
|
+
if (response.usage.totalTokens) {
|
|
309
|
+
span.setAttribute(exports.OpenTelemetryAttributes.TOKENS_TOTAL, response.usage.totalTokens);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// Mark span as successful
|
|
313
|
+
span.setStatus({ code: api.SpanStatusCode.OK });
|
|
314
|
+
span.end();
|
|
315
|
+
return response;
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
const duration = Date.now() - startTime;
|
|
319
|
+
// Safely add error information to span
|
|
320
|
+
// Wrap in try-catch to prevent span operations from masking the original error
|
|
321
|
+
try {
|
|
322
|
+
span.setAttribute(exports.OpenTelemetryAttributes.DURATION_MS, duration);
|
|
323
|
+
span.setAttribute('error', true);
|
|
324
|
+
span.setAttribute('error.type', error instanceof Error ? error.name : 'unknown');
|
|
325
|
+
if (error instanceof Error) {
|
|
326
|
+
span.recordException(error);
|
|
327
|
+
span.setStatus({
|
|
328
|
+
code: api.SpanStatusCode.ERROR,
|
|
329
|
+
message: error.message,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
span.setStatus({
|
|
334
|
+
code: api.SpanStatusCode.ERROR,
|
|
335
|
+
message: String(error),
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
span.end();
|
|
339
|
+
}
|
|
340
|
+
catch (spanError) {
|
|
341
|
+
// If span operations fail, log but don't mask the original error
|
|
342
|
+
console.error('[OpenTelemetry] Failed to record error in span:', spanError);
|
|
343
|
+
// Try to end the span anyway to prevent memory leak
|
|
344
|
+
try {
|
|
345
|
+
span.end();
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
// Ignore - best effort to clean up
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// Always re-throw the original error
|
|
352
|
+
throw error;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
// ============================================================================
|
|
357
|
+
// OpenTelemetry Telemetry Sink
|
|
358
|
+
// ============================================================================
|
|
359
|
+
/**
|
|
360
|
+
* OpenTelemetry-based telemetry sink.
|
|
361
|
+
*
|
|
362
|
+
* Implements the TelemetrySink interface using OpenTelemetry metrics.
|
|
363
|
+
* This allows you to use the existing telemetry middleware with OpenTelemetry.
|
|
364
|
+
*
|
|
365
|
+
* **Note:** Currently uses spans for metrics as the OpenTelemetry metrics API
|
|
366
|
+
* is still evolving. Consider using createOpenTelemetryMiddleware for full
|
|
367
|
+
* tracing support.
|
|
368
|
+
*/
|
|
369
|
+
class OpenTelemetryTelemetrySink {
|
|
370
|
+
tracer;
|
|
371
|
+
constructor(tracer) {
|
|
372
|
+
this.tracer = tracer;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Create a new OpenTelemetryTelemetrySink instance.
|
|
376
|
+
*
|
|
377
|
+
* @param config OpenTelemetry configuration
|
|
378
|
+
* @returns Promise that resolves to a new sink instance
|
|
379
|
+
* @throws Error if OpenTelemetry packages are not installed
|
|
380
|
+
*/
|
|
381
|
+
static async create(config = {}) {
|
|
382
|
+
// Check if OpenTelemetry is available
|
|
383
|
+
const available = await checkOpenTelemetryAvailability();
|
|
384
|
+
if (!available) {
|
|
385
|
+
throw new Error('OpenTelemetry packages are not installed. Please install:\n' +
|
|
386
|
+
'npm install @opentelemetry/api @opentelemetry/sdk-trace-base ' +
|
|
387
|
+
'@opentelemetry/exporter-trace-otlp-http @opentelemetry/resources ' +
|
|
388
|
+
'@opentelemetry/semantic-conventions');
|
|
389
|
+
}
|
|
390
|
+
const { tracerName = 'ai-matey-telemetry-sink' } = config;
|
|
391
|
+
// Initialize tracer provider (async to handle race conditions)
|
|
392
|
+
const provider = await getOrCreateTracerProvider(config);
|
|
393
|
+
const tracer = provider.getTracer(tracerName);
|
|
394
|
+
return new OpenTelemetryTelemetrySink(tracer);
|
|
395
|
+
}
|
|
396
|
+
recordMetric(name, value, tags) {
|
|
397
|
+
// Create a span for the metric (simplified approach)
|
|
398
|
+
const span = this.tracer.startSpan(`metric.${name}`, {
|
|
399
|
+
attributes: {
|
|
400
|
+
'metric.name': name,
|
|
401
|
+
'metric.value': value,
|
|
402
|
+
...tags,
|
|
403
|
+
},
|
|
404
|
+
});
|
|
405
|
+
span.end();
|
|
406
|
+
}
|
|
407
|
+
recordEvent(name, data) {
|
|
408
|
+
// Create a span for the event
|
|
409
|
+
// Flatten and sanitize data to only include primitive types
|
|
410
|
+
const attributes = {
|
|
411
|
+
'event.name': name,
|
|
412
|
+
};
|
|
413
|
+
if (data) {
|
|
414
|
+
for (const [key, value] of Object.entries(data)) {
|
|
415
|
+
// Only include primitive types that OpenTelemetry supports
|
|
416
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
417
|
+
attributes[key] = value;
|
|
418
|
+
}
|
|
419
|
+
else if (value === null || value === undefined) {
|
|
420
|
+
attributes[key] = String(value);
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// For complex objects, stringify them
|
|
424
|
+
attributes[key] = JSON.stringify(value);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
const span = this.tracer.startSpan(`event.${name}`, {
|
|
429
|
+
attributes,
|
|
430
|
+
});
|
|
431
|
+
span.end();
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
exports.OpenTelemetryTelemetrySink = OpenTelemetryTelemetrySink;
|
|
435
|
+
// ============================================================================
|
|
436
|
+
// Utility Functions
|
|
437
|
+
// ============================================================================
|
|
438
|
+
/**
|
|
439
|
+
* Check if OpenTelemetry packages are installed and available.
|
|
440
|
+
*
|
|
441
|
+
* @returns Promise that resolves to true if OpenTelemetry is available
|
|
442
|
+
*
|
|
443
|
+
* @example
|
|
444
|
+
* ```typescript
|
|
445
|
+
* import { isOpenTelemetryAvailable } from 'ai.matey.middleware';
|
|
446
|
+
*
|
|
447
|
+
* if (await isOpenTelemetryAvailable()) {
|
|
448
|
+
* console.log('OpenTelemetry is available!');
|
|
449
|
+
* } else {
|
|
450
|
+
* console.log('OpenTelemetry packages not installed.');
|
|
451
|
+
* }
|
|
452
|
+
* ```
|
|
453
|
+
*/
|
|
454
|
+
async function isOpenTelemetryAvailable() {
|
|
455
|
+
return checkOpenTelemetryAvailability();
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Synchronously check if OpenTelemetry is already loaded.
|
|
459
|
+
* Use isOpenTelemetryAvailable() for async check with dynamic import.
|
|
460
|
+
*
|
|
461
|
+
* @returns True if OpenTelemetry is already loaded
|
|
462
|
+
*
|
|
463
|
+
* @example
|
|
464
|
+
* ```typescript
|
|
465
|
+
* import { isOpenTelemetryLoaded } from 'ai.matey.middleware';
|
|
466
|
+
*
|
|
467
|
+
* if (isOpenTelemetryLoaded()) {
|
|
468
|
+
* console.log('OpenTelemetry is already loaded!');
|
|
469
|
+
* }
|
|
470
|
+
* ```
|
|
471
|
+
*/
|
|
472
|
+
function isOpenTelemetryLoaded() {
|
|
473
|
+
return isOtelLoaded();
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Force shutdown of the global tracer provider.
|
|
477
|
+
* Useful for graceful shutdown in server applications.
|
|
478
|
+
*
|
|
479
|
+
* @returns Promise that resolves when shutdown is complete
|
|
480
|
+
*
|
|
481
|
+
* @example
|
|
482
|
+
* ```typescript
|
|
483
|
+
* import { shutdownOpenTelemetry } from 'ai.matey.middleware';
|
|
484
|
+
*
|
|
485
|
+
* process.on('SIGTERM', async () => {
|
|
486
|
+
* await shutdownOpenTelemetry();
|
|
487
|
+
* process.exit(0);
|
|
488
|
+
* });
|
|
489
|
+
* ```
|
|
490
|
+
*/
|
|
491
|
+
async function shutdownOpenTelemetry() {
|
|
492
|
+
if (globalTracerProvider) {
|
|
493
|
+
await globalTracerProvider.shutdown();
|
|
494
|
+
globalTracerProvider = null;
|
|
495
|
+
globalTracerProviderConfig = null;
|
|
496
|
+
providerInitializationPromise = null;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
//# sourceMappingURL=opentelemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opentelemetry.js","sourceRoot":"","sources":["../../src/opentelemetry.ts"],"names":[],"mappings":"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"}
|