@mastra/observability 1.6.0-alpha.2 → 1.6.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/CHANGELOG.md +43 -0
- package/dist/context/logger.d.ts +4 -0
- package/dist/context/logger.d.ts.map +1 -1
- package/dist/context/metrics.d.ts +6 -0
- package/dist/context/metrics.d.ts.map +1 -1
- package/dist/default.d.ts +14 -1
- package/dist/default.d.ts.map +1 -1
- package/dist/index.cjs +468 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +468 -46
- package/dist/index.js.map +1 -1
- package/dist/instances/base.d.ts +5 -0
- package/dist/instances/base.d.ts.map +1 -1
- package/dist/recorded.d.ts +43 -0
- package/dist/recorded.d.ts.map +1 -0
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,47 @@ var __export = (target, all) => {
|
|
|
22
22
|
for (var name in all)
|
|
23
23
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
24
24
|
};
|
|
25
|
+
function routeToHandler(handler, event, logger) {
|
|
26
|
+
try {
|
|
27
|
+
switch (event.type) {
|
|
28
|
+
case observability.TracingEventType.SPAN_STARTED:
|
|
29
|
+
case observability.TracingEventType.SPAN_UPDATED:
|
|
30
|
+
case observability.TracingEventType.SPAN_ENDED: {
|
|
31
|
+
const fn = handler.onTracingEvent ? handler.onTracingEvent.bind(handler) : handler.exportTracingEvent.bind(handler);
|
|
32
|
+
return catchAsyncResult(fn(event), handler.name, "tracing", logger);
|
|
33
|
+
}
|
|
34
|
+
case "log":
|
|
35
|
+
if (handler.onLogEvent) {
|
|
36
|
+
return catchAsyncResult(handler.onLogEvent(event), handler.name, "log", logger);
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
case "metric":
|
|
40
|
+
if (handler.onMetricEvent) {
|
|
41
|
+
return catchAsyncResult(handler.onMetricEvent(event), handler.name, "metric", logger);
|
|
42
|
+
}
|
|
43
|
+
break;
|
|
44
|
+
case "score":
|
|
45
|
+
if (handler.onScoreEvent) {
|
|
46
|
+
return catchAsyncResult(handler.onScoreEvent(event), handler.name, "score", logger);
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
case "feedback":
|
|
50
|
+
if (handler.onFeedbackEvent) {
|
|
51
|
+
return catchAsyncResult(handler.onFeedbackEvent(event), handler.name, "feedback", logger);
|
|
52
|
+
}
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
} catch (err) {
|
|
56
|
+
logger.error(`[Observability] Handler error [handler=${handler.name}]:`, err);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function catchAsyncResult(result, handlerName, signal, logger) {
|
|
60
|
+
if (result && typeof result.then === "function") {
|
|
61
|
+
return result.catch((err) => {
|
|
62
|
+
logger.error(`[Observability] ${signal} handler error [handler=${handlerName}]:`, err);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
25
66
|
|
|
26
67
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
27
68
|
var external_exports = {};
|
|
@@ -15901,7 +15942,7 @@ var TestExporter = class extends BaseExporter {
|
|
|
15901
15942
|
this.#trackEvent("log");
|
|
15902
15943
|
if (this.#config.storeLogs) {
|
|
15903
15944
|
const log = event.log;
|
|
15904
|
-
const traceId = log.
|
|
15945
|
+
const traceId = log.traceId;
|
|
15905
15946
|
const logMessage = `[TestExporter] log.${log.level}: "${log.message}"${traceId ? ` (trace: ${traceId.slice(-8)})` : ""}`;
|
|
15906
15947
|
this.#debugLogs.push(logMessage);
|
|
15907
15948
|
}
|
|
@@ -16019,7 +16060,7 @@ var TestExporter = class extends BaseExporter {
|
|
|
16019
16060
|
getByTraceId(traceId) {
|
|
16020
16061
|
const events = this.#tracingEvents.filter((e) => e.exportedSpan.traceId === traceId);
|
|
16021
16062
|
const spans = this.#getUniqueSpansFromEvents(events);
|
|
16022
|
-
const logs = this.#logEvents.filter((e) => e.log.
|
|
16063
|
+
const logs = this.#logEvents.filter((e) => e.log.traceId === traceId).map((e) => e.log);
|
|
16023
16064
|
const scores = this.#scoreEvents.filter((e) => e.score.traceId === traceId).map((e) => e.score);
|
|
16024
16065
|
const feedback = this.#feedbackEvents.filter((e) => e.feedback.traceId === traceId).map((e) => e.feedback);
|
|
16025
16066
|
return { events, spans, logs, scores, feedback };
|
|
@@ -16086,7 +16127,7 @@ var TestExporter = class extends BaseExporter {
|
|
|
16086
16127
|
traceIds.add(event.exportedSpan.traceId);
|
|
16087
16128
|
}
|
|
16088
16129
|
for (const event of this.#logEvents) {
|
|
16089
|
-
if (event.log.
|
|
16130
|
+
if (event.log.traceId) traceIds.add(event.log.traceId);
|
|
16090
16131
|
}
|
|
16091
16132
|
for (const event of this.#scoreEvents) {
|
|
16092
16133
|
traceIds.add(event.score.traceId);
|
|
@@ -16121,7 +16162,7 @@ var TestExporter = class extends BaseExporter {
|
|
|
16121
16162
|
* Get logs for a specific trace
|
|
16122
16163
|
*/
|
|
16123
16164
|
getLogsByTraceId(traceId) {
|
|
16124
|
-
return this.#logEvents.filter((e) => e.log.
|
|
16165
|
+
return this.#logEvents.filter((e) => e.log.traceId === traceId).map((e) => e.log);
|
|
16125
16166
|
}
|
|
16126
16167
|
// ============================================================================
|
|
16127
16168
|
// Metric Query Methods
|
|
@@ -16995,47 +17036,6 @@ var BaseObservabilityEventBus = class _BaseObservabilityEventBus extends base.Ma
|
|
|
16995
17036
|
this.subscribers.clear();
|
|
16996
17037
|
}
|
|
16997
17038
|
};
|
|
16998
|
-
function routeToHandler(handler, event, logger) {
|
|
16999
|
-
try {
|
|
17000
|
-
switch (event.type) {
|
|
17001
|
-
case observability.TracingEventType.SPAN_STARTED:
|
|
17002
|
-
case observability.TracingEventType.SPAN_UPDATED:
|
|
17003
|
-
case observability.TracingEventType.SPAN_ENDED: {
|
|
17004
|
-
const fn = handler.onTracingEvent ? handler.onTracingEvent.bind(handler) : handler.exportTracingEvent.bind(handler);
|
|
17005
|
-
return catchAsyncResult(fn(event), handler.name, "tracing", logger);
|
|
17006
|
-
}
|
|
17007
|
-
case "log":
|
|
17008
|
-
if (handler.onLogEvent) {
|
|
17009
|
-
return catchAsyncResult(handler.onLogEvent(event), handler.name, "log", logger);
|
|
17010
|
-
}
|
|
17011
|
-
break;
|
|
17012
|
-
case "metric":
|
|
17013
|
-
if (handler.onMetricEvent) {
|
|
17014
|
-
return catchAsyncResult(handler.onMetricEvent(event), handler.name, "metric", logger);
|
|
17015
|
-
}
|
|
17016
|
-
break;
|
|
17017
|
-
case "score":
|
|
17018
|
-
if (handler.onScoreEvent) {
|
|
17019
|
-
return catchAsyncResult(handler.onScoreEvent(event), handler.name, "score", logger);
|
|
17020
|
-
}
|
|
17021
|
-
break;
|
|
17022
|
-
case "feedback":
|
|
17023
|
-
if (handler.onFeedbackEvent) {
|
|
17024
|
-
return catchAsyncResult(handler.onFeedbackEvent(event), handler.name, "feedback", logger);
|
|
17025
|
-
}
|
|
17026
|
-
break;
|
|
17027
|
-
}
|
|
17028
|
-
} catch (err) {
|
|
17029
|
-
logger.error(`[Observability] Handler error [handler=${handler.name}]:`, err);
|
|
17030
|
-
}
|
|
17031
|
-
}
|
|
17032
|
-
function catchAsyncResult(result, handlerName, signal, logger) {
|
|
17033
|
-
if (result && typeof result.then === "function") {
|
|
17034
|
-
return result.catch((err) => {
|
|
17035
|
-
logger.error(`[Observability] ${signal} handler error [handler=${handlerName}]:`, err);
|
|
17036
|
-
});
|
|
17037
|
-
}
|
|
17038
|
-
}
|
|
17039
17039
|
|
|
17040
17040
|
// src/bus/observability-bus.ts
|
|
17041
17041
|
var MAX_FLUSH_ITERATIONS = 3;
|
|
@@ -17195,9 +17195,12 @@ var LoggerContextImpl = class {
|
|
|
17195
17195
|
* mutations after construction do not affect emitted logs.
|
|
17196
17196
|
*/
|
|
17197
17197
|
constructor(config2) {
|
|
17198
|
+
const correlationContext = config2.correlationContext ? { ...config2.correlationContext } : void 0;
|
|
17198
17199
|
this.config = {
|
|
17199
17200
|
...config2,
|
|
17200
|
-
|
|
17201
|
+
traceId: config2.traceId ?? correlationContext?.traceId,
|
|
17202
|
+
spanId: config2.spanId ?? correlationContext?.spanId,
|
|
17203
|
+
correlationContext,
|
|
17201
17204
|
metadata: config2.metadata ? structuredClone(config2.metadata) : void 0
|
|
17202
17205
|
};
|
|
17203
17206
|
}
|
|
@@ -17234,6 +17237,8 @@ var LoggerContextImpl = class {
|
|
|
17234
17237
|
level,
|
|
17235
17238
|
message,
|
|
17236
17239
|
data,
|
|
17240
|
+
traceId: this.config.traceId,
|
|
17241
|
+
spanId: this.config.spanId,
|
|
17237
17242
|
correlationContext: this.config.correlationContext,
|
|
17238
17243
|
metadata: this.config.metadata
|
|
17239
17244
|
};
|
|
@@ -17244,6 +17249,8 @@ var LoggerContextImpl = class {
|
|
|
17244
17249
|
|
|
17245
17250
|
// src/context/metrics.ts
|
|
17246
17251
|
var MetricsContextImpl = class {
|
|
17252
|
+
traceId;
|
|
17253
|
+
spanId;
|
|
17247
17254
|
correlationContext;
|
|
17248
17255
|
metadata;
|
|
17249
17256
|
cardinalityFilter;
|
|
@@ -17254,6 +17261,8 @@ var MetricsContextImpl = class {
|
|
|
17254
17261
|
*/
|
|
17255
17262
|
constructor(config2) {
|
|
17256
17263
|
this.correlationContext = config2.correlationContext ? { ...config2.correlationContext } : void 0;
|
|
17264
|
+
this.traceId = config2.traceId ?? this.correlationContext?.traceId;
|
|
17265
|
+
this.spanId = config2.spanId ?? this.correlationContext?.spanId;
|
|
17257
17266
|
this.metadata = config2.metadata ? structuredClone(config2.metadata) : void 0;
|
|
17258
17267
|
this.cardinalityFilter = config2.cardinalityFilter;
|
|
17259
17268
|
this.observabilityBus = config2.observabilityBus;
|
|
@@ -17267,6 +17276,8 @@ var MetricsContextImpl = class {
|
|
|
17267
17276
|
const costContext = options?.costContext ? cloneCostContext(options.costContext) : void 0;
|
|
17268
17277
|
const exportedMetric = {
|
|
17269
17278
|
timestamp: /* @__PURE__ */ new Date(),
|
|
17279
|
+
traceId: this.traceId,
|
|
17280
|
+
spanId: this.spanId,
|
|
17270
17281
|
name,
|
|
17271
17282
|
value,
|
|
17272
17283
|
labels: filteredLabels,
|
|
@@ -19201,6 +19212,8 @@ var BaseObservabilityInstance = class extends base.MastraBase {
|
|
|
19201
19212
|
const correlationContext = span?.getCorrelationContext?.();
|
|
19202
19213
|
const metadata = span?.metadata ? structuredClone(span.metadata) : void 0;
|
|
19203
19214
|
return new LoggerContextImpl({
|
|
19215
|
+
traceId: span?.traceId,
|
|
19216
|
+
spanId: span?.id,
|
|
19204
19217
|
correlationContext,
|
|
19205
19218
|
metadata,
|
|
19206
19219
|
observabilityBus: this.observabilityBus
|
|
@@ -19215,6 +19228,8 @@ var BaseObservabilityInstance = class extends base.MastraBase {
|
|
|
19215
19228
|
const correlationContext = span?.getCorrelationContext?.();
|
|
19216
19229
|
const metadata = span?.metadata ? structuredClone(span.metadata) : void 0;
|
|
19217
19230
|
return new MetricsContextImpl({
|
|
19231
|
+
traceId: span?.traceId,
|
|
19232
|
+
spanId: span?.id,
|
|
19218
19233
|
correlationContext,
|
|
19219
19234
|
metadata,
|
|
19220
19235
|
cardinalityFilter: this.cardinalityFilter,
|
|
@@ -19229,6 +19244,13 @@ var BaseObservabilityInstance = class extends base.MastraBase {
|
|
|
19229
19244
|
emitObservabilityEvent(event) {
|
|
19230
19245
|
this.observabilityBus.emit(event);
|
|
19231
19246
|
}
|
|
19247
|
+
/**
|
|
19248
|
+
* Internal hook used by RecordedTrace/RecordedSpan hydration to route
|
|
19249
|
+
* non-tracing annotation events back through the normal exporter pipeline.
|
|
19250
|
+
*/
|
|
19251
|
+
__emitRecordedEvent(event) {
|
|
19252
|
+
this.emitObservabilityEvent(event);
|
|
19253
|
+
}
|
|
19232
19254
|
// ============================================================================
|
|
19233
19255
|
// Span Lifecycle Management
|
|
19234
19256
|
// ============================================================================
|
|
@@ -19503,6 +19525,311 @@ var DefaultObservabilityInstance = class extends BaseObservabilityInstance {
|
|
|
19503
19525
|
}
|
|
19504
19526
|
};
|
|
19505
19527
|
|
|
19528
|
+
// src/recorded.ts
|
|
19529
|
+
function nullToUndefined(value) {
|
|
19530
|
+
return value ?? void 0;
|
|
19531
|
+
}
|
|
19532
|
+
function mergeMetadata(base, extra) {
|
|
19533
|
+
if (!base && !extra) return void 0;
|
|
19534
|
+
return {
|
|
19535
|
+
...base ?? {},
|
|
19536
|
+
...extra ?? {}
|
|
19537
|
+
};
|
|
19538
|
+
}
|
|
19539
|
+
function normalizeErrorInfo(error48) {
|
|
19540
|
+
if (!error48 || typeof error48 !== "object" || !("message" in error48) || typeof error48.message !== "string") {
|
|
19541
|
+
return void 0;
|
|
19542
|
+
}
|
|
19543
|
+
return {
|
|
19544
|
+
message: error48.message,
|
|
19545
|
+
id: "id" in error48 && typeof error48.id === "string" ? error48.id : void 0,
|
|
19546
|
+
domain: "domain" in error48 && typeof error48.domain === "string" ? error48.domain : void 0,
|
|
19547
|
+
category: "category" in error48 && typeof error48.category === "string" ? error48.category : void 0,
|
|
19548
|
+
details: "details" in error48 && error48.details && typeof error48.details === "object" ? error48.details : void 0
|
|
19549
|
+
};
|
|
19550
|
+
}
|
|
19551
|
+
function buildCorrelationContext(span, rootSpan, parent) {
|
|
19552
|
+
return {
|
|
19553
|
+
tags: rootSpan.tags ?? void 0,
|
|
19554
|
+
entityType: nullToUndefined(span.entityType),
|
|
19555
|
+
entityId: nullToUndefined(span.entityId),
|
|
19556
|
+
entityName: nullToUndefined(span.entityName),
|
|
19557
|
+
parentEntityType: parent?.entityType ?? void 0,
|
|
19558
|
+
parentEntityId: parent?.entityId ?? void 0,
|
|
19559
|
+
parentEntityName: parent?.entityName ?? void 0,
|
|
19560
|
+
rootEntityType: nullToUndefined(rootSpan.entityType),
|
|
19561
|
+
rootEntityId: nullToUndefined(rootSpan.entityId),
|
|
19562
|
+
rootEntityName: nullToUndefined(rootSpan.entityName),
|
|
19563
|
+
userId: nullToUndefined(span.userId),
|
|
19564
|
+
organizationId: nullToUndefined(span.organizationId),
|
|
19565
|
+
resourceId: nullToUndefined(span.resourceId),
|
|
19566
|
+
runId: nullToUndefined(span.runId),
|
|
19567
|
+
sessionId: nullToUndefined(span.sessionId),
|
|
19568
|
+
threadId: nullToUndefined(span.threadId),
|
|
19569
|
+
requestId: nullToUndefined(span.requestId),
|
|
19570
|
+
environment: nullToUndefined(span.environment),
|
|
19571
|
+
source: nullToUndefined(span.source),
|
|
19572
|
+
serviceName: nullToUndefined(span.serviceName),
|
|
19573
|
+
experimentId: nullToUndefined(span.experimentId)
|
|
19574
|
+
};
|
|
19575
|
+
}
|
|
19576
|
+
function buildRecordedScoreEvent(args) {
|
|
19577
|
+
const { span, rootSpan, parent, score, spanId } = args;
|
|
19578
|
+
return {
|
|
19579
|
+
type: "score",
|
|
19580
|
+
score: {
|
|
19581
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
19582
|
+
traceId: span.traceId,
|
|
19583
|
+
spanId,
|
|
19584
|
+
scorerId: score.scorerId,
|
|
19585
|
+
scorerVersion: score.scorerVersion,
|
|
19586
|
+
source: score.source,
|
|
19587
|
+
scoreSource: score.scoreSource,
|
|
19588
|
+
score: score.score,
|
|
19589
|
+
reason: score.reason,
|
|
19590
|
+
experimentId: score.experimentId,
|
|
19591
|
+
scoreTraceId: score.scoreTraceId,
|
|
19592
|
+
correlationContext: buildCorrelationContext(span, rootSpan, parent),
|
|
19593
|
+
metadata: mergeMetadata(span.metadata, score.metadata)
|
|
19594
|
+
}
|
|
19595
|
+
};
|
|
19596
|
+
}
|
|
19597
|
+
function buildRecordedFeedbackEvent(args) {
|
|
19598
|
+
const { span, rootSpan, parent, feedback, spanId } = args;
|
|
19599
|
+
return {
|
|
19600
|
+
type: "feedback",
|
|
19601
|
+
feedback: {
|
|
19602
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
19603
|
+
traceId: span.traceId,
|
|
19604
|
+
spanId,
|
|
19605
|
+
source: feedback.source,
|
|
19606
|
+
feedbackSource: feedback.feedbackSource,
|
|
19607
|
+
feedbackType: feedback.feedbackType,
|
|
19608
|
+
value: feedback.value,
|
|
19609
|
+
userId: feedback.userId,
|
|
19610
|
+
feedbackUserId: feedback.feedbackUserId,
|
|
19611
|
+
comment: feedback.comment,
|
|
19612
|
+
sourceId: feedback.sourceId,
|
|
19613
|
+
experimentId: feedback.experimentId,
|
|
19614
|
+
correlationContext: buildCorrelationContext(span, rootSpan, parent),
|
|
19615
|
+
metadata: mergeMetadata(span.metadata, feedback.metadata)
|
|
19616
|
+
}
|
|
19617
|
+
};
|
|
19618
|
+
}
|
|
19619
|
+
function findSpanById(spans, spanId) {
|
|
19620
|
+
if (!spanId) return void 0;
|
|
19621
|
+
return spans.find((span) => span.spanId === spanId);
|
|
19622
|
+
}
|
|
19623
|
+
function buildRecordedScoreEventFromTrace(args) {
|
|
19624
|
+
const rootSpan = findRootSpan(args.trace.spans);
|
|
19625
|
+
if (!rootSpan) return null;
|
|
19626
|
+
const span = args.spanId ? findSpanById(args.trace.spans, args.spanId) : rootSpan;
|
|
19627
|
+
if (!span) return null;
|
|
19628
|
+
const parent = span.parentSpanId ? findSpanById(args.trace.spans, span.parentSpanId) : void 0;
|
|
19629
|
+
return buildRecordedScoreEvent({
|
|
19630
|
+
span,
|
|
19631
|
+
rootSpan,
|
|
19632
|
+
parent,
|
|
19633
|
+
score: args.score,
|
|
19634
|
+
spanId: args.spanId
|
|
19635
|
+
});
|
|
19636
|
+
}
|
|
19637
|
+
function buildRecordedFeedbackEventFromTrace(args) {
|
|
19638
|
+
const rootSpan = findRootSpan(args.trace.spans);
|
|
19639
|
+
if (!rootSpan) return null;
|
|
19640
|
+
const span = args.spanId ? findSpanById(args.trace.spans, args.spanId) : rootSpan;
|
|
19641
|
+
if (!span) return null;
|
|
19642
|
+
const parent = span.parentSpanId ? findSpanById(args.trace.spans, span.parentSpanId) : void 0;
|
|
19643
|
+
return buildRecordedFeedbackEvent({
|
|
19644
|
+
span,
|
|
19645
|
+
rootSpan,
|
|
19646
|
+
parent,
|
|
19647
|
+
feedback: args.feedback,
|
|
19648
|
+
spanId: args.spanId
|
|
19649
|
+
});
|
|
19650
|
+
}
|
|
19651
|
+
var RecordedSpanImpl = class {
|
|
19652
|
+
id;
|
|
19653
|
+
traceId;
|
|
19654
|
+
name;
|
|
19655
|
+
type;
|
|
19656
|
+
entityType;
|
|
19657
|
+
entityId;
|
|
19658
|
+
entityName;
|
|
19659
|
+
startTime;
|
|
19660
|
+
endTime;
|
|
19661
|
+
attributes;
|
|
19662
|
+
metadata;
|
|
19663
|
+
tags;
|
|
19664
|
+
input;
|
|
19665
|
+
output;
|
|
19666
|
+
errorInfo;
|
|
19667
|
+
requestContext;
|
|
19668
|
+
isEvent;
|
|
19669
|
+
isRootSpan;
|
|
19670
|
+
parentSpanId;
|
|
19671
|
+
parent;
|
|
19672
|
+
children = [];
|
|
19673
|
+
#raw;
|
|
19674
|
+
#rootSpan;
|
|
19675
|
+
#emitRecordedEvent;
|
|
19676
|
+
#canEmitRecordedEvent;
|
|
19677
|
+
#debugRecordedAnnotationUnavailable;
|
|
19678
|
+
constructor(args) {
|
|
19679
|
+
const { raw, rootSpan, emitRecordedEvent, canEmitRecordedEvent, debugRecordedAnnotationUnavailable } = args;
|
|
19680
|
+
this.#raw = raw;
|
|
19681
|
+
this.#rootSpan = rootSpan;
|
|
19682
|
+
this.#emitRecordedEvent = emitRecordedEvent;
|
|
19683
|
+
this.#canEmitRecordedEvent = canEmitRecordedEvent;
|
|
19684
|
+
this.#debugRecordedAnnotationUnavailable = debugRecordedAnnotationUnavailable;
|
|
19685
|
+
this.id = raw.spanId;
|
|
19686
|
+
this.traceId = raw.traceId;
|
|
19687
|
+
this.name = raw.name;
|
|
19688
|
+
this.type = raw.spanType;
|
|
19689
|
+
this.entityType = raw.entityType ?? void 0;
|
|
19690
|
+
this.entityId = raw.entityId ?? void 0;
|
|
19691
|
+
this.entityName = raw.entityName ?? void 0;
|
|
19692
|
+
this.startTime = raw.startedAt;
|
|
19693
|
+
this.endTime = raw.endedAt ?? void 0;
|
|
19694
|
+
this.attributes = raw.attributes ?? void 0;
|
|
19695
|
+
this.metadata = raw.metadata ?? void 0;
|
|
19696
|
+
this.tags = raw.tags ?? void 0;
|
|
19697
|
+
this.input = raw.input ?? void 0;
|
|
19698
|
+
this.output = raw.output ?? void 0;
|
|
19699
|
+
this.errorInfo = normalizeErrorInfo(raw.error);
|
|
19700
|
+
this.requestContext = raw.requestContext ?? void 0;
|
|
19701
|
+
this.isEvent = raw.isEvent;
|
|
19702
|
+
this.isRootSpan = !raw.parentSpanId;
|
|
19703
|
+
this.parentSpanId = raw.parentSpanId ?? void 0;
|
|
19704
|
+
}
|
|
19705
|
+
async addScore(score) {
|
|
19706
|
+
if (!this.#canEmitRecordedEvent()) {
|
|
19707
|
+
this.#debugRecordedAnnotationUnavailable({ kind: "score", traceId: this.traceId, spanId: this.id });
|
|
19708
|
+
return;
|
|
19709
|
+
}
|
|
19710
|
+
await this.#emitRecordedEvent(
|
|
19711
|
+
buildRecordedScoreEvent({
|
|
19712
|
+
span: this.#raw,
|
|
19713
|
+
rootSpan: this.#rootSpan,
|
|
19714
|
+
parent: this.parent,
|
|
19715
|
+
score,
|
|
19716
|
+
spanId: this.id
|
|
19717
|
+
})
|
|
19718
|
+
);
|
|
19719
|
+
}
|
|
19720
|
+
async addFeedback(feedback) {
|
|
19721
|
+
if (!this.#canEmitRecordedEvent()) {
|
|
19722
|
+
this.#debugRecordedAnnotationUnavailable({ kind: "feedback", traceId: this.traceId, spanId: this.id });
|
|
19723
|
+
return;
|
|
19724
|
+
}
|
|
19725
|
+
await this.#emitRecordedEvent(
|
|
19726
|
+
buildRecordedFeedbackEvent({
|
|
19727
|
+
span: this.#raw,
|
|
19728
|
+
rootSpan: this.#rootSpan,
|
|
19729
|
+
parent: this.parent,
|
|
19730
|
+
feedback,
|
|
19731
|
+
spanId: this.id
|
|
19732
|
+
})
|
|
19733
|
+
);
|
|
19734
|
+
}
|
|
19735
|
+
};
|
|
19736
|
+
var RecordedTraceImpl = class {
|
|
19737
|
+
traceId;
|
|
19738
|
+
rootSpan;
|
|
19739
|
+
spans;
|
|
19740
|
+
#rootRecord;
|
|
19741
|
+
#emitRecordedEvent;
|
|
19742
|
+
#spanMap;
|
|
19743
|
+
#canEmitRecordedEvent;
|
|
19744
|
+
#debugRecordedAnnotationUnavailable;
|
|
19745
|
+
constructor(args) {
|
|
19746
|
+
this.traceId = args.traceId;
|
|
19747
|
+
this.rootSpan = args.rootSpan;
|
|
19748
|
+
this.#rootRecord = args.rootRecord;
|
|
19749
|
+
this.spans = args.spans;
|
|
19750
|
+
this.#emitRecordedEvent = args.emitRecordedEvent;
|
|
19751
|
+
this.#spanMap = new Map(args.spans.map((span) => [span.id, span]));
|
|
19752
|
+
this.#canEmitRecordedEvent = args.canEmitRecordedEvent;
|
|
19753
|
+
this.#debugRecordedAnnotationUnavailable = args.debugRecordedAnnotationUnavailable;
|
|
19754
|
+
}
|
|
19755
|
+
getSpan(spanId) {
|
|
19756
|
+
return this.#spanMap.get(spanId) ?? null;
|
|
19757
|
+
}
|
|
19758
|
+
async addScore(score) {
|
|
19759
|
+
if (!this.#canEmitRecordedEvent()) {
|
|
19760
|
+
this.#debugRecordedAnnotationUnavailable({ kind: "score", traceId: this.traceId });
|
|
19761
|
+
return;
|
|
19762
|
+
}
|
|
19763
|
+
await this.#emitRecordedEvent(
|
|
19764
|
+
buildRecordedScoreEvent({
|
|
19765
|
+
span: this.#rootRecord,
|
|
19766
|
+
rootSpan: this.#rootRecord,
|
|
19767
|
+
score
|
|
19768
|
+
})
|
|
19769
|
+
);
|
|
19770
|
+
}
|
|
19771
|
+
async addFeedback(feedback) {
|
|
19772
|
+
if (!this.#canEmitRecordedEvent()) {
|
|
19773
|
+
this.#debugRecordedAnnotationUnavailable({ kind: "feedback", traceId: this.traceId });
|
|
19774
|
+
return;
|
|
19775
|
+
}
|
|
19776
|
+
await this.#emitRecordedEvent(
|
|
19777
|
+
buildRecordedFeedbackEvent({
|
|
19778
|
+
span: this.#rootRecord,
|
|
19779
|
+
rootSpan: this.#rootRecord,
|
|
19780
|
+
feedback
|
|
19781
|
+
})
|
|
19782
|
+
);
|
|
19783
|
+
}
|
|
19784
|
+
};
|
|
19785
|
+
function findRootSpan(spans) {
|
|
19786
|
+
const spanIds = new Set(spans.map((span) => span.spanId));
|
|
19787
|
+
return spans.find((span) => !span.parentSpanId || !spanIds.has(span.parentSpanId)) ?? spans[0];
|
|
19788
|
+
}
|
|
19789
|
+
function hydrateRecordedTrace(args) {
|
|
19790
|
+
const {
|
|
19791
|
+
trace,
|
|
19792
|
+
emitRecordedEvent,
|
|
19793
|
+
canEmitRecordedEvent = () => true,
|
|
19794
|
+
debugRecordedAnnotationUnavailable = () => {
|
|
19795
|
+
}
|
|
19796
|
+
} = args;
|
|
19797
|
+
const rootSpan = findRootSpan(trace.spans);
|
|
19798
|
+
if (!rootSpan) {
|
|
19799
|
+
return null;
|
|
19800
|
+
}
|
|
19801
|
+
const recordedSpans = trace.spans.map(
|
|
19802
|
+
(raw) => new RecordedSpanImpl({
|
|
19803
|
+
raw,
|
|
19804
|
+
rootSpan,
|
|
19805
|
+
emitRecordedEvent,
|
|
19806
|
+
canEmitRecordedEvent,
|
|
19807
|
+
debugRecordedAnnotationUnavailable
|
|
19808
|
+
})
|
|
19809
|
+
);
|
|
19810
|
+
const spanMap = new Map(recordedSpans.map((span) => [span.id, span]));
|
|
19811
|
+
for (const span of recordedSpans) {
|
|
19812
|
+
if (!span.parentSpanId) continue;
|
|
19813
|
+
const parent = spanMap.get(span.parentSpanId);
|
|
19814
|
+
if (!parent) continue;
|
|
19815
|
+
span.parent = parent;
|
|
19816
|
+
parent.children.push(span);
|
|
19817
|
+
}
|
|
19818
|
+
const hydratedRootSpan = spanMap.get(rootSpan.spanId);
|
|
19819
|
+
if (!hydratedRootSpan) {
|
|
19820
|
+
return null;
|
|
19821
|
+
}
|
|
19822
|
+
return new RecordedTraceImpl({
|
|
19823
|
+
traceId: trace.traceId,
|
|
19824
|
+
rootSpan: hydratedRootSpan,
|
|
19825
|
+
rootRecord: rootSpan,
|
|
19826
|
+
spans: recordedSpans,
|
|
19827
|
+
emitRecordedEvent,
|
|
19828
|
+
canEmitRecordedEvent,
|
|
19829
|
+
debugRecordedAnnotationUnavailable
|
|
19830
|
+
});
|
|
19831
|
+
}
|
|
19832
|
+
|
|
19506
19833
|
// src/registry.ts
|
|
19507
19834
|
var ObservabilityRegistry = class {
|
|
19508
19835
|
#instances = /* @__PURE__ */ new Map();
|
|
@@ -19743,6 +20070,7 @@ function isInstance(obj) {
|
|
|
19743
20070
|
}
|
|
19744
20071
|
var Observability = class extends base.MastraBase {
|
|
19745
20072
|
#registry = new ObservabilityRegistry();
|
|
20073
|
+
#mastra;
|
|
19746
20074
|
constructor(config2) {
|
|
19747
20075
|
super({
|
|
19748
20076
|
component: logger.RegisteredLogger.OBSERVABILITY,
|
|
@@ -19817,6 +20145,7 @@ var Observability = class extends base.MastraBase {
|
|
|
19817
20145
|
setMastraContext(options) {
|
|
19818
20146
|
const instances = this.listInstances();
|
|
19819
20147
|
const { mastra } = options;
|
|
20148
|
+
this.#mastra = mastra;
|
|
19820
20149
|
instances.forEach((instance) => {
|
|
19821
20150
|
const config2 = instance.getConfig();
|
|
19822
20151
|
const exporters = instance.getExporters();
|
|
@@ -19845,6 +20174,60 @@ var Observability = class extends base.MastraBase {
|
|
|
19845
20174
|
getSelectedInstance(options) {
|
|
19846
20175
|
return this.#registry.getSelected(options);
|
|
19847
20176
|
}
|
|
20177
|
+
async getRecordedTrace(args) {
|
|
20178
|
+
const observabilityStorage = await this.#getObservabilityStorage();
|
|
20179
|
+
if (!observabilityStorage) {
|
|
20180
|
+
return null;
|
|
20181
|
+
}
|
|
20182
|
+
const trace = await observabilityStorage.getTrace({ traceId: args.traceId });
|
|
20183
|
+
if (!trace) {
|
|
20184
|
+
return null;
|
|
20185
|
+
}
|
|
20186
|
+
return hydrateRecordedTrace({
|
|
20187
|
+
trace,
|
|
20188
|
+
emitRecordedEvent: (event) => this.#emitRecordedEvent(event),
|
|
20189
|
+
canEmitRecordedEvent: () => !!this.#getRecordedTraceInstance(),
|
|
20190
|
+
debugRecordedAnnotationUnavailable: ({ kind, traceId, spanId }) => {
|
|
20191
|
+
this.logger?.debug(
|
|
20192
|
+
kind === "score" ? "addScore() is unavailable; rehydrate the trace before calling addScore()" : "addFeedback() is unavailable; rehydrate the trace before calling addFeedback()",
|
|
20193
|
+
{
|
|
20194
|
+
traceId,
|
|
20195
|
+
spanId
|
|
20196
|
+
}
|
|
20197
|
+
);
|
|
20198
|
+
}
|
|
20199
|
+
});
|
|
20200
|
+
}
|
|
20201
|
+
async addScore(args) {
|
|
20202
|
+
const trace = await this.#getStoredTrace(args.traceId);
|
|
20203
|
+
if (!trace) {
|
|
20204
|
+
return;
|
|
20205
|
+
}
|
|
20206
|
+
const event = buildRecordedScoreEventFromTrace({
|
|
20207
|
+
trace,
|
|
20208
|
+
spanId: args.spanId,
|
|
20209
|
+
score: args.score
|
|
20210
|
+
});
|
|
20211
|
+
if (!event) {
|
|
20212
|
+
return;
|
|
20213
|
+
}
|
|
20214
|
+
await this.#emitRecordedEvent(event);
|
|
20215
|
+
}
|
|
20216
|
+
async addFeedback(args) {
|
|
20217
|
+
const trace = await this.#getStoredTrace(args.traceId);
|
|
20218
|
+
if (!trace) {
|
|
20219
|
+
return;
|
|
20220
|
+
}
|
|
20221
|
+
const event = buildRecordedFeedbackEventFromTrace({
|
|
20222
|
+
trace,
|
|
20223
|
+
spanId: args.spanId,
|
|
20224
|
+
feedback: args.feedback
|
|
20225
|
+
});
|
|
20226
|
+
if (!event) {
|
|
20227
|
+
return;
|
|
20228
|
+
}
|
|
20229
|
+
await this.#emitRecordedEvent(event);
|
|
20230
|
+
}
|
|
19848
20231
|
/** Register a named observability instance, optionally marking it as default. */
|
|
19849
20232
|
registerInstance(name, instance, isDefault = false) {
|
|
19850
20233
|
this.#registry.register(name, instance, isDefault);
|
|
@@ -19881,6 +20264,45 @@ var Observability = class extends base.MastraBase {
|
|
|
19881
20264
|
async shutdown() {
|
|
19882
20265
|
await this.#registry.shutdown();
|
|
19883
20266
|
}
|
|
20267
|
+
async #getObservabilityStorage() {
|
|
20268
|
+
const storage = this.#mastra?.getStorage();
|
|
20269
|
+
if (!storage) {
|
|
20270
|
+
return null;
|
|
20271
|
+
}
|
|
20272
|
+
return await storage.getStore("observability") ?? null;
|
|
20273
|
+
}
|
|
20274
|
+
async #getStoredTrace(traceId) {
|
|
20275
|
+
const observabilityStorage = await this.#getObservabilityStorage();
|
|
20276
|
+
if (!observabilityStorage) {
|
|
20277
|
+
return null;
|
|
20278
|
+
}
|
|
20279
|
+
return observabilityStorage.getTrace({ traceId });
|
|
20280
|
+
}
|
|
20281
|
+
#getRecordedTraceInstance() {
|
|
20282
|
+
return this.getDefaultInstance() ?? Array.from(this.listInstances().values())[0];
|
|
20283
|
+
}
|
|
20284
|
+
async #emitRecordedEvent(event) {
|
|
20285
|
+
const instance = this.#getRecordedTraceInstance();
|
|
20286
|
+
if (!instance) {
|
|
20287
|
+
this.logger?.debug(
|
|
20288
|
+
event.type === "score" ? "Score event was dropped because no observability instance is registered" : "Feedback event was dropped because no observability instance is registered",
|
|
20289
|
+
{ eventType: event.type }
|
|
20290
|
+
);
|
|
20291
|
+
return;
|
|
20292
|
+
}
|
|
20293
|
+
if (instance instanceof BaseObservabilityInstance) {
|
|
20294
|
+
instance.__emitRecordedEvent(event);
|
|
20295
|
+
return;
|
|
20296
|
+
}
|
|
20297
|
+
const bridge = instance.getBridge();
|
|
20298
|
+
const handlerResults = [
|
|
20299
|
+
...instance.getExporters().map((exporter) => routeToHandler(exporter, event, this.logger)),
|
|
20300
|
+
...bridge ? [routeToHandler(bridge, event, this.logger)] : []
|
|
20301
|
+
].filter((result) => !!result && typeof result.then === "function");
|
|
20302
|
+
if (handlerResults.length > 0) {
|
|
20303
|
+
await Promise.allSettled(handlerResults);
|
|
20304
|
+
}
|
|
20305
|
+
}
|
|
19884
20306
|
};
|
|
19885
20307
|
|
|
19886
20308
|
// src/tracing-options.ts
|