@mastra/observability 1.0.0-beta.1 → 1.0.0-beta.3

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
@@ -37,18 +37,38 @@ var observabilityInstanceConfigSchema = zod.z.object({
37
37
  serviceName: zod.z.string().min(1, "Service name is required"),
38
38
  sampling: samplingStrategySchema.optional(),
39
39
  exporters: zod.z.array(zod.z.any()).optional(),
40
+ bridge: zod.z.any().optional(),
40
41
  spanOutputProcessors: zod.z.array(zod.z.any()).optional(),
41
42
  includeInternalSpans: zod.z.boolean().optional(),
42
43
  requestContextKeys: zod.z.array(zod.z.string()).optional()
43
- });
44
+ }).refine(
45
+ (data) => {
46
+ const hasExporters = data.exporters && data.exporters.length > 0;
47
+ const hasBridge = !!data.bridge;
48
+ return hasExporters || hasBridge;
49
+ },
50
+ {
51
+ message: "At least one exporter or a bridge is required"
52
+ }
53
+ );
44
54
  var observabilityConfigValueSchema = zod.z.object({
45
55
  serviceName: zod.z.string().min(1, "Service name is required"),
46
56
  sampling: samplingStrategySchema.optional(),
47
57
  exporters: zod.z.array(zod.z.any()).optional(),
58
+ bridge: zod.z.any().optional(),
48
59
  spanOutputProcessors: zod.z.array(zod.z.any()).optional(),
49
60
  includeInternalSpans: zod.z.boolean().optional(),
50
61
  requestContextKeys: zod.z.array(zod.z.string()).optional()
51
- });
62
+ }).refine(
63
+ (data) => {
64
+ const hasExporters = data.exporters && data.exporters.length > 0;
65
+ const hasBridge = !!data.bridge;
66
+ return hasExporters || hasBridge;
67
+ },
68
+ {
69
+ message: "At least one exporter or a bridge is required"
70
+ }
71
+ );
52
72
  var observabilityRegistryConfigSchema = zod.z.object({
53
73
  default: zod.z.object({
54
74
  enabled: zod.z.boolean().optional()
@@ -75,6 +95,18 @@ var observabilityRegistryConfigSchema = zod.z.object({
75
95
  {
76
96
  message: 'A "configSelector" function is required when multiple configs are specified to determine which config to use.'
77
97
  }
98
+ ).refine(
99
+ (data) => {
100
+ if (data.configSelector) {
101
+ const isDefaultEnabled = data.default?.enabled === true;
102
+ const hasConfigs = data.configs && typeof data.configs === "object" && !Array.isArray(data.configs) ? Object.keys(data.configs).length > 0 : false;
103
+ return isDefaultEnabled || hasConfigs;
104
+ }
105
+ return true;
106
+ },
107
+ {
108
+ message: 'A "configSelector" requires at least one config or default observability to be configured.'
109
+ }
78
110
  );
79
111
  var BaseExporter = class {
80
112
  /** Mastra logger instance */
@@ -895,6 +927,27 @@ var DefaultExporter = class extends BaseExporter {
895
927
  this.logger.info("DefaultExporter shutdown complete");
896
928
  }
897
929
  };
930
+
931
+ // src/exporters/test.ts
932
+ var TestExporter = class extends BaseExporter {
933
+ name = "tracing-test-exporter";
934
+ #events = [];
935
+ constructor(config = {}) {
936
+ super(config);
937
+ }
938
+ async _exportTracingEvent(event) {
939
+ this.#events.push(event);
940
+ }
941
+ clearEvents() {
942
+ this.#events = [];
943
+ }
944
+ get events() {
945
+ return this.#events;
946
+ }
947
+ async shutdown() {
948
+ this.logger.info("TestExporter shutdown");
949
+ }
950
+ };
898
951
  var ModelSpanTracker = class {
899
952
  #modelSpan;
900
953
  #currentStepSpan;
@@ -902,9 +955,30 @@ var ModelSpanTracker = class {
902
955
  #accumulator = {};
903
956
  #stepIndex = 0;
904
957
  #chunkSequence = 0;
958
+ /** Tracks whether completionStartTime has been captured for this generation */
959
+ #completionStartTimeCaptured = false;
960
+ /** Tracks tool output accumulators by toolCallId for consolidating sub-agent streams */
961
+ #toolOutputAccumulators = /* @__PURE__ */ new Map();
962
+ /** Tracks toolCallIds that had streaming output (to skip redundant tool-result spans) */
963
+ #streamedToolCallIds = /* @__PURE__ */ new Set();
905
964
  constructor(modelSpan) {
906
965
  this.#modelSpan = modelSpan;
907
966
  }
967
+ /**
968
+ * Capture the completion start time (time to first token) when the first content chunk arrives.
969
+ * This is used by observability providers like Langfuse to calculate TTFT metrics.
970
+ */
971
+ #captureCompletionStartTime() {
972
+ if (this.#completionStartTimeCaptured || !this.#modelSpan) {
973
+ return;
974
+ }
975
+ this.#completionStartTimeCaptured = true;
976
+ this.#modelSpan.update({
977
+ attributes: {
978
+ completionStartTime: /* @__PURE__ */ new Date()
979
+ }
980
+ });
981
+ }
908
982
  /**
909
983
  * Get the tracing context for creating child spans.
910
984
  * Returns the current step span if active, otherwise the model span.
@@ -1129,6 +1203,77 @@ var ModelSpanTracker = class {
1129
1203
  break;
1130
1204
  }
1131
1205
  }
1206
+ /**
1207
+ * Handle tool-output chunks from sub-agents.
1208
+ * Consolidates streaming text/reasoning deltas into a single span per tool call.
1209
+ */
1210
+ #handleToolOutputChunk(chunk) {
1211
+ if (chunk.type !== "tool-output") return;
1212
+ const payload = chunk.payload;
1213
+ const { output, toolCallId, toolName } = payload;
1214
+ let acc = this.#toolOutputAccumulators.get(toolCallId);
1215
+ if (!acc) {
1216
+ if (!this.#currentStepSpan) {
1217
+ this.#startStepSpan();
1218
+ }
1219
+ acc = {
1220
+ toolName: toolName || "unknown",
1221
+ toolCallId,
1222
+ text: "",
1223
+ reasoning: "",
1224
+ sequenceNumber: this.#chunkSequence++,
1225
+ // Name the span 'tool-result' for consistency (tool-call → tool-result)
1226
+ span: this.#currentStepSpan?.createChildSpan({
1227
+ name: `chunk: 'tool-result'`,
1228
+ type: observability.SpanType.MODEL_CHUNK,
1229
+ attributes: {
1230
+ chunkType: "tool-result",
1231
+ sequenceNumber: this.#chunkSequence - 1
1232
+ }
1233
+ })
1234
+ };
1235
+ this.#toolOutputAccumulators.set(toolCallId, acc);
1236
+ }
1237
+ if (output && typeof output === "object" && "type" in output) {
1238
+ const innerType = output.type;
1239
+ switch (innerType) {
1240
+ case "text-delta":
1241
+ if (output.payload?.text) {
1242
+ acc.text += output.payload.text;
1243
+ }
1244
+ break;
1245
+ case "reasoning-delta":
1246
+ if (output.payload?.text) {
1247
+ acc.reasoning += output.payload.text;
1248
+ }
1249
+ break;
1250
+ case "finish":
1251
+ case "workflow-finish":
1252
+ this.#endToolOutputSpan(toolCallId);
1253
+ break;
1254
+ }
1255
+ }
1256
+ }
1257
+ /**
1258
+ * End a tool output span and clean up the accumulator
1259
+ */
1260
+ #endToolOutputSpan(toolCallId) {
1261
+ const acc = this.#toolOutputAccumulators.get(toolCallId);
1262
+ if (!acc) return;
1263
+ const output = {
1264
+ toolCallId: acc.toolCallId,
1265
+ toolName: acc.toolName
1266
+ };
1267
+ if (acc.text) {
1268
+ output.text = acc.text;
1269
+ }
1270
+ if (acc.reasoning) {
1271
+ output.reasoning = acc.reasoning;
1272
+ }
1273
+ acc.span?.end({ output });
1274
+ this.#toolOutputAccumulators.delete(toolCallId);
1275
+ this.#streamedToolCallIds.add(toolCallId);
1276
+ }
1132
1277
  /**
1133
1278
  * Wraps a stream with model tracing transform to track MODEL_STEP and MODEL_CHUNK spans.
1134
1279
  *
@@ -1136,9 +1281,14 @@ var ModelSpanTracker = class {
1136
1281
  * create MODEL_STEP and MODEL_CHUNK spans for each semantic unit in the stream.
1137
1282
  */
1138
1283
  wrapStream(stream) {
1284
+ let captureCompletionStartTime = false;
1139
1285
  return stream.pipeThrough(
1140
1286
  new web.TransformStream({
1141
1287
  transform: (chunk, controller) => {
1288
+ if (!captureCompletionStartTime) {
1289
+ captureCompletionStartTime = true;
1290
+ this.#captureCompletionStartTime();
1291
+ }
1142
1292
  controller.enqueue(chunk);
1143
1293
  switch (chunk.type) {
1144
1294
  case "text-start":
@@ -1172,6 +1322,19 @@ var ModelSpanTracker = class {
1172
1322
  case "start":
1173
1323
  case "finish":
1174
1324
  break;
1325
+ case "tool-output":
1326
+ this.#handleToolOutputChunk(chunk);
1327
+ break;
1328
+ case "tool-result": {
1329
+ const toolCallId = chunk.payload?.toolCallId;
1330
+ if (toolCallId && this.#streamedToolCallIds.has(toolCallId)) {
1331
+ this.#streamedToolCallIds.delete(toolCallId);
1332
+ break;
1333
+ }
1334
+ const { args, ...cleanPayload } = chunk.payload || {};
1335
+ this.#createEventSpan(chunk.type, cleanPayload);
1336
+ break;
1337
+ }
1175
1338
  // Default: auto-create event span for all other chunk types
1176
1339
  default: {
1177
1340
  let outputPayload = chunk.payload;
@@ -1226,6 +1389,16 @@ function isSpanInternal(spanType, flags) {
1226
1389
  return false;
1227
1390
  }
1228
1391
  }
1392
+ function getExternalParentId(options) {
1393
+ if (!options.parent) {
1394
+ return void 0;
1395
+ }
1396
+ if (options.parent.isInternal) {
1397
+ return options.parent.getParentSpanId(false);
1398
+ } else {
1399
+ return options.parent.id;
1400
+ }
1401
+ }
1229
1402
  var BaseSpan = class {
1230
1403
  name;
1231
1404
  type;
@@ -1240,6 +1413,7 @@ var BaseSpan = class {
1240
1413
  output;
1241
1414
  errorInfo;
1242
1415
  metadata;
1416
+ tags;
1243
1417
  traceState;
1244
1418
  /** Parent span ID (for root spans that are children of external spans) */
1245
1419
  parentSpanId;
@@ -1254,6 +1428,7 @@ var BaseSpan = class {
1254
1428
  this.isEvent = options.isEvent ?? false;
1255
1429
  this.isInternal = isSpanInternal(this.type, options.tracingPolicy?.internal);
1256
1430
  this.traceState = options.traceState;
1431
+ this.tags = !options.parent && options.tags?.length ? options.tags : void 0;
1257
1432
  if (this.isEvent) {
1258
1433
  this.output = deepClean(options.output);
1259
1434
  } else {
@@ -1316,12 +1491,36 @@ var BaseSpan = class {
1316
1491
  errorInfo: this.errorInfo,
1317
1492
  isEvent: this.isEvent,
1318
1493
  isRootSpan: this.isRootSpan,
1319
- parentSpanId: this.getParentSpanId(includeInternalSpans)
1494
+ parentSpanId: this.getParentSpanId(includeInternalSpans),
1495
+ // Tags are only included for root spans
1496
+ ...this.isRootSpan && this.tags?.length ? { tags: this.tags } : {}
1320
1497
  };
1321
1498
  }
1322
1499
  get externalTraceId() {
1323
1500
  return this.isValid ? this.traceId : void 0;
1324
1501
  }
1502
+ /**
1503
+ * Execute an async function within this span's tracing context.
1504
+ * Delegates to the bridge if available.
1505
+ */
1506
+ async executeInContext(fn) {
1507
+ const bridge = this.observabilityInstance.getBridge();
1508
+ if (bridge?.executeInContext) {
1509
+ return bridge.executeInContext(this.id, fn);
1510
+ }
1511
+ return fn();
1512
+ }
1513
+ /**
1514
+ * Execute a synchronous function within this span's tracing context.
1515
+ * Delegates to the bridge if available.
1516
+ */
1517
+ executeInContextSync(fn) {
1518
+ const bridge = this.observabilityInstance.getBridge();
1519
+ if (bridge?.executeInContextSync) {
1520
+ return bridge.executeInContextSync(this.id, fn);
1521
+ }
1522
+ return fn();
1523
+ }
1325
1524
  };
1326
1525
  var DEFAULT_KEYS_TO_STRIP = /* @__PURE__ */ new Set([
1327
1526
  "logger",
@@ -1368,27 +1567,30 @@ var DefaultSpan = class extends BaseSpan {
1368
1567
  traceId;
1369
1568
  constructor(options, observabilityInstance) {
1370
1569
  super(options, observabilityInstance);
1371
- this.id = generateSpanId();
1570
+ const bridge = observabilityInstance.getBridge();
1571
+ if (bridge && !this.isInternal) {
1572
+ const bridgeIds = bridge.createSpan(options);
1573
+ if (bridgeIds) {
1574
+ this.id = bridgeIds.spanId;
1575
+ this.traceId = bridgeIds.traceId;
1576
+ this.parentSpanId = bridgeIds.parentSpanId;
1577
+ return;
1578
+ }
1579
+ }
1372
1580
  if (options.parent) {
1373
1581
  this.traceId = options.parent.traceId;
1374
- } else if (options.traceId) {
1375
- if (isValidTraceId(options.traceId)) {
1376
- this.traceId = options.traceId;
1377
- } else {
1378
- console.error(
1379
- `[Mastra Tracing] Invalid traceId: must be 1-32 hexadecimal characters, got "${options.traceId}". Generating new trace ID.`
1380
- );
1381
- this.traceId = generateTraceId();
1382
- }
1383
- } else {
1384
- this.traceId = generateTraceId();
1582
+ this.parentSpanId = options.parent.id;
1583
+ this.id = generateSpanId();
1584
+ return;
1385
1585
  }
1386
- if (!options.parent && options.parentSpanId) {
1586
+ this.traceId = getOrCreateTraceId(options);
1587
+ this.id = generateSpanId();
1588
+ if (options.parentSpanId) {
1387
1589
  if (isValidSpanId(options.parentSpanId)) {
1388
1590
  this.parentSpanId = options.parentSpanId;
1389
1591
  } else {
1390
1592
  console.error(
1391
- `[Mastra Tracing] Invalid parentSpanId: must be 1-16 hexadecimal characters, got "${options.parentSpanId}". Ignoring parent span ID.`
1593
+ `[Mastra Tracing] Invalid parentSpanId: must be 1-16 hexadecimal characters, got "${options.parentSpanId}". Ignoring.`
1392
1594
  );
1393
1595
  }
1394
1596
  }
@@ -1493,6 +1695,18 @@ function isValidTraceId(traceId) {
1493
1695
  function isValidSpanId(spanId) {
1494
1696
  return /^[0-9a-f]{1,16}$/i.test(spanId);
1495
1697
  }
1698
+ function getOrCreateTraceId(options) {
1699
+ if (options.traceId) {
1700
+ if (isValidTraceId(options.traceId)) {
1701
+ return options.traceId;
1702
+ } else {
1703
+ console.error(
1704
+ `[Mastra Tracing] Invalid traceId: must be 1-32 hexadecimal characters, got "${options.traceId}". Generating new trace ID.`
1705
+ );
1706
+ }
1707
+ }
1708
+ return generateTraceId();
1709
+ }
1496
1710
 
1497
1711
  // src/spans/no-op.ts
1498
1712
  var NoOpSpan = class extends BaseSpan {
@@ -1525,13 +1739,17 @@ var BaseObservabilityInstance = class extends base.MastraBase {
1525
1739
  sampling: config.sampling ?? { type: "always" /* ALWAYS */ },
1526
1740
  exporters: config.exporters ?? [],
1527
1741
  spanOutputProcessors: config.spanOutputProcessors ?? [],
1742
+ bridge: config.bridge ?? void 0,
1528
1743
  includeInternalSpans: config.includeInternalSpans ?? false,
1529
1744
  requestContextKeys: config.requestContextKeys ?? []
1530
1745
  };
1746
+ if (this.config.bridge?.init) {
1747
+ this.config.bridge.init({ config: this.config });
1748
+ }
1531
1749
  }
1532
1750
  /**
1533
1751
  * Override setLogger to add Observability specific initialization log
1534
- * and propagate logger to exporters
1752
+ * and propagate logger to exporters and bridge
1535
1753
  */
1536
1754
  __setLogger(logger) {
1537
1755
  super.__setLogger(logger);
@@ -1540,8 +1758,11 @@ var BaseObservabilityInstance = class extends base.MastraBase {
1540
1758
  exporter.__setLogger(logger);
1541
1759
  }
1542
1760
  });
1761
+ if (this.config.bridge?.__setLogger) {
1762
+ this.config.bridge.__setLogger(logger);
1763
+ }
1543
1764
  this.logger.debug(
1544
- `[Observability] Initialized [service=${this.config.serviceName}] [instance=${this.config.name}] [sampling=${this.config.sampling.type}]`
1765
+ `[Observability] Initialized [service=${this.config.serviceName}] [instance=${this.config.name}] [sampling=${this.config.sampling?.type}] [bridge=${!!this.config.bridge}]`
1545
1766
  );
1546
1767
  }
1547
1768
  // ============================================================================
@@ -1570,11 +1791,15 @@ var BaseObservabilityInstance = class extends base.MastraBase {
1570
1791
  } else {
1571
1792
  traceState = this.computeTraceState(tracingOptions);
1572
1793
  }
1573
- const enrichedMetadata = this.extractMetadataFromRequestContext(requestContext, metadata, traceState);
1794
+ const tracingMetadata = !options.parent ? tracingOptions?.metadata : void 0;
1795
+ const mergedMetadata = metadata || tracingMetadata ? { ...metadata, ...tracingMetadata } : void 0;
1796
+ const enrichedMetadata = this.extractMetadataFromRequestContext(requestContext, mergedMetadata, traceState);
1797
+ const tags = !options.parent ? tracingOptions?.tags : void 0;
1574
1798
  const span = this.createSpan({
1575
1799
  ...rest,
1576
1800
  metadata: enrichedMetadata,
1577
- traceState
1801
+ traceState,
1802
+ tags
1578
1803
  });
1579
1804
  if (span.isEvent) {
1580
1805
  this.emitSpanEnded(span);
@@ -1608,6 +1833,12 @@ var BaseObservabilityInstance = class extends base.MastraBase {
1608
1833
  getSpanOutputProcessors() {
1609
1834
  return [...this.spanOutputProcessors];
1610
1835
  }
1836
+ /**
1837
+ * Get the bridge instance if configured
1838
+ */
1839
+ getBridge() {
1840
+ return this.config.bridge;
1841
+ }
1611
1842
  /**
1612
1843
  * Get the logger instance (for exporters and other components)
1613
1844
  */
@@ -1652,7 +1883,9 @@ var BaseObservabilityInstance = class extends base.MastraBase {
1652
1883
  */
1653
1884
  shouldSample(options) {
1654
1885
  const { sampling } = this.config;
1655
- switch (sampling.type) {
1886
+ switch (sampling?.type) {
1887
+ case void 0:
1888
+ return true;
1656
1889
  case "always" /* ALWAYS */:
1657
1890
  return true;
1658
1891
  case "never" /* NEVER */:
@@ -1784,17 +2017,21 @@ var BaseObservabilityInstance = class extends base.MastraBase {
1784
2017
  }
1785
2018
  }
1786
2019
  /**
1787
- * Export tracing event through all exporters (realtime mode)
2020
+ * Export tracing event through all exporters and bridge (realtime mode)
1788
2021
  */
1789
2022
  async exportTracingEvent(event) {
1790
- const exportPromises = this.exporters.map(async (exporter) => {
2023
+ const targets = [
2024
+ ...this.exporters
2025
+ ];
2026
+ if (this.config.bridge) {
2027
+ targets.push(this.config.bridge);
2028
+ }
2029
+ const exportPromises = targets.map(async (target) => {
1791
2030
  try {
1792
- if (exporter.exportTracingEvent) {
1793
- await exporter.exportTracingEvent(event);
1794
- this.logger.debug(`[Observability] Event exported [exporter=${exporter.name}] [type=${event.type}]`);
1795
- }
2031
+ await target.exportTracingEvent(event);
2032
+ this.logger.debug(`[Observability] Event exported [target=${target.name}] [type=${event.type}]`);
1796
2033
  } catch (error) {
1797
- this.logger.error(`[Observability] Export error [exporter=${exporter.name}]`, error);
2034
+ this.logger.error(`[Observability] Export error [target=${target.name}]`, error);
1798
2035
  }
1799
2036
  });
1800
2037
  await Promise.allSettled(exportPromises);
@@ -1818,6 +2055,9 @@ var BaseObservabilityInstance = class extends base.MastraBase {
1818
2055
  ...this.exporters.map((e) => e.shutdown()),
1819
2056
  ...this.spanOutputProcessors.map((p) => p.shutdown())
1820
2057
  ];
2058
+ if (this.config.bridge) {
2059
+ shutdownPromises.push(this.config.bridge.shutdown());
2060
+ }
1821
2061
  await Promise.allSettled(shutdownPromises);
1822
2062
  this.logger.info(`[Observability] Shutdown completed [name=${this.name}]`);
1823
2063
  }
@@ -1964,9 +2204,16 @@ var SensitiveDataFilter = class {
1964
2204
  /**
1965
2205
  * Recursively filter objects/arrays for sensitive keys.
1966
2206
  * Handles circular references by replacing with a marker.
2207
+ * Also attempts to parse and redact JSON strings.
1967
2208
  */
1968
2209
  deepFilter(obj, seen = /* @__PURE__ */ new WeakSet()) {
1969
2210
  if (obj === null || typeof obj !== "object") {
2211
+ if (typeof obj === "string") {
2212
+ const trimmed = obj.trim();
2213
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
2214
+ return this.redactJsonString(obj);
2215
+ }
2216
+ }
1970
2217
  return obj;
1971
2218
  }
1972
2219
  if (seen.has(obj)) {
@@ -2019,6 +2266,22 @@ var SensitiveDataFilter = class {
2019
2266
  return normalizedKey === sensitiveField;
2020
2267
  });
2021
2268
  }
2269
+ /**
2270
+ * Attempt to parse a string as JSON and redact sensitive fields within it.
2271
+ * If parsing fails or no sensitive data is found, returns the original string.
2272
+ */
2273
+ redactJsonString(str) {
2274
+ try {
2275
+ const parsed = JSON.parse(str);
2276
+ if (parsed && typeof parsed === "object") {
2277
+ const filtered = this.deepFilter(parsed, /* @__PURE__ */ new WeakSet());
2278
+ return JSON.stringify(filtered);
2279
+ }
2280
+ return str;
2281
+ } catch {
2282
+ return str;
2283
+ }
2284
+ }
2022
2285
  /**
2023
2286
  * Redact a sensitive value.
2024
2287
  * - Full style: replaces with a fixed token.
@@ -2171,6 +2434,11 @@ var Observability = class extends base.MastraBase {
2171
2434
  }
2172
2435
  };
2173
2436
 
2437
+ // src/tracing-options.ts
2438
+ function buildTracingOptions(...updaters) {
2439
+ return updaters.reduce((opts, updater) => updater(opts), {});
2440
+ }
2441
+
2174
2442
  exports.BaseExporter = BaseExporter;
2175
2443
  exports.BaseObservabilityInstance = BaseObservabilityInstance;
2176
2444
  exports.BaseSpan = BaseSpan;
@@ -2184,7 +2452,10 @@ exports.NoOpSpan = NoOpSpan;
2184
2452
  exports.Observability = Observability;
2185
2453
  exports.SamplingStrategyType = SamplingStrategyType;
2186
2454
  exports.SensitiveDataFilter = SensitiveDataFilter;
2455
+ exports.TestExporter = TestExporter;
2456
+ exports.buildTracingOptions = buildTracingOptions;
2187
2457
  exports.deepClean = deepClean;
2458
+ exports.getExternalParentId = getExternalParentId;
2188
2459
  exports.observabilityConfigValueSchema = observabilityConfigValueSchema;
2189
2460
  exports.observabilityInstanceConfigSchema = observabilityInstanceConfigSchema;
2190
2461
  exports.observabilityRegistryConfigSchema = observabilityRegistryConfigSchema;