@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/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.correlationContext?.traceId;
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.correlationContext?.traceId === traceId).map((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.correlationContext?.traceId) traceIds.add(event.log.correlationContext.traceId);
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.correlationContext?.traceId === traceId).map((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
- correlationContext: config2.correlationContext ? { ...config2.correlationContext } : void 0,
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