@mastra/observability 1.12.0-alpha.2 → 1.12.0-alpha.4
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/CHANGELOG.md +59 -0
- package/README.md +3 -3
- package/dist/bus/base.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/exporters/cloud.d.ts +12 -0
- package/dist/exporters/cloud.d.ts.map +1 -1
- package/dist/exporters/default.d.ts +12 -1
- package/dist/exporters/default.d.ts.map +1 -1
- package/dist/exporters/index.d.ts +2 -0
- package/dist/exporters/index.d.ts.map +1 -1
- package/dist/exporters/mastra-platform.d.ts +58 -0
- package/dist/exporters/mastra-platform.d.ts.map +1 -0
- package/dist/exporters/mastra-storage.d.ts +91 -0
- package/dist/exporters/mastra-storage.d.ts.map +1 -0
- package/dist/index.cjs +860 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +859 -9
- package/dist/index.js.map +1 -1
- package/dist/model-tracing.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -16209,6 +16209,852 @@ var DefaultExporter = class extends BaseExporter {
|
|
|
16209
16209
|
this.logger.info("DefaultExporter shutdown complete");
|
|
16210
16210
|
}
|
|
16211
16211
|
};
|
|
16212
|
+
var SIGNAL_PUBLISH_SUFFIXES2 = {
|
|
16213
|
+
traces: "/spans/publish",
|
|
16214
|
+
logs: "/logs/publish",
|
|
16215
|
+
metrics: "/metrics/publish",
|
|
16216
|
+
scores: "/scores/publish",
|
|
16217
|
+
feedback: "/feedback/publish"
|
|
16218
|
+
};
|
|
16219
|
+
var DEFAULT_PLATFORM_SPAN_FILTER = (span) => span.type !== SpanType.MODEL_CHUNK;
|
|
16220
|
+
var SIGNAL_PUBLISH_SEGMENTS2 = {
|
|
16221
|
+
traces: "spans",
|
|
16222
|
+
logs: "logs",
|
|
16223
|
+
metrics: "metrics",
|
|
16224
|
+
scores: "scores",
|
|
16225
|
+
feedback: "feedback"
|
|
16226
|
+
};
|
|
16227
|
+
function trimTrailingSlashes2(value) {
|
|
16228
|
+
let end = value.length;
|
|
16229
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) {
|
|
16230
|
+
end--;
|
|
16231
|
+
}
|
|
16232
|
+
return end === value.length ? value : value.slice(0, end);
|
|
16233
|
+
}
|
|
16234
|
+
function createInvalidEndpointError2(endpoint, text, cause) {
|
|
16235
|
+
return new MastraError(
|
|
16236
|
+
{
|
|
16237
|
+
id: `MASTRA_PLATFORM_EXPORTER_INVALID_ENDPOINT`,
|
|
16238
|
+
text,
|
|
16239
|
+
domain: ErrorDomain.MASTRA_OBSERVABILITY,
|
|
16240
|
+
category: ErrorCategory.USER,
|
|
16241
|
+
details: {
|
|
16242
|
+
endpoint
|
|
16243
|
+
}
|
|
16244
|
+
},
|
|
16245
|
+
cause
|
|
16246
|
+
);
|
|
16247
|
+
}
|
|
16248
|
+
var VALID_PROJECT_ID2 = /^[a-zA-Z0-9_-]+$/;
|
|
16249
|
+
function createInvalidProjectIdError2(projectId) {
|
|
16250
|
+
return new MastraError({
|
|
16251
|
+
id: `MASTRA_PLATFORM_EXPORTER_INVALID_PROJECT_ID`,
|
|
16252
|
+
text: "MastraPlatformExporter projectId must only contain letters, numbers, hyphens, and underscores.",
|
|
16253
|
+
domain: ErrorDomain.MASTRA_OBSERVABILITY,
|
|
16254
|
+
category: ErrorCategory.USER,
|
|
16255
|
+
details: {
|
|
16256
|
+
projectId
|
|
16257
|
+
}
|
|
16258
|
+
});
|
|
16259
|
+
}
|
|
16260
|
+
function resolveBaseEndpoint2(baseEndpoint) {
|
|
16261
|
+
const normalizedEndpoint = trimTrailingSlashes2(baseEndpoint);
|
|
16262
|
+
const invalidText = 'MastraPlatformExporter endpoint must be a base origin like "https://collector.example.com" with no path, search, or hash.';
|
|
16263
|
+
try {
|
|
16264
|
+
const parsedEndpoint = new URL(normalizedEndpoint);
|
|
16265
|
+
if (parsedEndpoint.pathname !== "/" || parsedEndpoint.search || parsedEndpoint.hash) {
|
|
16266
|
+
throw createInvalidEndpointError2(baseEndpoint, invalidText);
|
|
16267
|
+
}
|
|
16268
|
+
return trimTrailingSlashes2(parsedEndpoint.origin);
|
|
16269
|
+
} catch (error48) {
|
|
16270
|
+
if (error48 instanceof MastraError) {
|
|
16271
|
+
throw error48;
|
|
16272
|
+
}
|
|
16273
|
+
throw createInvalidEndpointError2(baseEndpoint, invalidText, error48);
|
|
16274
|
+
}
|
|
16275
|
+
}
|
|
16276
|
+
function buildSignalPath2(signal, projectId) {
|
|
16277
|
+
const signalSegment = SIGNAL_PUBLISH_SEGMENTS2[signal];
|
|
16278
|
+
if (!projectId) {
|
|
16279
|
+
return `/ai/${signalSegment}/publish`;
|
|
16280
|
+
}
|
|
16281
|
+
return `/projects/${projectId}/ai/${signalSegment}/publish`;
|
|
16282
|
+
}
|
|
16283
|
+
function buildSignalEndpoint2(baseEndpoint, signal, projectId) {
|
|
16284
|
+
return `${baseEndpoint}${buildSignalPath2(signal, projectId)}`;
|
|
16285
|
+
}
|
|
16286
|
+
function resolveExplicitSignalEndpoint2(signal, endpoint, projectId) {
|
|
16287
|
+
const normalizedEndpoint = trimTrailingSlashes2(endpoint);
|
|
16288
|
+
const invalidText = `MastraPlatformExporter ${signal}Endpoint must be a base origin like "https://collector.example.com" or a full ${signal} publish URL ending in "${SIGNAL_PUBLISH_SUFFIXES2[signal]}".`;
|
|
16289
|
+
try {
|
|
16290
|
+
const parsedEndpoint = new URL(normalizedEndpoint);
|
|
16291
|
+
if (parsedEndpoint.search || parsedEndpoint.hash) {
|
|
16292
|
+
throw createInvalidEndpointError2(endpoint, invalidText);
|
|
16293
|
+
}
|
|
16294
|
+
const normalizedOrigin = trimTrailingSlashes2(parsedEndpoint.origin);
|
|
16295
|
+
const normalizedPathname = trimTrailingSlashes2(parsedEndpoint.pathname);
|
|
16296
|
+
if (!normalizedPathname || normalizedPathname === "/") {
|
|
16297
|
+
return buildSignalEndpoint2(normalizedOrigin, signal, projectId);
|
|
16298
|
+
}
|
|
16299
|
+
if (normalizedPathname.endsWith(SIGNAL_PUBLISH_SUFFIXES2[signal])) {
|
|
16300
|
+
return `${normalizedOrigin}${normalizedPathname}`;
|
|
16301
|
+
}
|
|
16302
|
+
throw createInvalidEndpointError2(endpoint, invalidText);
|
|
16303
|
+
} catch (error48) {
|
|
16304
|
+
if (error48 instanceof MastraError) {
|
|
16305
|
+
throw error48;
|
|
16306
|
+
}
|
|
16307
|
+
throw createInvalidEndpointError2(endpoint, invalidText, error48);
|
|
16308
|
+
}
|
|
16309
|
+
}
|
|
16310
|
+
function deriveSignalEndpointFromTracesEndpoint2(signal, tracesEndpoint) {
|
|
16311
|
+
if (signal === "traces") {
|
|
16312
|
+
return tracesEndpoint;
|
|
16313
|
+
}
|
|
16314
|
+
const normalizedTracesEndpoint = trimTrailingSlashes2(tracesEndpoint);
|
|
16315
|
+
const invalidText = 'MastraPlatformExporter tracesEndpoint must be a base origin like "https://collector.example.com" or a full traces publish URL ending in "/spans/publish".';
|
|
16316
|
+
try {
|
|
16317
|
+
const parsedEndpoint = new URL(normalizedTracesEndpoint);
|
|
16318
|
+
const normalizedOrigin = trimTrailingSlashes2(parsedEndpoint.origin);
|
|
16319
|
+
const normalizedPathname = trimTrailingSlashes2(parsedEndpoint.pathname);
|
|
16320
|
+
if (!normalizedPathname.endsWith(SIGNAL_PUBLISH_SUFFIXES2.traces)) {
|
|
16321
|
+
throw createInvalidEndpointError2(tracesEndpoint, invalidText);
|
|
16322
|
+
}
|
|
16323
|
+
const basePath = normalizedPathname.slice(0, -SIGNAL_PUBLISH_SUFFIXES2.traces.length);
|
|
16324
|
+
return `${normalizedOrigin}${basePath}${SIGNAL_PUBLISH_SUFFIXES2[signal]}`;
|
|
16325
|
+
} catch (error48) {
|
|
16326
|
+
if (error48 instanceof MastraError) {
|
|
16327
|
+
throw error48;
|
|
16328
|
+
}
|
|
16329
|
+
throw createInvalidEndpointError2(tracesEndpoint, invalidText, error48);
|
|
16330
|
+
}
|
|
16331
|
+
}
|
|
16332
|
+
var MastraPlatformExporter = class extends BaseExporter {
|
|
16333
|
+
name = "mastra-platform-exporter";
|
|
16334
|
+
platformConfig;
|
|
16335
|
+
buffer;
|
|
16336
|
+
flushTimer = null;
|
|
16337
|
+
inFlightFlushes = /* @__PURE__ */ new Set();
|
|
16338
|
+
constructor(config2 = {}) {
|
|
16339
|
+
super(config2);
|
|
16340
|
+
if (config2.projectId !== void 0 && !VALID_PROJECT_ID2.test(config2.projectId)) {
|
|
16341
|
+
throw createInvalidProjectIdError2(config2.projectId);
|
|
16342
|
+
}
|
|
16343
|
+
const accessToken = config2.accessToken || process.env.MASTRA_PLATFORM_ACCESS_TOKEN || process.env.MASTRA_CLOUD_ACCESS_TOKEN;
|
|
16344
|
+
const envProjectId = process.env.MASTRA_PROJECT_ID === "" ? void 0 : process.env.MASTRA_PROJECT_ID;
|
|
16345
|
+
const rawProjectId = config2.projectId ?? envProjectId;
|
|
16346
|
+
if (rawProjectId !== void 0 && !VALID_PROJECT_ID2.test(rawProjectId)) {
|
|
16347
|
+
throw createInvalidProjectIdError2(rawProjectId);
|
|
16348
|
+
}
|
|
16349
|
+
const projectId = rawProjectId;
|
|
16350
|
+
if (!accessToken) {
|
|
16351
|
+
this.setDisabled("MASTRA_PLATFORM_ACCESS_TOKEN environment variable not set.", "debug");
|
|
16352
|
+
}
|
|
16353
|
+
const tracesEndpointOverride = config2.tracesEndpoint ?? process.env.MASTRA_CLOUD_TRACES_ENDPOINT;
|
|
16354
|
+
let baseEndpoint;
|
|
16355
|
+
let tracesEndpoint;
|
|
16356
|
+
if (tracesEndpointOverride) {
|
|
16357
|
+
tracesEndpoint = resolveExplicitSignalEndpoint2("traces", tracesEndpointOverride, projectId);
|
|
16358
|
+
} else {
|
|
16359
|
+
baseEndpoint = resolveBaseEndpoint2(config2.endpoint ?? "https://observability.mastra.ai");
|
|
16360
|
+
tracesEndpoint = buildSignalEndpoint2(baseEndpoint, "traces", projectId);
|
|
16361
|
+
}
|
|
16362
|
+
const resolveConfiguredSignalEndpoint = (signal, explicitEndpoint) => {
|
|
16363
|
+
if (explicitEndpoint) {
|
|
16364
|
+
return resolveExplicitSignalEndpoint2(signal, explicitEndpoint, projectId);
|
|
16365
|
+
}
|
|
16366
|
+
if (tracesEndpointOverride) {
|
|
16367
|
+
return deriveSignalEndpointFromTracesEndpoint2(signal, tracesEndpoint);
|
|
16368
|
+
}
|
|
16369
|
+
return buildSignalEndpoint2(baseEndpoint, signal, projectId);
|
|
16370
|
+
};
|
|
16371
|
+
this.platformConfig = {
|
|
16372
|
+
logger: this.logger,
|
|
16373
|
+
logLevel: config2.logLevel ?? LogLevel.INFO,
|
|
16374
|
+
maxBatchSize: config2.maxBatchSize ?? 1e3,
|
|
16375
|
+
maxBatchWaitMs: config2.maxBatchWaitMs ?? 5e3,
|
|
16376
|
+
maxRetries: config2.maxRetries ?? 3,
|
|
16377
|
+
accessToken: accessToken || "",
|
|
16378
|
+
tracesEndpoint,
|
|
16379
|
+
logsEndpoint: resolveConfiguredSignalEndpoint("logs", config2.logsEndpoint),
|
|
16380
|
+
metricsEndpoint: resolveConfiguredSignalEndpoint("metrics", config2.metricsEndpoint),
|
|
16381
|
+
scoresEndpoint: resolveConfiguredSignalEndpoint("scores", config2.scoresEndpoint),
|
|
16382
|
+
feedbackEndpoint: resolveConfiguredSignalEndpoint("feedback", config2.feedbackEndpoint)
|
|
16383
|
+
};
|
|
16384
|
+
this.buffer = {
|
|
16385
|
+
spans: [],
|
|
16386
|
+
logs: [],
|
|
16387
|
+
metrics: [],
|
|
16388
|
+
scores: [],
|
|
16389
|
+
feedback: [],
|
|
16390
|
+
totalSize: 0
|
|
16391
|
+
};
|
|
16392
|
+
}
|
|
16393
|
+
async _exportTracingEvent(event) {
|
|
16394
|
+
if (event.type !== TracingEventType.SPAN_ENDED) {
|
|
16395
|
+
return;
|
|
16396
|
+
}
|
|
16397
|
+
if (!DEFAULT_PLATFORM_SPAN_FILTER(event.exportedSpan)) {
|
|
16398
|
+
return;
|
|
16399
|
+
}
|
|
16400
|
+
this.addToBuffer(event);
|
|
16401
|
+
await this.handleBufferedEvent();
|
|
16402
|
+
}
|
|
16403
|
+
async onLogEvent(event) {
|
|
16404
|
+
if (this.isDisabled) {
|
|
16405
|
+
return;
|
|
16406
|
+
}
|
|
16407
|
+
this.addLogToBuffer(event);
|
|
16408
|
+
await this.handleBufferedEvent();
|
|
16409
|
+
}
|
|
16410
|
+
async onMetricEvent(event) {
|
|
16411
|
+
if (this.isDisabled) {
|
|
16412
|
+
return;
|
|
16413
|
+
}
|
|
16414
|
+
this.addMetricToBuffer(event);
|
|
16415
|
+
await this.handleBufferedEvent();
|
|
16416
|
+
}
|
|
16417
|
+
async onScoreEvent(event) {
|
|
16418
|
+
if (this.isDisabled) {
|
|
16419
|
+
return;
|
|
16420
|
+
}
|
|
16421
|
+
this.addScoreToBuffer(event);
|
|
16422
|
+
await this.handleBufferedEvent();
|
|
16423
|
+
}
|
|
16424
|
+
async onFeedbackEvent(event) {
|
|
16425
|
+
if (this.isDisabled) {
|
|
16426
|
+
return;
|
|
16427
|
+
}
|
|
16428
|
+
this.addFeedbackToBuffer(event);
|
|
16429
|
+
await this.handleBufferedEvent();
|
|
16430
|
+
}
|
|
16431
|
+
addToBuffer(event) {
|
|
16432
|
+
this.markBufferStart();
|
|
16433
|
+
const spanRecord = this.formatSpan(event.exportedSpan);
|
|
16434
|
+
this.buffer.spans.push(spanRecord);
|
|
16435
|
+
this.buffer.totalSize++;
|
|
16436
|
+
}
|
|
16437
|
+
addLogToBuffer(event) {
|
|
16438
|
+
this.markBufferStart();
|
|
16439
|
+
this.buffer.logs.push(this.formatLog(event.log));
|
|
16440
|
+
this.buffer.totalSize++;
|
|
16441
|
+
}
|
|
16442
|
+
addMetricToBuffer(event) {
|
|
16443
|
+
this.markBufferStart();
|
|
16444
|
+
this.buffer.metrics.push(this.formatMetric(event.metric));
|
|
16445
|
+
this.buffer.totalSize++;
|
|
16446
|
+
}
|
|
16447
|
+
addScoreToBuffer(event) {
|
|
16448
|
+
this.markBufferStart();
|
|
16449
|
+
this.buffer.scores.push(this.formatScore(event.score));
|
|
16450
|
+
this.buffer.totalSize++;
|
|
16451
|
+
}
|
|
16452
|
+
addFeedbackToBuffer(event) {
|
|
16453
|
+
this.markBufferStart();
|
|
16454
|
+
this.buffer.feedback.push(this.formatFeedback(event.feedback));
|
|
16455
|
+
this.buffer.totalSize++;
|
|
16456
|
+
}
|
|
16457
|
+
markBufferStart() {
|
|
16458
|
+
if (this.buffer.totalSize === 0) {
|
|
16459
|
+
this.buffer.firstEventTime = /* @__PURE__ */ new Date();
|
|
16460
|
+
}
|
|
16461
|
+
}
|
|
16462
|
+
formatSpan(span) {
|
|
16463
|
+
const spanRecord = {
|
|
16464
|
+
...span,
|
|
16465
|
+
spanId: span.id,
|
|
16466
|
+
spanType: span.type,
|
|
16467
|
+
startedAt: span.startTime,
|
|
16468
|
+
endedAt: span.endTime ?? null,
|
|
16469
|
+
error: span.errorInfo ?? null,
|
|
16470
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
16471
|
+
updatedAt: null
|
|
16472
|
+
};
|
|
16473
|
+
return spanRecord;
|
|
16474
|
+
}
|
|
16475
|
+
formatLog(log) {
|
|
16476
|
+
return {
|
|
16477
|
+
...log
|
|
16478
|
+
};
|
|
16479
|
+
}
|
|
16480
|
+
formatMetric(metric) {
|
|
16481
|
+
return {
|
|
16482
|
+
...metric
|
|
16483
|
+
};
|
|
16484
|
+
}
|
|
16485
|
+
formatScore(score) {
|
|
16486
|
+
return {
|
|
16487
|
+
...score
|
|
16488
|
+
};
|
|
16489
|
+
}
|
|
16490
|
+
formatFeedback(feedback) {
|
|
16491
|
+
return {
|
|
16492
|
+
...feedback
|
|
16493
|
+
};
|
|
16494
|
+
}
|
|
16495
|
+
async handleBufferedEvent() {
|
|
16496
|
+
if (this.shouldFlush()) {
|
|
16497
|
+
void this.flush().catch((error48) => {
|
|
16498
|
+
this.logger.error("Batch flush failed", {
|
|
16499
|
+
error: error48 instanceof Error ? error48.message : String(error48)
|
|
16500
|
+
});
|
|
16501
|
+
});
|
|
16502
|
+
} else if (this.buffer.totalSize === 1) {
|
|
16503
|
+
this.scheduleFlush();
|
|
16504
|
+
}
|
|
16505
|
+
}
|
|
16506
|
+
shouldFlush() {
|
|
16507
|
+
if (this.buffer.totalSize >= this.platformConfig.maxBatchSize) {
|
|
16508
|
+
return true;
|
|
16509
|
+
}
|
|
16510
|
+
if (this.buffer.firstEventTime && this.buffer.totalSize > 0) {
|
|
16511
|
+
const elapsed = Date.now() - this.buffer.firstEventTime.getTime();
|
|
16512
|
+
if (elapsed >= this.platformConfig.maxBatchWaitMs) {
|
|
16513
|
+
return true;
|
|
16514
|
+
}
|
|
16515
|
+
}
|
|
16516
|
+
return false;
|
|
16517
|
+
}
|
|
16518
|
+
scheduleFlush() {
|
|
16519
|
+
if (this.flushTimer) {
|
|
16520
|
+
clearTimeout(this.flushTimer);
|
|
16521
|
+
}
|
|
16522
|
+
this.flushTimer = setTimeout(() => {
|
|
16523
|
+
void this.flush().catch((error48) => {
|
|
16524
|
+
const mastraError = new MastraError(
|
|
16525
|
+
{
|
|
16526
|
+
id: `MASTRA_PLATFORM_EXPORTER_FAILED_TO_SCHEDULE_FLUSH`,
|
|
16527
|
+
domain: ErrorDomain.MASTRA_OBSERVABILITY,
|
|
16528
|
+
category: ErrorCategory.USER
|
|
16529
|
+
},
|
|
16530
|
+
error48
|
|
16531
|
+
);
|
|
16532
|
+
this.logger.trackException(mastraError);
|
|
16533
|
+
this.logger.error("Scheduled flush failed", mastraError);
|
|
16534
|
+
});
|
|
16535
|
+
}, this.platformConfig.maxBatchWaitMs);
|
|
16536
|
+
}
|
|
16537
|
+
async flushBuffer() {
|
|
16538
|
+
if (this.flushTimer) {
|
|
16539
|
+
clearTimeout(this.flushTimer);
|
|
16540
|
+
this.flushTimer = null;
|
|
16541
|
+
}
|
|
16542
|
+
if (this.buffer.totalSize === 0) {
|
|
16543
|
+
return;
|
|
16544
|
+
}
|
|
16545
|
+
const startTime = Date.now();
|
|
16546
|
+
const spansCopy = [...this.buffer.spans];
|
|
16547
|
+
const logsCopy = [...this.buffer.logs];
|
|
16548
|
+
const metricsCopy = [...this.buffer.metrics];
|
|
16549
|
+
const scoresCopy = [...this.buffer.scores];
|
|
16550
|
+
const feedbackCopy = [...this.buffer.feedback];
|
|
16551
|
+
const batchSize = this.buffer.totalSize;
|
|
16552
|
+
const flushReason = this.buffer.totalSize >= this.platformConfig.maxBatchSize ? "size" : "time";
|
|
16553
|
+
this.resetBuffer();
|
|
16554
|
+
const results = await Promise.all([
|
|
16555
|
+
this.flushSignalBatch("traces", spansCopy),
|
|
16556
|
+
this.flushSignalBatch("logs", logsCopy),
|
|
16557
|
+
this.flushSignalBatch("metrics", metricsCopy),
|
|
16558
|
+
this.flushSignalBatch("scores", scoresCopy),
|
|
16559
|
+
this.flushSignalBatch("feedback", feedbackCopy)
|
|
16560
|
+
]);
|
|
16561
|
+
const failedSignals = results.filter((result) => !result.succeeded).map((result) => result.signal);
|
|
16562
|
+
const elapsed = Date.now() - startTime;
|
|
16563
|
+
if (failedSignals.length === 0) {
|
|
16564
|
+
this.logger.debug("Batch flushed successfully", {
|
|
16565
|
+
batchSize,
|
|
16566
|
+
flushReason,
|
|
16567
|
+
durationMs: elapsed
|
|
16568
|
+
});
|
|
16569
|
+
return;
|
|
16570
|
+
}
|
|
16571
|
+
this.logger.warn("Batch flush completed with dropped signal batches", {
|
|
16572
|
+
batchSize,
|
|
16573
|
+
flushReason,
|
|
16574
|
+
durationMs: elapsed,
|
|
16575
|
+
failedSignals
|
|
16576
|
+
});
|
|
16577
|
+
}
|
|
16578
|
+
/**
|
|
16579
|
+
* Uploads a signal batch to the configured Mastra Observability API using fetchWithRetry.
|
|
16580
|
+
*/
|
|
16581
|
+
async batchUpload(signal, records) {
|
|
16582
|
+
const headers = {
|
|
16583
|
+
Authorization: `Bearer ${this.platformConfig.accessToken}`,
|
|
16584
|
+
"Content-Type": "application/json"
|
|
16585
|
+
};
|
|
16586
|
+
const endpointMap = {
|
|
16587
|
+
traces: this.platformConfig.tracesEndpoint,
|
|
16588
|
+
logs: this.platformConfig.logsEndpoint,
|
|
16589
|
+
metrics: this.platformConfig.metricsEndpoint,
|
|
16590
|
+
scores: this.platformConfig.scoresEndpoint,
|
|
16591
|
+
feedback: this.platformConfig.feedbackEndpoint
|
|
16592
|
+
};
|
|
16593
|
+
const options = {
|
|
16594
|
+
method: "POST",
|
|
16595
|
+
headers,
|
|
16596
|
+
body: JSON.stringify({ [SIGNAL_PUBLISH_SEGMENTS2[signal]]: records })
|
|
16597
|
+
};
|
|
16598
|
+
await fetchWithRetry(endpointMap[signal], options, this.platformConfig.maxRetries);
|
|
16599
|
+
}
|
|
16600
|
+
async flushSignalBatch(signal, records) {
|
|
16601
|
+
if (records.length === 0) {
|
|
16602
|
+
return { signal, succeeded: true };
|
|
16603
|
+
}
|
|
16604
|
+
try {
|
|
16605
|
+
await this.batchUpload(signal, records);
|
|
16606
|
+
return { signal, succeeded: true };
|
|
16607
|
+
} catch (error48) {
|
|
16608
|
+
const errorId = `MASTRA_PLATFORM_EXPORTER_FAILED_TO_BATCH_UPLOAD_${signal.toUpperCase()}`;
|
|
16609
|
+
const mastraError = new MastraError(
|
|
16610
|
+
{
|
|
16611
|
+
id: errorId,
|
|
16612
|
+
domain: ErrorDomain.MASTRA_OBSERVABILITY,
|
|
16613
|
+
category: ErrorCategory.USER,
|
|
16614
|
+
details: {
|
|
16615
|
+
signal,
|
|
16616
|
+
droppedBatchSize: records.length
|
|
16617
|
+
}
|
|
16618
|
+
},
|
|
16619
|
+
error48
|
|
16620
|
+
);
|
|
16621
|
+
this.logger.trackException(mastraError);
|
|
16622
|
+
this.logger.error("Batch upload failed after all retries, dropping batch", mastraError);
|
|
16623
|
+
return { signal, succeeded: false };
|
|
16624
|
+
}
|
|
16625
|
+
}
|
|
16626
|
+
resetBuffer() {
|
|
16627
|
+
this.buffer.spans = [];
|
|
16628
|
+
this.buffer.logs = [];
|
|
16629
|
+
this.buffer.metrics = [];
|
|
16630
|
+
this.buffer.scores = [];
|
|
16631
|
+
this.buffer.feedback = [];
|
|
16632
|
+
this.buffer.firstEventTime = void 0;
|
|
16633
|
+
this.buffer.totalSize = 0;
|
|
16634
|
+
}
|
|
16635
|
+
/**
|
|
16636
|
+
* Force flush any buffered events without shutting down the exporter.
|
|
16637
|
+
* This is useful in serverless environments where you need to ensure events
|
|
16638
|
+
* are exported before the runtime instance is terminated.
|
|
16639
|
+
*/
|
|
16640
|
+
async flush() {
|
|
16641
|
+
if (this.isDisabled) {
|
|
16642
|
+
return;
|
|
16643
|
+
}
|
|
16644
|
+
while (this.buffer.totalSize > 0 || this.inFlightFlushes.size > 0) {
|
|
16645
|
+
if (this.buffer.totalSize > 0) {
|
|
16646
|
+
this.logger.debug("Flushing buffered events", {
|
|
16647
|
+
bufferedEvents: this.buffer.totalSize
|
|
16648
|
+
});
|
|
16649
|
+
const flushPromise = this.flushBuffer();
|
|
16650
|
+
this.inFlightFlushes.add(flushPromise);
|
|
16651
|
+
try {
|
|
16652
|
+
await flushPromise;
|
|
16653
|
+
} finally {
|
|
16654
|
+
this.inFlightFlushes.delete(flushPromise);
|
|
16655
|
+
}
|
|
16656
|
+
continue;
|
|
16657
|
+
}
|
|
16658
|
+
await Promise.allSettled([...this.inFlightFlushes]);
|
|
16659
|
+
}
|
|
16660
|
+
}
|
|
16661
|
+
async shutdown() {
|
|
16662
|
+
if (this.isDisabled) {
|
|
16663
|
+
return;
|
|
16664
|
+
}
|
|
16665
|
+
if (this.flushTimer) {
|
|
16666
|
+
clearTimeout(this.flushTimer);
|
|
16667
|
+
this.flushTimer = null;
|
|
16668
|
+
}
|
|
16669
|
+
try {
|
|
16670
|
+
await this.flush();
|
|
16671
|
+
} catch (error48) {
|
|
16672
|
+
const mastraError = new MastraError(
|
|
16673
|
+
{
|
|
16674
|
+
id: `MASTRA_PLATFORM_EXPORTER_FAILED_TO_FLUSH_REMAINING_EVENTS_DURING_SHUTDOWN`,
|
|
16675
|
+
domain: ErrorDomain.MASTRA_OBSERVABILITY,
|
|
16676
|
+
category: ErrorCategory.USER,
|
|
16677
|
+
details: {
|
|
16678
|
+
remainingEvents: this.buffer.totalSize
|
|
16679
|
+
}
|
|
16680
|
+
},
|
|
16681
|
+
error48
|
|
16682
|
+
);
|
|
16683
|
+
this.logger.trackException(mastraError);
|
|
16684
|
+
this.logger.error("Failed to flush remaining events during shutdown", mastraError);
|
|
16685
|
+
}
|
|
16686
|
+
this.logger.info("MastraPlatformExporter shutdown complete");
|
|
16687
|
+
}
|
|
16688
|
+
};
|
|
16689
|
+
function resolveTracingStorageStrategy2(config2, observabilityStorage, storageName, logger) {
|
|
16690
|
+
const observabilityStrategy = observabilityStorage.observabilityStrategy;
|
|
16691
|
+
if (config2.strategy && config2.strategy !== "auto") {
|
|
16692
|
+
if (observabilityStrategy.supported.includes(config2.strategy)) {
|
|
16693
|
+
return config2.strategy;
|
|
16694
|
+
}
|
|
16695
|
+
logger.warn("User-specified tracing strategy not supported by storage adapter, falling back to auto-selection", {
|
|
16696
|
+
userStrategy: config2.strategy,
|
|
16697
|
+
storageAdapter: storageName,
|
|
16698
|
+
supportedStrategies: observabilityStrategy.supported,
|
|
16699
|
+
fallbackStrategy: observabilityStrategy.preferred
|
|
16700
|
+
});
|
|
16701
|
+
}
|
|
16702
|
+
return observabilityStrategy.preferred;
|
|
16703
|
+
}
|
|
16704
|
+
var MastraStorageExporter = class extends BaseExporter {
|
|
16705
|
+
name = "mastra-storage-exporter";
|
|
16706
|
+
#config;
|
|
16707
|
+
#isInitializing = false;
|
|
16708
|
+
#initPromises = /* @__PURE__ */ new Set();
|
|
16709
|
+
#eventBuffer;
|
|
16710
|
+
#storage;
|
|
16711
|
+
#observabilityStorage;
|
|
16712
|
+
#resolvedStrategy;
|
|
16713
|
+
#flushTimer;
|
|
16714
|
+
// Signals whose storage methods threw "not implemented" — skip on future flushes
|
|
16715
|
+
#unsupportedSignals = /* @__PURE__ */ new Set();
|
|
16716
|
+
constructor(config2 = {}) {
|
|
16717
|
+
super(config2);
|
|
16718
|
+
this.#config = {
|
|
16719
|
+
...config2,
|
|
16720
|
+
maxBatchSize: config2.maxBatchSize ?? 1e3,
|
|
16721
|
+
maxBufferSize: config2.maxBufferSize ?? 1e4,
|
|
16722
|
+
maxBatchWaitMs: config2.maxBatchWaitMs ?? 5e3,
|
|
16723
|
+
maxRetries: config2.maxRetries ?? 4,
|
|
16724
|
+
retryDelayMs: config2.retryDelayMs ?? 500,
|
|
16725
|
+
strategy: config2.strategy ?? "auto"
|
|
16726
|
+
};
|
|
16727
|
+
this.#eventBuffer = new EventBuffer({ maxRetries: this.#config.maxRetries ?? 4 });
|
|
16728
|
+
}
|
|
16729
|
+
/**
|
|
16730
|
+
* Initialize the exporter (called after all dependencies are ready)
|
|
16731
|
+
*/
|
|
16732
|
+
async init(options) {
|
|
16733
|
+
try {
|
|
16734
|
+
this.#isInitializing = true;
|
|
16735
|
+
this.#storage = options.mastra?.getStorage();
|
|
16736
|
+
if (!this.#storage) {
|
|
16737
|
+
this.logger.warn("MastraStorageExporter disabled: Storage not available. Traces will not be persisted.");
|
|
16738
|
+
return;
|
|
16739
|
+
}
|
|
16740
|
+
this.#observabilityStorage = await this.#storage.getStore("observability");
|
|
16741
|
+
if (!this.#observabilityStorage) {
|
|
16742
|
+
this.logger.warn(
|
|
16743
|
+
"MastraStorageExporter disabled: Observability storage not available. Traces will not be persisted."
|
|
16744
|
+
);
|
|
16745
|
+
return;
|
|
16746
|
+
}
|
|
16747
|
+
if (!this.#resolvedStrategy) {
|
|
16748
|
+
this.#resolvedStrategy = resolveTracingStorageStrategy2(
|
|
16749
|
+
this.#config,
|
|
16750
|
+
this.#observabilityStorage,
|
|
16751
|
+
this.#storage.constructor.name,
|
|
16752
|
+
this.logger
|
|
16753
|
+
);
|
|
16754
|
+
this.logger.debug("tracing storage exporter initialized", {
|
|
16755
|
+
strategy: this.#resolvedStrategy,
|
|
16756
|
+
source: this.#config.strategy !== "auto" ? "user" : "auto",
|
|
16757
|
+
storageAdapter: this.#storage.constructor.name,
|
|
16758
|
+
maxBatchSize: this.#config.maxBatchSize,
|
|
16759
|
+
maxBatchWaitMs: this.#config.maxBatchWaitMs
|
|
16760
|
+
});
|
|
16761
|
+
}
|
|
16762
|
+
if (this.#resolvedStrategy) {
|
|
16763
|
+
this.#eventBuffer.init({ strategy: this.#resolvedStrategy });
|
|
16764
|
+
}
|
|
16765
|
+
} finally {
|
|
16766
|
+
this.#isInitializing = false;
|
|
16767
|
+
this.#initPromises.forEach((resolve) => {
|
|
16768
|
+
resolve();
|
|
16769
|
+
});
|
|
16770
|
+
this.#initPromises.clear();
|
|
16771
|
+
}
|
|
16772
|
+
}
|
|
16773
|
+
/**
|
|
16774
|
+
* Checks if buffer should be flushed based on size or time triggers
|
|
16775
|
+
*/
|
|
16776
|
+
shouldFlush() {
|
|
16777
|
+
if (this.#resolvedStrategy === "realtime") {
|
|
16778
|
+
return true;
|
|
16779
|
+
}
|
|
16780
|
+
if (this.#eventBuffer.totalSize >= this.#config.maxBufferSize) {
|
|
16781
|
+
return true;
|
|
16782
|
+
}
|
|
16783
|
+
if (this.#eventBuffer.totalSize >= this.#config.maxBatchSize) {
|
|
16784
|
+
return true;
|
|
16785
|
+
}
|
|
16786
|
+
if (this.#eventBuffer.totalSize > 0) {
|
|
16787
|
+
if (this.#eventBuffer.elapsed >= this.#config.maxBatchWaitMs) {
|
|
16788
|
+
return true;
|
|
16789
|
+
}
|
|
16790
|
+
}
|
|
16791
|
+
return false;
|
|
16792
|
+
}
|
|
16793
|
+
/**
|
|
16794
|
+
* Schedules a flush using setTimeout
|
|
16795
|
+
*/
|
|
16796
|
+
scheduleFlush() {
|
|
16797
|
+
if (this.#flushTimer) {
|
|
16798
|
+
clearTimeout(this.#flushTimer);
|
|
16799
|
+
}
|
|
16800
|
+
this.#flushTimer = setTimeout(() => {
|
|
16801
|
+
this.flushBuffer().catch((error48) => {
|
|
16802
|
+
this.logger.error("Scheduled flush failed", {
|
|
16803
|
+
error: error48 instanceof Error ? error48.message : String(error48)
|
|
16804
|
+
});
|
|
16805
|
+
});
|
|
16806
|
+
}, this.#config.maxBatchWaitMs);
|
|
16807
|
+
}
|
|
16808
|
+
/**
|
|
16809
|
+
* Checks flush triggers and schedules/triggers flush as needed.
|
|
16810
|
+
* Called after adding any event to the buffer.
|
|
16811
|
+
* Returns the flush promise when flushing so callers can await it.
|
|
16812
|
+
*/
|
|
16813
|
+
async handleBatchedFlush() {
|
|
16814
|
+
if (this.shouldFlush()) {
|
|
16815
|
+
await this.flushBuffer();
|
|
16816
|
+
} else if (this.#eventBuffer.totalSize === 1) {
|
|
16817
|
+
this.scheduleFlush();
|
|
16818
|
+
}
|
|
16819
|
+
}
|
|
16820
|
+
/**
|
|
16821
|
+
* Flush a batch of create events for a single signal type.
|
|
16822
|
+
* On "not implemented" errors, disables the signal for future flushes.
|
|
16823
|
+
* On other errors, re-adds events to the buffer for retry.
|
|
16824
|
+
*/
|
|
16825
|
+
async flushCreates(signal, events, storageCall) {
|
|
16826
|
+
if (this.#unsupportedSignals.has(signal) || events.length === 0) return;
|
|
16827
|
+
try {
|
|
16828
|
+
await storageCall(events);
|
|
16829
|
+
} catch (error48) {
|
|
16830
|
+
if (error48 instanceof MastraError && error48.domain === ErrorDomain.MASTRA_OBSERVABILITY && error48.id.endsWith("_NOT_IMPLEMENTED")) {
|
|
16831
|
+
this.logger.warn(error48.message);
|
|
16832
|
+
this.#unsupportedSignals.add(signal);
|
|
16833
|
+
} else {
|
|
16834
|
+
this.#eventBuffer.reAddCreates(events);
|
|
16835
|
+
}
|
|
16836
|
+
}
|
|
16837
|
+
}
|
|
16838
|
+
/**
|
|
16839
|
+
* Flush span update/end events, deferring any whose span hasn't been created yet.
|
|
16840
|
+
* When `isEnd` is true, successfully flushed spans are removed from tracking.
|
|
16841
|
+
*/
|
|
16842
|
+
async flushSpanUpdates(events, deferredUpdates, isEnd) {
|
|
16843
|
+
if (this.#unsupportedSignals.has("tracing") || events.length === 0) return;
|
|
16844
|
+
const partials = [];
|
|
16845
|
+
for (const event of events) {
|
|
16846
|
+
const span = event.exportedSpan;
|
|
16847
|
+
if (this.#eventBuffer.spanExists(span)) {
|
|
16848
|
+
partials.push({
|
|
16849
|
+
traceId: span.traceId,
|
|
16850
|
+
spanId: span.id,
|
|
16851
|
+
updates: buildUpdateSpanRecord(span)
|
|
16852
|
+
});
|
|
16853
|
+
} else {
|
|
16854
|
+
deferredUpdates.push(event);
|
|
16855
|
+
}
|
|
16856
|
+
}
|
|
16857
|
+
if (partials.length === 0) return;
|
|
16858
|
+
try {
|
|
16859
|
+
await this.#observabilityStorage.batchUpdateSpans({ records: partials });
|
|
16860
|
+
if (isEnd) {
|
|
16861
|
+
this.#eventBuffer.endFinishedSpans({ records: partials });
|
|
16862
|
+
}
|
|
16863
|
+
} catch (error48) {
|
|
16864
|
+
if (error48 instanceof MastraError && error48.domain === ErrorDomain.MASTRA_OBSERVABILITY && error48.id.endsWith("_NOT_IMPLEMENTED")) {
|
|
16865
|
+
this.logger.warn(error48.message);
|
|
16866
|
+
this.#unsupportedSignals.add("tracing");
|
|
16867
|
+
} else {
|
|
16868
|
+
deferredUpdates.length = 0;
|
|
16869
|
+
this.#eventBuffer.reAddUpdates(events);
|
|
16870
|
+
}
|
|
16871
|
+
}
|
|
16872
|
+
}
|
|
16873
|
+
/**
|
|
16874
|
+
* Flushes the current buffer to storage.
|
|
16875
|
+
*
|
|
16876
|
+
* Creates are flushed first, then their span keys are added to allCreatedSpans.
|
|
16877
|
+
* Updates are checked against allCreatedSpans — those whose span hasn't been
|
|
16878
|
+
* created yet are re-inserted into the live buffer for the next flush.
|
|
16879
|
+
* Completed spans (SPAN_ENDED) are cleaned up from allCreatedSpans after success.
|
|
16880
|
+
*/
|
|
16881
|
+
async flushBuffer() {
|
|
16882
|
+
if (!this.#observabilityStorage) {
|
|
16883
|
+
this.logger.debug("Cannot flush. Observability storage is not initialized");
|
|
16884
|
+
return;
|
|
16885
|
+
}
|
|
16886
|
+
if (!this.#resolvedStrategy) {
|
|
16887
|
+
this.logger.debug("Cannot flush. Observability strategy is not resolved");
|
|
16888
|
+
return;
|
|
16889
|
+
}
|
|
16890
|
+
if (this.#flushTimer) {
|
|
16891
|
+
clearTimeout(this.#flushTimer);
|
|
16892
|
+
this.#flushTimer = void 0;
|
|
16893
|
+
}
|
|
16894
|
+
if (this.#eventBuffer.totalSize === 0) {
|
|
16895
|
+
return;
|
|
16896
|
+
}
|
|
16897
|
+
const startTime = Date.now();
|
|
16898
|
+
const batchSize = this.#eventBuffer.totalSize;
|
|
16899
|
+
const creates = this.#eventBuffer.creates;
|
|
16900
|
+
const updates = this.#eventBuffer.updates;
|
|
16901
|
+
this.#eventBuffer.reset();
|
|
16902
|
+
const createFeedbackEvents = [];
|
|
16903
|
+
const createLogEvents = [];
|
|
16904
|
+
const createMetricEvents = [];
|
|
16905
|
+
const createScoreEvents = [];
|
|
16906
|
+
const createSpanEvents = [];
|
|
16907
|
+
const updateSpanEvents = [];
|
|
16908
|
+
const endSpanEvents = [];
|
|
16909
|
+
for (const createEvent of creates) {
|
|
16910
|
+
switch (createEvent.type) {
|
|
16911
|
+
case "feedback":
|
|
16912
|
+
createFeedbackEvents.push(createEvent);
|
|
16913
|
+
break;
|
|
16914
|
+
case "log":
|
|
16915
|
+
createLogEvents.push(createEvent);
|
|
16916
|
+
break;
|
|
16917
|
+
case "metric":
|
|
16918
|
+
createMetricEvents.push(createEvent);
|
|
16919
|
+
break;
|
|
16920
|
+
case "score":
|
|
16921
|
+
createScoreEvents.push(createEvent);
|
|
16922
|
+
break;
|
|
16923
|
+
default:
|
|
16924
|
+
createSpanEvents.push(createEvent);
|
|
16925
|
+
break;
|
|
16926
|
+
}
|
|
16927
|
+
}
|
|
16928
|
+
for (const updateEvent of updates) {
|
|
16929
|
+
switch (updateEvent.type) {
|
|
16930
|
+
case TracingEventType.SPAN_UPDATED:
|
|
16931
|
+
updateSpanEvents.push(updateEvent);
|
|
16932
|
+
break;
|
|
16933
|
+
case TracingEventType.SPAN_ENDED:
|
|
16934
|
+
endSpanEvents.push(updateEvent);
|
|
16935
|
+
break;
|
|
16936
|
+
}
|
|
16937
|
+
}
|
|
16938
|
+
await Promise.all([
|
|
16939
|
+
this.flushCreates(
|
|
16940
|
+
"feedback",
|
|
16941
|
+
createFeedbackEvents,
|
|
16942
|
+
(events) => this.#observabilityStorage.batchCreateFeedback({ feedbacks: events.map((f) => buildFeedbackRecord(f)) })
|
|
16943
|
+
),
|
|
16944
|
+
this.flushCreates(
|
|
16945
|
+
"logs",
|
|
16946
|
+
createLogEvents,
|
|
16947
|
+
(events) => this.#observabilityStorage.batchCreateLogs({ logs: events.map((l) => buildLogRecord(l)) })
|
|
16948
|
+
),
|
|
16949
|
+
this.flushCreates(
|
|
16950
|
+
"metrics",
|
|
16951
|
+
createMetricEvents,
|
|
16952
|
+
(events) => this.#observabilityStorage.batchCreateMetrics({ metrics: events.map((m) => buildMetricRecord(m)) })
|
|
16953
|
+
),
|
|
16954
|
+
this.flushCreates(
|
|
16955
|
+
"scores",
|
|
16956
|
+
createScoreEvents,
|
|
16957
|
+
(events) => this.#observabilityStorage.batchCreateScores({ scores: events.map((s) => buildScoreRecord(s)) })
|
|
16958
|
+
),
|
|
16959
|
+
this.flushCreates("tracing", createSpanEvents, async (events) => {
|
|
16960
|
+
const records = events.map((t) => buildCreateSpanRecord(t.exportedSpan));
|
|
16961
|
+
await this.#observabilityStorage.batchCreateSpans({ records });
|
|
16962
|
+
this.#eventBuffer.addCreatedSpans({ records });
|
|
16963
|
+
})
|
|
16964
|
+
]);
|
|
16965
|
+
const deferredUpdates = [];
|
|
16966
|
+
await this.flushSpanUpdates(updateSpanEvents, deferredUpdates, false);
|
|
16967
|
+
await this.flushSpanUpdates(endSpanEvents, deferredUpdates, true);
|
|
16968
|
+
if (deferredUpdates.length > 0) {
|
|
16969
|
+
this.#eventBuffer.reAddUpdates(deferredUpdates);
|
|
16970
|
+
}
|
|
16971
|
+
const elapsed = Date.now() - startTime;
|
|
16972
|
+
this.logger.debug("Batch flushed", {
|
|
16973
|
+
strategy: this.#resolvedStrategy,
|
|
16974
|
+
batchSize,
|
|
16975
|
+
durationMs: elapsed,
|
|
16976
|
+
deferredUpdates: deferredUpdates.length > 0 ? deferredUpdates.length : void 0
|
|
16977
|
+
});
|
|
16978
|
+
return;
|
|
16979
|
+
}
|
|
16980
|
+
async _exportTracingEvent(event) {
|
|
16981
|
+
await this.waitForInit();
|
|
16982
|
+
if (!this.#observabilityStorage) {
|
|
16983
|
+
this.logger.debug("Cannot store traces. Observability storage is not initialized");
|
|
16984
|
+
return;
|
|
16985
|
+
}
|
|
16986
|
+
this.#eventBuffer.addEvent(event);
|
|
16987
|
+
await this.handleBatchedFlush();
|
|
16988
|
+
}
|
|
16989
|
+
/**
|
|
16990
|
+
* Resolves when an ongoing init call is finished
|
|
16991
|
+
* Doesn't wait for the caller to call init
|
|
16992
|
+
* @returns
|
|
16993
|
+
*/
|
|
16994
|
+
async waitForInit() {
|
|
16995
|
+
if (!this.#isInitializing) return;
|
|
16996
|
+
return new Promise((resolve) => {
|
|
16997
|
+
this.#initPromises.add(resolve);
|
|
16998
|
+
});
|
|
16999
|
+
}
|
|
17000
|
+
/**
|
|
17001
|
+
* Handle metric events — buffer for batch flush.
|
|
17002
|
+
*/
|
|
17003
|
+
async onMetricEvent(event) {
|
|
17004
|
+
await this.waitForInit();
|
|
17005
|
+
if (!this.#observabilityStorage) return;
|
|
17006
|
+
this.#eventBuffer.addEvent(event);
|
|
17007
|
+
await this.handleBatchedFlush();
|
|
17008
|
+
}
|
|
17009
|
+
/**
|
|
17010
|
+
* Handle log events — buffer for batch flush.
|
|
17011
|
+
*/
|
|
17012
|
+
async onLogEvent(event) {
|
|
17013
|
+
await this.waitForInit();
|
|
17014
|
+
if (!this.#observabilityStorage) return;
|
|
17015
|
+
this.#eventBuffer.addEvent(event);
|
|
17016
|
+
await this.handleBatchedFlush();
|
|
17017
|
+
}
|
|
17018
|
+
/**
|
|
17019
|
+
* Handle score events — buffer for batch flush.
|
|
17020
|
+
*/
|
|
17021
|
+
async onScoreEvent(event) {
|
|
17022
|
+
await this.waitForInit();
|
|
17023
|
+
if (!this.#observabilityStorage) return;
|
|
17024
|
+
this.#eventBuffer.addEvent(event);
|
|
17025
|
+
await this.handleBatchedFlush();
|
|
17026
|
+
}
|
|
17027
|
+
/**
|
|
17028
|
+
* Handle feedback events — buffer for batch flush.
|
|
17029
|
+
*/
|
|
17030
|
+
async onFeedbackEvent(event) {
|
|
17031
|
+
await this.waitForInit();
|
|
17032
|
+
if (!this.#observabilityStorage) return;
|
|
17033
|
+
this.#eventBuffer.addEvent(event);
|
|
17034
|
+
await this.handleBatchedFlush();
|
|
17035
|
+
}
|
|
17036
|
+
/**
|
|
17037
|
+
* Force flush any buffered spans without shutting down the exporter.
|
|
17038
|
+
* This is useful in serverless environments where you need to ensure spans
|
|
17039
|
+
* are exported before the runtime instance is terminated.
|
|
17040
|
+
*/
|
|
17041
|
+
async flush() {
|
|
17042
|
+
if (this.#eventBuffer.totalSize > 0) {
|
|
17043
|
+
this.logger.debug("Flushing buffered events", {
|
|
17044
|
+
bufferedEvents: this.#eventBuffer.totalSize
|
|
17045
|
+
});
|
|
17046
|
+
await this.flushBuffer();
|
|
17047
|
+
}
|
|
17048
|
+
}
|
|
17049
|
+
async shutdown() {
|
|
17050
|
+
if (this.#flushTimer) {
|
|
17051
|
+
clearTimeout(this.#flushTimer);
|
|
17052
|
+
this.#flushTimer = void 0;
|
|
17053
|
+
}
|
|
17054
|
+
await this.flush();
|
|
17055
|
+
this.logger.info("MastraStorageExporter shutdown complete");
|
|
17056
|
+
}
|
|
17057
|
+
};
|
|
16212
17058
|
var _snapshotsDir;
|
|
16213
17059
|
async function getSnapshotsDir() {
|
|
16214
17060
|
if (!_snapshotsDir) {
|
|
@@ -18175,7 +19021,6 @@ var PricingRegistry = class _PricingRegistry {
|
|
|
18175
19021
|
constructor(pricingModels) {
|
|
18176
19022
|
this.pricingModels = pricingModels;
|
|
18177
19023
|
}
|
|
18178
|
-
pricingModels;
|
|
18179
19024
|
static globalRegistry = null;
|
|
18180
19025
|
static fromText(pricingModelText) {
|
|
18181
19026
|
return new _PricingRegistry(parsePricingModelText(pricingModelText));
|
|
@@ -19027,7 +19872,8 @@ var ModelSpanTracker = class {
|
|
|
19027
19872
|
...payload?.messageId ? { messageId: payload.messageId } : {},
|
|
19028
19873
|
...payload?.warnings?.length ? { warnings: payload.warnings } : {}
|
|
19029
19874
|
},
|
|
19030
|
-
input
|
|
19875
|
+
input,
|
|
19876
|
+
tracingPolicy: this.#modelSpan?.tracingPolicy
|
|
19031
19877
|
});
|
|
19032
19878
|
this.#currentStepInputIsFinal = Array.isArray(payload?.inputMessages);
|
|
19033
19879
|
this.#chunkSequence = 0;
|
|
@@ -19094,7 +19940,8 @@ var ModelSpanTracker = class {
|
|
|
19094
19940
|
...ctx?.toolChoice !== void 0 ? { toolChoice: ctx.toolChoice } : {},
|
|
19095
19941
|
...ctx?.responseFormat !== void 0 ? { responseFormat: ctx.responseFormat } : {}
|
|
19096
19942
|
},
|
|
19097
|
-
input
|
|
19943
|
+
input,
|
|
19944
|
+
tracingPolicy: this.#modelSpan?.tracingPolicy
|
|
19098
19945
|
});
|
|
19099
19946
|
}
|
|
19100
19947
|
/**
|
|
@@ -19187,7 +20034,8 @@ var ModelSpanTracker = class {
|
|
|
19187
20034
|
attributes: {
|
|
19188
20035
|
chunkType,
|
|
19189
20036
|
sequenceNumber: this.#chunkSequence
|
|
19190
|
-
}
|
|
20037
|
+
},
|
|
20038
|
+
tracingPolicy: this.#modelSpan?.tracingPolicy
|
|
19191
20039
|
});
|
|
19192
20040
|
this.#currentChunkType = chunkType;
|
|
19193
20041
|
this.#accumulator = initialData || {};
|
|
@@ -19230,7 +20078,8 @@ var ModelSpanTracker = class {
|
|
|
19230
20078
|
...options?.attributes
|
|
19231
20079
|
},
|
|
19232
20080
|
metadata: options?.metadata,
|
|
19233
|
-
output
|
|
20081
|
+
output,
|
|
20082
|
+
tracingPolicy: this.#modelSpan?.tracingPolicy
|
|
19234
20083
|
});
|
|
19235
20084
|
if (span) {
|
|
19236
20085
|
this.#chunkSequence++;
|
|
@@ -19350,7 +20199,8 @@ var ModelSpanTracker = class {
|
|
|
19350
20199
|
chunkType: "tool-call-approval",
|
|
19351
20200
|
sequenceNumber: this.#chunkSequence
|
|
19352
20201
|
},
|
|
19353
|
-
output: payload
|
|
20202
|
+
output: payload,
|
|
20203
|
+
tracingPolicy: this.#modelSpan?.tracingPolicy
|
|
19354
20204
|
});
|
|
19355
20205
|
if (span) {
|
|
19356
20206
|
this.#chunkSequence++;
|
|
@@ -21148,14 +21998,14 @@ var Observability = class extends MastraBase {
|
|
|
21148
21998
|
};
|
|
21149
21999
|
if (config2.default?.enabled) {
|
|
21150
22000
|
console.warn(
|
|
21151
|
-
'[Mastra Observability] The "default: { enabled: true }" configuration is deprecated and will be removed in a future version. Please use explicit configs with
|
|
22001
|
+
'[Mastra Observability] The "default: { enabled: true }" configuration is deprecated and will be removed in a future version. Please use explicit configs with MastraStorageExporter and MastraPlatformExporter instead. Sensitive data filtering is applied by default and can be controlled via the top-level "sensitiveDataFilter" option. See https://mastra.ai/docs/observability/tracing/overview for the recommended configuration.'
|
|
21152
22002
|
);
|
|
21153
22003
|
const autoFilter = buildAutoSensitiveFilter();
|
|
21154
22004
|
const defaultInstance = new DefaultObservabilityInstance({
|
|
21155
22005
|
serviceName: "mastra",
|
|
21156
22006
|
name: "default",
|
|
21157
22007
|
sampling: { type: "always" /* ALWAYS */ },
|
|
21158
|
-
exporters: [new
|
|
22008
|
+
exporters: [new MastraStorageExporter(), new MastraPlatformExporter()],
|
|
21159
22009
|
spanOutputProcessors: autoFilter ? [autoFilter] : []
|
|
21160
22010
|
});
|
|
21161
22011
|
this.#registry.register("default", defaultInstance, true);
|
|
@@ -21405,6 +22255,6 @@ function buildTracingOptions(...updaters) {
|
|
|
21405
22255
|
return updaters.reduce((opts, updater) => updater(opts), {});
|
|
21406
22256
|
}
|
|
21407
22257
|
|
|
21408
|
-
export { BaseExporter, BaseObservabilityEventBus, BaseObservabilityInstance, BaseSpan, CardinalityFilter, CloudExporter, ConsoleExporter, DEFAULT_DEEP_CLEAN_OPTIONS, DEFAULT_KEYS_TO_STRIP, DefaultExporter, DefaultObservabilityInstance, DefaultSpan, JsonExporter, LoggerContextImpl, MetricsContextImpl, ModelSpanTracker, NoOpSpan, Observability, ObservabilityBus, SamplingStrategyType, SensitiveDataFilter, TestExporter, TraceData, TrackingExporter, buildTracingOptions, chainFormatters, deepClean, getExternalParentId, isSerializedMap, mergeSerializationOptions, observabilityConfigValueSchema, observabilityFeatures, observabilityInstanceConfigSchema, observabilityRegistryConfigSchema, reconstructSerializedMap, routeToHandler, samplingStrategySchema, serializationOptionsSchema, truncateString };
|
|
22258
|
+
export { BaseExporter, BaseObservabilityEventBus, BaseObservabilityInstance, BaseSpan, CardinalityFilter, CloudExporter, ConsoleExporter, DEFAULT_DEEP_CLEAN_OPTIONS, DEFAULT_KEYS_TO_STRIP, DefaultExporter, DefaultObservabilityInstance, DefaultSpan, JsonExporter, LoggerContextImpl, MastraPlatformExporter, MastraStorageExporter, MetricsContextImpl, ModelSpanTracker, NoOpSpan, Observability, ObservabilityBus, SamplingStrategyType, SensitiveDataFilter, TestExporter, TraceData, TrackingExporter, buildTracingOptions, chainFormatters, deepClean, getExternalParentId, isSerializedMap, mergeSerializationOptions, observabilityConfigValueSchema, observabilityFeatures, observabilityInstanceConfigSchema, observabilityRegistryConfigSchema, reconstructSerializedMap, routeToHandler, samplingStrategySchema, serializationOptionsSchema, truncateString };
|
|
21409
22259
|
//# sourceMappingURL=index.js.map
|
|
21410
22260
|
//# sourceMappingURL=index.js.map
|