@mastra/observability 0.0.0-span-scorring-test-20251124132129 → 0.0.0-top-level-fix-20251211103030

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.d.ts CHANGED
@@ -11,4 +11,5 @@ export * from './spans/index.js';
11
11
  export * from './exporters/index.js';
12
12
  export * from './span_processors/index.js';
13
13
  export * from './model-tracing.js';
14
+ export * from './tracing-options.js';
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,cAAc,UAAU,CAAC;AAGzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,cAAc,UAAU,CAAC;AAGzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAGhC,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -35,18 +35,38 @@ var observabilityInstanceConfigSchema = z.object({
35
35
  serviceName: z.string().min(1, "Service name is required"),
36
36
  sampling: samplingStrategySchema.optional(),
37
37
  exporters: z.array(z.any()).optional(),
38
+ bridge: z.any().optional(),
38
39
  spanOutputProcessors: z.array(z.any()).optional(),
39
40
  includeInternalSpans: z.boolean().optional(),
40
41
  requestContextKeys: z.array(z.string()).optional()
41
- });
42
+ }).refine(
43
+ (data) => {
44
+ const hasExporters = data.exporters && data.exporters.length > 0;
45
+ const hasBridge = !!data.bridge;
46
+ return hasExporters || hasBridge;
47
+ },
48
+ {
49
+ message: "At least one exporter or a bridge is required"
50
+ }
51
+ );
42
52
  var observabilityConfigValueSchema = z.object({
43
53
  serviceName: z.string().min(1, "Service name is required"),
44
54
  sampling: samplingStrategySchema.optional(),
45
55
  exporters: z.array(z.any()).optional(),
56
+ bridge: z.any().optional(),
46
57
  spanOutputProcessors: z.array(z.any()).optional(),
47
58
  includeInternalSpans: z.boolean().optional(),
48
59
  requestContextKeys: z.array(z.string()).optional()
49
- });
60
+ }).refine(
61
+ (data) => {
62
+ const hasExporters = data.exporters && data.exporters.length > 0;
63
+ const hasBridge = !!data.bridge;
64
+ return hasExporters || hasBridge;
65
+ },
66
+ {
67
+ message: "At least one exporter or a bridge is required"
68
+ }
69
+ );
50
70
  var observabilityRegistryConfigSchema = z.object({
51
71
  default: z.object({
52
72
  enabled: z.boolean().optional()
@@ -73,6 +93,18 @@ var observabilityRegistryConfigSchema = z.object({
73
93
  {
74
94
  message: 'A "configSelector" function is required when multiple configs are specified to determine which config to use.'
75
95
  }
96
+ ).refine(
97
+ (data) => {
98
+ if (data.configSelector) {
99
+ const isDefaultEnabled = data.default?.enabled === true;
100
+ const hasConfigs = data.configs && typeof data.configs === "object" && !Array.isArray(data.configs) ? Object.keys(data.configs).length > 0 : false;
101
+ return isDefaultEnabled || hasConfigs;
102
+ }
103
+ return true;
104
+ },
105
+ {
106
+ message: 'A "configSelector" requires at least one config or default observability to be configured.'
107
+ }
76
108
  );
77
109
  var BaseExporter = class {
78
110
  /** Mastra logger instance */
@@ -893,6 +925,79 @@ var DefaultExporter = class extends BaseExporter {
893
925
  this.logger.info("DefaultExporter shutdown complete");
894
926
  }
895
927
  };
928
+
929
+ // src/exporters/test.ts
930
+ var TestExporter = class extends BaseExporter {
931
+ name = "tracing-test-exporter";
932
+ #events = [];
933
+ constructor(config = {}) {
934
+ super(config);
935
+ }
936
+ async _exportTracingEvent(event) {
937
+ this.#events.push(event);
938
+ }
939
+ clearEvents() {
940
+ this.#events = [];
941
+ }
942
+ get events() {
943
+ return this.#events;
944
+ }
945
+ async shutdown() {
946
+ this.logger.info("TestExporter shutdown");
947
+ }
948
+ };
949
+
950
+ // src/usage.ts
951
+ function extractUsageMetrics(usage, providerMetadata) {
952
+ if (!usage) {
953
+ return {};
954
+ }
955
+ const inputDetails = {};
956
+ const outputDetails = {};
957
+ let inputTokens = usage.inputTokens;
958
+ const outputTokens = usage.outputTokens;
959
+ if (usage.cachedInputTokens) {
960
+ inputDetails.cacheRead = usage.cachedInputTokens;
961
+ }
962
+ if (usage.reasoningTokens) {
963
+ outputDetails.reasoning = usage.reasoningTokens;
964
+ }
965
+ const anthropic = providerMetadata?.anthropic;
966
+ if (anthropic) {
967
+ if (anthropic.cacheReadInputTokens) {
968
+ inputDetails.cacheRead = anthropic.cacheReadInputTokens;
969
+ }
970
+ if (anthropic.cacheCreationInputTokens) {
971
+ inputDetails.cacheWrite = anthropic.cacheCreationInputTokens;
972
+ }
973
+ if (anthropic.cacheReadInputTokens || anthropic.cacheCreationInputTokens) {
974
+ inputDetails.text = usage.inputTokens;
975
+ inputTokens = (usage.inputTokens ?? 0) + (anthropic.cacheReadInputTokens ?? 0) + (anthropic.cacheCreationInputTokens ?? 0);
976
+ }
977
+ }
978
+ const google = providerMetadata?.google;
979
+ if (google?.usageMetadata) {
980
+ if (google.usageMetadata.cachedContentTokenCount) {
981
+ inputDetails.cacheRead = google.usageMetadata.cachedContentTokenCount;
982
+ }
983
+ if (google.usageMetadata.thoughtsTokenCount) {
984
+ outputDetails.reasoning = google.usageMetadata.thoughtsTokenCount;
985
+ }
986
+ }
987
+ const result = {
988
+ inputTokens,
989
+ outputTokens
990
+ };
991
+ if (Object.keys(inputDetails).length > 0) {
992
+ result.inputDetails = inputDetails;
993
+ }
994
+ if (Object.keys(outputDetails).length > 0) {
995
+ result.outputDetails = outputDetails;
996
+ }
997
+ return result;
998
+ }
999
+
1000
+ // src/model-tracing.ts
896
1001
  var ModelSpanTracker = class {
897
1002
  #modelSpan;
898
1003
  #currentStepSpan;
@@ -900,9 +1005,23 @@ var ModelSpanTracker = class {
900
1005
  #accumulator = {};
901
1006
  #stepIndex = 0;
902
1007
  #chunkSequence = 0;
1008
+ #completionStartTime;
1009
+ /** Tracks tool output accumulators by toolCallId for consolidating sub-agent streams */
1010
+ #toolOutputAccumulators = /* @__PURE__ */ new Map();
1011
+ /** Tracks toolCallIds that had streaming output (to skip redundant tool-result spans) */
1012
+ #streamedToolCallIds = /* @__PURE__ */ new Set();
903
1013
  constructor(modelSpan) {
904
1014
  this.#modelSpan = modelSpan;
905
1015
  }
1016
+ /**
1017
+ * Capture the completion start time (time to first token) when the first content chunk arrives.
1018
+ */
1019
+ #captureCompletionStartTime() {
1020
+ if (this.#completionStartTime) {
1021
+ return;
1022
+ }
1023
+ this.#completionStartTime = /* @__PURE__ */ new Date();
1024
+ }
906
1025
  /**
907
1026
  * Get the tracing context for creating child spans.
908
1027
  * Returns the current step span if active, otherwise the model span.
@@ -919,10 +1038,16 @@ var ModelSpanTracker = class {
919
1038
  this.#modelSpan?.error(options);
920
1039
  }
921
1040
  /**
922
- * End the generation span
1041
+ * End the generation span with optional raw usage data.
1042
+ * If usage is provided, it will be converted to UsageStats with cache token details.
923
1043
  */
924
1044
  endGeneration(options) {
925
- this.#modelSpan?.end(options);
1045
+ const { usage, providerMetadata, ...spanOptions } = options ?? {};
1046
+ if (spanOptions.attributes) {
1047
+ spanOptions.attributes.completionStartTime = this.#completionStartTime;
1048
+ spanOptions.attributes.usage = extractUsageMetrics(usage, providerMetadata);
1049
+ }
1050
+ this.#modelSpan?.end(spanOptions);
926
1051
  }
927
1052
  /**
928
1053
  * Update the generation span
@@ -952,9 +1077,10 @@ var ModelSpanTracker = class {
952
1077
  #endStepSpan(payload) {
953
1078
  if (!this.#currentStepSpan) return;
954
1079
  const output = payload.output;
955
- const { usage, ...otherOutput } = output;
1080
+ const { usage: rawUsage, ...otherOutput } = output;
956
1081
  const stepResult = payload.stepResult;
957
1082
  const metadata = payload.metadata;
1083
+ const usage = extractUsageMetrics(rawUsage, metadata?.providerMetadata);
958
1084
  const cleanMetadata = metadata ? { ...metadata } : void 0;
959
1085
  if (cleanMetadata?.request) {
960
1086
  delete cleanMetadata.request;
@@ -1127,6 +1253,77 @@ var ModelSpanTracker = class {
1127
1253
  break;
1128
1254
  }
1129
1255
  }
1256
+ /**
1257
+ * Handle tool-output chunks from sub-agents.
1258
+ * Consolidates streaming text/reasoning deltas into a single span per tool call.
1259
+ */
1260
+ #handleToolOutputChunk(chunk) {
1261
+ if (chunk.type !== "tool-output") return;
1262
+ const payload = chunk.payload;
1263
+ const { output, toolCallId, toolName } = payload;
1264
+ let acc = this.#toolOutputAccumulators.get(toolCallId);
1265
+ if (!acc) {
1266
+ if (!this.#currentStepSpan) {
1267
+ this.#startStepSpan();
1268
+ }
1269
+ acc = {
1270
+ toolName: toolName || "unknown",
1271
+ toolCallId,
1272
+ text: "",
1273
+ reasoning: "",
1274
+ sequenceNumber: this.#chunkSequence++,
1275
+ // Name the span 'tool-result' for consistency (tool-call → tool-result)
1276
+ span: this.#currentStepSpan?.createChildSpan({
1277
+ name: `chunk: 'tool-result'`,
1278
+ type: SpanType.MODEL_CHUNK,
1279
+ attributes: {
1280
+ chunkType: "tool-result",
1281
+ sequenceNumber: this.#chunkSequence - 1
1282
+ }
1283
+ })
1284
+ };
1285
+ this.#toolOutputAccumulators.set(toolCallId, acc);
1286
+ }
1287
+ if (output && typeof output === "object" && "type" in output) {
1288
+ const innerType = output.type;
1289
+ switch (innerType) {
1290
+ case "text-delta":
1291
+ if (output.payload?.text) {
1292
+ acc.text += output.payload.text;
1293
+ }
1294
+ break;
1295
+ case "reasoning-delta":
1296
+ if (output.payload?.text) {
1297
+ acc.reasoning += output.payload.text;
1298
+ }
1299
+ break;
1300
+ case "finish":
1301
+ case "workflow-finish":
1302
+ this.#endToolOutputSpan(toolCallId);
1303
+ break;
1304
+ }
1305
+ }
1306
+ }
1307
+ /**
1308
+ * End a tool output span and clean up the accumulator
1309
+ */
1310
+ #endToolOutputSpan(toolCallId) {
1311
+ const acc = this.#toolOutputAccumulators.get(toolCallId);
1312
+ if (!acc) return;
1313
+ const output = {
1314
+ toolCallId: acc.toolCallId,
1315
+ toolName: acc.toolName
1316
+ };
1317
+ if (acc.text) {
1318
+ output.text = acc.text;
1319
+ }
1320
+ if (acc.reasoning) {
1321
+ output.reasoning = acc.reasoning;
1322
+ }
1323
+ acc.span?.end({ output });
1324
+ this.#toolOutputAccumulators.delete(toolCallId);
1325
+ this.#streamedToolCallIds.add(toolCallId);
1326
+ }
1130
1327
  /**
1131
1328
  * Wraps a stream with model tracing transform to track MODEL_STEP and MODEL_CHUNK spans.
1132
1329
  *
@@ -1137,6 +1334,13 @@ var ModelSpanTracker = class {
1137
1334
  return stream.pipeThrough(
1138
1335
  new TransformStream({
1139
1336
  transform: (chunk, controller) => {
1337
+ switch (chunk.type) {
1338
+ case "text-delta":
1339
+ case "tool-call-delta":
1340
+ case "reasoning-delta":
1341
+ this.#captureCompletionStartTime();
1342
+ break;
1343
+ }
1140
1344
  controller.enqueue(chunk);
1141
1345
  switch (chunk.type) {
1142
1346
  case "text-start":
@@ -1170,6 +1374,19 @@ var ModelSpanTracker = class {
1170
1374
  case "start":
1171
1375
  case "finish":
1172
1376
  break;
1377
+ case "tool-output":
1378
+ this.#handleToolOutputChunk(chunk);
1379
+ break;
1380
+ case "tool-result": {
1381
+ const toolCallId = chunk.payload?.toolCallId;
1382
+ if (toolCallId && this.#streamedToolCallIds.has(toolCallId)) {
1383
+ this.#streamedToolCallIds.delete(toolCallId);
1384
+ break;
1385
+ }
1386
+ const { args, ...cleanPayload } = chunk.payload || {};
1387
+ this.#createEventSpan(chunk.type, cleanPayload);
1388
+ break;
1389
+ }
1173
1390
  // Default: auto-create event span for all other chunk types
1174
1391
  default: {
1175
1392
  let outputPayload = chunk.payload;
@@ -1224,6 +1441,16 @@ function isSpanInternal(spanType, flags) {
1224
1441
  return false;
1225
1442
  }
1226
1443
  }
1444
+ function getExternalParentId(options) {
1445
+ if (!options.parent) {
1446
+ return void 0;
1447
+ }
1448
+ if (options.parent.isInternal) {
1449
+ return options.parent.getParentSpanId(false);
1450
+ } else {
1451
+ return options.parent.id;
1452
+ }
1453
+ }
1227
1454
  var BaseSpan = class {
1228
1455
  name;
1229
1456
  type;
@@ -1238,6 +1465,7 @@ var BaseSpan = class {
1238
1465
  output;
1239
1466
  errorInfo;
1240
1467
  metadata;
1468
+ tags;
1241
1469
  traceState;
1242
1470
  /** Parent span ID (for root spans that are children of external spans) */
1243
1471
  parentSpanId;
@@ -1252,6 +1480,7 @@ var BaseSpan = class {
1252
1480
  this.isEvent = options.isEvent ?? false;
1253
1481
  this.isInternal = isSpanInternal(this.type, options.tracingPolicy?.internal);
1254
1482
  this.traceState = options.traceState;
1483
+ this.tags = !options.parent && options.tags?.length ? options.tags : void 0;
1255
1484
  if (this.isEvent) {
1256
1485
  this.output = deepClean(options.output);
1257
1486
  } else {
@@ -1314,12 +1543,36 @@ var BaseSpan = class {
1314
1543
  errorInfo: this.errorInfo,
1315
1544
  isEvent: this.isEvent,
1316
1545
  isRootSpan: this.isRootSpan,
1317
- parentSpanId: this.getParentSpanId(includeInternalSpans)
1546
+ parentSpanId: this.getParentSpanId(includeInternalSpans),
1547
+ // Tags are only included for root spans
1548
+ ...this.isRootSpan && this.tags?.length ? { tags: this.tags } : {}
1318
1549
  };
1319
1550
  }
1320
1551
  get externalTraceId() {
1321
1552
  return this.isValid ? this.traceId : void 0;
1322
1553
  }
1554
+ /**
1555
+ * Execute an async function within this span's tracing context.
1556
+ * Delegates to the bridge if available.
1557
+ */
1558
+ async executeInContext(fn) {
1559
+ const bridge = this.observabilityInstance.getBridge();
1560
+ if (bridge?.executeInContext) {
1561
+ return bridge.executeInContext(this.id, fn);
1562
+ }
1563
+ return fn();
1564
+ }
1565
+ /**
1566
+ * Execute a synchronous function within this span's tracing context.
1567
+ * Delegates to the bridge if available.
1568
+ */
1569
+ executeInContextSync(fn) {
1570
+ const bridge = this.observabilityInstance.getBridge();
1571
+ if (bridge?.executeInContextSync) {
1572
+ return bridge.executeInContextSync(this.id, fn);
1573
+ }
1574
+ return fn();
1575
+ }
1323
1576
  };
1324
1577
  var DEFAULT_KEYS_TO_STRIP = /* @__PURE__ */ new Set([
1325
1578
  "logger",
@@ -1345,6 +1598,9 @@ function deepClean(value, options = {}, _seen = /* @__PURE__ */ new WeakSet(), _
1345
1598
  return "[Circular]";
1346
1599
  }
1347
1600
  _seen.add(value);
1601
+ if (value instanceof Date) {
1602
+ return value;
1603
+ }
1348
1604
  if (Array.isArray(value)) {
1349
1605
  return value.map((item) => deepClean(item, options, _seen, _depth + 1));
1350
1606
  }
@@ -1366,27 +1622,30 @@ var DefaultSpan = class extends BaseSpan {
1366
1622
  traceId;
1367
1623
  constructor(options, observabilityInstance) {
1368
1624
  super(options, observabilityInstance);
1369
- this.id = generateSpanId();
1625
+ const bridge = observabilityInstance.getBridge();
1626
+ if (bridge && !this.isInternal) {
1627
+ const bridgeIds = bridge.createSpan(options);
1628
+ if (bridgeIds) {
1629
+ this.id = bridgeIds.spanId;
1630
+ this.traceId = bridgeIds.traceId;
1631
+ this.parentSpanId = bridgeIds.parentSpanId;
1632
+ return;
1633
+ }
1634
+ }
1370
1635
  if (options.parent) {
1371
1636
  this.traceId = options.parent.traceId;
1372
- } else if (options.traceId) {
1373
- if (isValidTraceId(options.traceId)) {
1374
- this.traceId = options.traceId;
1375
- } else {
1376
- console.error(
1377
- `[Mastra Tracing] Invalid traceId: must be 1-32 hexadecimal characters, got "${options.traceId}". Generating new trace ID.`
1378
- );
1379
- this.traceId = generateTraceId();
1380
- }
1381
- } else {
1382
- this.traceId = generateTraceId();
1637
+ this.parentSpanId = options.parent.id;
1638
+ this.id = generateSpanId();
1639
+ return;
1383
1640
  }
1384
- if (!options.parent && options.parentSpanId) {
1641
+ this.traceId = getOrCreateTraceId(options);
1642
+ this.id = generateSpanId();
1643
+ if (options.parentSpanId) {
1385
1644
  if (isValidSpanId(options.parentSpanId)) {
1386
1645
  this.parentSpanId = options.parentSpanId;
1387
1646
  } else {
1388
1647
  console.error(
1389
- `[Mastra Tracing] Invalid parentSpanId: must be 1-16 hexadecimal characters, got "${options.parentSpanId}". Ignoring parent span ID.`
1648
+ `[Mastra Tracing] Invalid parentSpanId: must be 1-16 hexadecimal characters, got "${options.parentSpanId}". Ignoring.`
1390
1649
  );
1391
1650
  }
1392
1651
  }
@@ -1491,6 +1750,18 @@ function isValidTraceId(traceId) {
1491
1750
  function isValidSpanId(spanId) {
1492
1751
  return /^[0-9a-f]{1,16}$/i.test(spanId);
1493
1752
  }
1753
+ function getOrCreateTraceId(options) {
1754
+ if (options.traceId) {
1755
+ if (isValidTraceId(options.traceId)) {
1756
+ return options.traceId;
1757
+ } else {
1758
+ console.error(
1759
+ `[Mastra Tracing] Invalid traceId: must be 1-32 hexadecimal characters, got "${options.traceId}". Generating new trace ID.`
1760
+ );
1761
+ }
1762
+ }
1763
+ return generateTraceId();
1764
+ }
1494
1765
 
1495
1766
  // src/spans/no-op.ts
1496
1767
  var NoOpSpan = class extends BaseSpan {
@@ -1523,13 +1794,17 @@ var BaseObservabilityInstance = class extends MastraBase {
1523
1794
  sampling: config.sampling ?? { type: "always" /* ALWAYS */ },
1524
1795
  exporters: config.exporters ?? [],
1525
1796
  spanOutputProcessors: config.spanOutputProcessors ?? [],
1797
+ bridge: config.bridge ?? void 0,
1526
1798
  includeInternalSpans: config.includeInternalSpans ?? false,
1527
1799
  requestContextKeys: config.requestContextKeys ?? []
1528
1800
  };
1801
+ if (this.config.bridge?.init) {
1802
+ this.config.bridge.init({ config: this.config });
1803
+ }
1529
1804
  }
1530
1805
  /**
1531
1806
  * Override setLogger to add Observability specific initialization log
1532
- * and propagate logger to exporters
1807
+ * and propagate logger to exporters and bridge
1533
1808
  */
1534
1809
  __setLogger(logger) {
1535
1810
  super.__setLogger(logger);
@@ -1538,8 +1813,11 @@ var BaseObservabilityInstance = class extends MastraBase {
1538
1813
  exporter.__setLogger(logger);
1539
1814
  }
1540
1815
  });
1816
+ if (this.config.bridge?.__setLogger) {
1817
+ this.config.bridge.__setLogger(logger);
1818
+ }
1541
1819
  this.logger.debug(
1542
- `[Observability] Initialized [service=${this.config.serviceName}] [instance=${this.config.name}] [sampling=${this.config.sampling.type}]`
1820
+ `[Observability] Initialized [service=${this.config.serviceName}] [instance=${this.config.name}] [sampling=${this.config.sampling?.type}] [bridge=${!!this.config.bridge}]`
1543
1821
  );
1544
1822
  }
1545
1823
  // ============================================================================
@@ -1568,11 +1846,15 @@ var BaseObservabilityInstance = class extends MastraBase {
1568
1846
  } else {
1569
1847
  traceState = this.computeTraceState(tracingOptions);
1570
1848
  }
1571
- const enrichedMetadata = this.extractMetadataFromRequestContext(requestContext, metadata, traceState);
1849
+ const tracingMetadata = !options.parent ? tracingOptions?.metadata : void 0;
1850
+ const mergedMetadata = metadata || tracingMetadata ? { ...metadata, ...tracingMetadata } : void 0;
1851
+ const enrichedMetadata = this.extractMetadataFromRequestContext(requestContext, mergedMetadata, traceState);
1852
+ const tags = !options.parent ? tracingOptions?.tags : void 0;
1572
1853
  const span = this.createSpan({
1573
1854
  ...rest,
1574
1855
  metadata: enrichedMetadata,
1575
- traceState
1856
+ traceState,
1857
+ tags
1576
1858
  });
1577
1859
  if (span.isEvent) {
1578
1860
  this.emitSpanEnded(span);
@@ -1606,6 +1888,12 @@ var BaseObservabilityInstance = class extends MastraBase {
1606
1888
  getSpanOutputProcessors() {
1607
1889
  return [...this.spanOutputProcessors];
1608
1890
  }
1891
+ /**
1892
+ * Get the bridge instance if configured
1893
+ */
1894
+ getBridge() {
1895
+ return this.config.bridge;
1896
+ }
1609
1897
  /**
1610
1898
  * Get the logger instance (for exporters and other components)
1611
1899
  */
@@ -1650,7 +1938,9 @@ var BaseObservabilityInstance = class extends MastraBase {
1650
1938
  */
1651
1939
  shouldSample(options) {
1652
1940
  const { sampling } = this.config;
1653
- switch (sampling.type) {
1941
+ switch (sampling?.type) {
1942
+ case void 0:
1943
+ return true;
1654
1944
  case "always" /* ALWAYS */:
1655
1945
  return true;
1656
1946
  case "never" /* NEVER */:
@@ -1782,17 +2072,21 @@ var BaseObservabilityInstance = class extends MastraBase {
1782
2072
  }
1783
2073
  }
1784
2074
  /**
1785
- * Export tracing event through all exporters (realtime mode)
2075
+ * Export tracing event through all exporters and bridge (realtime mode)
1786
2076
  */
1787
2077
  async exportTracingEvent(event) {
1788
- const exportPromises = this.exporters.map(async (exporter) => {
2078
+ const targets = [
2079
+ ...this.exporters
2080
+ ];
2081
+ if (this.config.bridge) {
2082
+ targets.push(this.config.bridge);
2083
+ }
2084
+ const exportPromises = targets.map(async (target) => {
1789
2085
  try {
1790
- if (exporter.exportTracingEvent) {
1791
- await exporter.exportTracingEvent(event);
1792
- this.logger.debug(`[Observability] Event exported [exporter=${exporter.name}] [type=${event.type}]`);
1793
- }
2086
+ await target.exportTracingEvent(event);
2087
+ this.logger.debug(`[Observability] Event exported [target=${target.name}] [type=${event.type}]`);
1794
2088
  } catch (error) {
1795
- this.logger.error(`[Observability] Export error [exporter=${exporter.name}]`, error);
2089
+ this.logger.error(`[Observability] Export error [target=${target.name}]`, error);
1796
2090
  }
1797
2091
  });
1798
2092
  await Promise.allSettled(exportPromises);
@@ -1816,6 +2110,9 @@ var BaseObservabilityInstance = class extends MastraBase {
1816
2110
  ...this.exporters.map((e) => e.shutdown()),
1817
2111
  ...this.spanOutputProcessors.map((p) => p.shutdown())
1818
2112
  ];
2113
+ if (this.config.bridge) {
2114
+ shutdownPromises.push(this.config.bridge.shutdown());
2115
+ }
1819
2116
  await Promise.allSettled(shutdownPromises);
1820
2117
  this.logger.info(`[Observability] Shutdown completed [name=${this.name}]`);
1821
2118
  }
@@ -1962,9 +2259,16 @@ var SensitiveDataFilter = class {
1962
2259
  /**
1963
2260
  * Recursively filter objects/arrays for sensitive keys.
1964
2261
  * Handles circular references by replacing with a marker.
2262
+ * Also attempts to parse and redact JSON strings.
1965
2263
  */
1966
2264
  deepFilter(obj, seen = /* @__PURE__ */ new WeakSet()) {
1967
2265
  if (obj === null || typeof obj !== "object") {
2266
+ if (typeof obj === "string") {
2267
+ const trimmed = obj.trim();
2268
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
2269
+ return this.redactJsonString(obj);
2270
+ }
2271
+ }
1968
2272
  return obj;
1969
2273
  }
1970
2274
  if (seen.has(obj)) {
@@ -2017,6 +2321,22 @@ var SensitiveDataFilter = class {
2017
2321
  return normalizedKey === sensitiveField;
2018
2322
  });
2019
2323
  }
2324
+ /**
2325
+ * Attempt to parse a string as JSON and redact sensitive fields within it.
2326
+ * If parsing fails or no sensitive data is found, returns the original string.
2327
+ */
2328
+ redactJsonString(str) {
2329
+ try {
2330
+ const parsed = JSON.parse(str);
2331
+ if (parsed && typeof parsed === "object") {
2332
+ const filtered = this.deepFilter(parsed, /* @__PURE__ */ new WeakSet());
2333
+ return JSON.stringify(filtered);
2334
+ }
2335
+ return str;
2336
+ } catch {
2337
+ return str;
2338
+ }
2339
+ }
2020
2340
  /**
2021
2341
  * Redact a sensitive value.
2022
2342
  * - Full style: replaces with a fixed token.
@@ -2169,6 +2489,11 @@ var Observability = class extends MastraBase {
2169
2489
  }
2170
2490
  };
2171
2491
 
2172
- export { BaseExporter, BaseObservabilityInstance, BaseSpan, CloudExporter, ConsoleExporter, DefaultExporter, DefaultObservabilityInstance, DefaultSpan, ModelSpanTracker, NoOpSpan, Observability, SamplingStrategyType, SensitiveDataFilter, deepClean, observabilityConfigValueSchema, observabilityInstanceConfigSchema, observabilityRegistryConfigSchema, samplingStrategySchema };
2492
+ // src/tracing-options.ts
2493
+ function buildTracingOptions(...updaters) {
2494
+ return updaters.reduce((opts, updater) => updater(opts), {});
2495
+ }
2496
+
2497
+ export { BaseExporter, BaseObservabilityInstance, BaseSpan, CloudExporter, ConsoleExporter, DefaultExporter, DefaultObservabilityInstance, DefaultSpan, ModelSpanTracker, NoOpSpan, Observability, SamplingStrategyType, SensitiveDataFilter, TestExporter, buildTracingOptions, deepClean, getExternalParentId, observabilityConfigValueSchema, observabilityInstanceConfigSchema, observabilityRegistryConfigSchema, samplingStrategySchema };
2173
2498
  //# sourceMappingURL=index.js.map
2174
2499
  //# sourceMappingURL=index.js.map