@mastra/observability 1.0.0-beta.10 → 1.0.0-beta.11

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
@@ -4164,7 +4164,11 @@ var BaseExporter = class {
4164
4164
  /** Mastra logger instance */
4165
4165
  logger;
4166
4166
  /** Whether this exporter is disabled */
4167
- isDisabled = false;
4167
+ #disabled = false;
4168
+ /** Public getter for disabled state */
4169
+ get isDisabled() {
4170
+ return this.#disabled;
4171
+ }
4168
4172
  /**
4169
4173
  * Initialize the base exporter with logger
4170
4174
  */
@@ -4203,7 +4207,7 @@ var BaseExporter = class {
4203
4207
  * @param reason - Reason why the exporter is disabled
4204
4208
  */
4205
4209
  setDisabled(reason) {
4206
- this.isDisabled = true;
4210
+ this.#disabled = true;
4207
4211
  this.logger.warn(`${this.name} disabled: ${reason}`);
4208
4212
  }
4209
4213
  /**
@@ -4227,6 +4231,939 @@ var BaseExporter = class {
4227
4231
  this.logger.info(`${this.name} shutdown complete`);
4228
4232
  }
4229
4233
  };
4234
+ var TraceData = class {
4235
+ /** The vendor-specific root/trace object */
4236
+ #rootSpan;
4237
+ /** The span ID of the root span */
4238
+ #rootSpanId;
4239
+ /** Whether a span with isRootSpan=true has been successfully processed */
4240
+ #rootSpanProcessed;
4241
+ /** Maps eventId to vendor-specific event objects */
4242
+ #events;
4243
+ /** Maps spanId to vendor-specific span objects */
4244
+ #spans;
4245
+ /** Maps spanId to parentSpanId, representing the span hierarchy */
4246
+ #tree;
4247
+ /** Set of span IDs that have started but not yet ended */
4248
+ #activeSpanIds;
4249
+ /** Maps spanId to vendor-specific metadata */
4250
+ #metadata;
4251
+ /** Arbitrary key-value storage for per-trace data */
4252
+ #extraData;
4253
+ /** Events waiting for the root span to be processed */
4254
+ #waitingForRoot;
4255
+ /** Events waiting for specific parent spans, keyed by parentSpanId */
4256
+ #waitingForParent;
4257
+ /** When this trace data was created, used for cap enforcement */
4258
+ createdAt;
4259
+ constructor() {
4260
+ this.#events = /* @__PURE__ */ new Map();
4261
+ this.#spans = /* @__PURE__ */ new Map();
4262
+ this.#activeSpanIds = /* @__PURE__ */ new Set();
4263
+ this.#tree = /* @__PURE__ */ new Map();
4264
+ this.#metadata = /* @__PURE__ */ new Map();
4265
+ this.#extraData = /* @__PURE__ */ new Map();
4266
+ this.#rootSpanProcessed = false;
4267
+ this.#waitingForRoot = [];
4268
+ this.#waitingForParent = /* @__PURE__ */ new Map();
4269
+ this.createdAt = /* @__PURE__ */ new Date();
4270
+ }
4271
+ /**
4272
+ * Check if this trace has a root span registered.
4273
+ * @returns True if addRoot() has been called
4274
+ */
4275
+ hasRoot() {
4276
+ return !!this.#rootSpanId;
4277
+ }
4278
+ /**
4279
+ * Register the root span for this trace.
4280
+ * @param args.rootId - The span ID of the root span
4281
+ * @param args.rootData - The vendor-specific root object
4282
+ */
4283
+ addRoot(args) {
4284
+ this.#rootSpanId = args.rootId;
4285
+ this.#rootSpan = args.rootData;
4286
+ this.#rootSpanProcessed = true;
4287
+ }
4288
+ /**
4289
+ * Get the vendor-specific root object.
4290
+ * @returns The root object, or undefined if not yet set
4291
+ */
4292
+ getRoot() {
4293
+ return this.#rootSpan;
4294
+ }
4295
+ /**
4296
+ * Check if a span with isRootSpan=true has been successfully processed.
4297
+ * Set via addRoot() or markRootSpanProcessed().
4298
+ * @returns True if the root span has been processed
4299
+ */
4300
+ isRootProcessed() {
4301
+ return this.#rootSpanProcessed;
4302
+ }
4303
+ /**
4304
+ * Mark that the root span has been processed.
4305
+ * Used by exporters with skipBuildRootTask=true where root goes through _buildSpan
4306
+ * instead of _buildRoot.
4307
+ */
4308
+ markRootSpanProcessed() {
4309
+ this.#rootSpanProcessed = true;
4310
+ }
4311
+ /**
4312
+ * Store an arbitrary value in per-trace storage.
4313
+ * @param key - Storage key
4314
+ * @param value - Value to store
4315
+ */
4316
+ setExtraValue(key, value) {
4317
+ this.#extraData.set(key, value);
4318
+ }
4319
+ /**
4320
+ * Check if a key exists in per-trace storage.
4321
+ * @param key - Storage key
4322
+ * @returns True if the key exists
4323
+ */
4324
+ hasExtraValue(key) {
4325
+ return this.#extraData.has(key);
4326
+ }
4327
+ /**
4328
+ * Get a value from per-trace storage.
4329
+ * @param key - Storage key
4330
+ * @returns The stored value, or undefined if not found
4331
+ */
4332
+ getExtraValue(key) {
4333
+ return this.#extraData.get(key);
4334
+ }
4335
+ // ============================================================================
4336
+ // Early Queue Methods
4337
+ // ============================================================================
4338
+ /**
4339
+ * Add an event to the waiting queue.
4340
+ * @param args.event - The tracing event to queue
4341
+ * @param args.waitingFor - 'root' or a specific parentSpanId
4342
+ * @param args.attempts - Optional: preserve attempts count when re-queuing
4343
+ * @param args.queuedAt - Optional: preserve original queue time when re-queuing
4344
+ */
4345
+ addToWaitingQueue(args) {
4346
+ const queuedEvent = {
4347
+ event: args.event,
4348
+ waitingFor: args.waitingFor,
4349
+ attempts: args.attempts ?? 0,
4350
+ queuedAt: args.queuedAt ?? /* @__PURE__ */ new Date()
4351
+ };
4352
+ if (args.waitingFor === "root") {
4353
+ this.#waitingForRoot.push(queuedEvent);
4354
+ } else {
4355
+ const queue = this.#waitingForParent.get(args.waitingFor) ?? [];
4356
+ queue.push(queuedEvent);
4357
+ this.#waitingForParent.set(args.waitingFor, queue);
4358
+ }
4359
+ }
4360
+ /**
4361
+ * Get all events waiting for the root span.
4362
+ * Returns a copy of the internal array.
4363
+ */
4364
+ getEventsWaitingForRoot() {
4365
+ return [...this.#waitingForRoot];
4366
+ }
4367
+ /**
4368
+ * Get all events waiting for a specific parent span.
4369
+ * Returns a copy of the internal array.
4370
+ */
4371
+ getEventsWaitingFor(args) {
4372
+ return [...this.#waitingForParent.get(args.spanId) ?? []];
4373
+ }
4374
+ /**
4375
+ * Clear the waiting-for-root queue.
4376
+ */
4377
+ clearWaitingForRoot() {
4378
+ this.#waitingForRoot = [];
4379
+ }
4380
+ /**
4381
+ * Clear the waiting queue for a specific parent span.
4382
+ */
4383
+ clearWaitingFor(args) {
4384
+ this.#waitingForParent.delete(args.spanId);
4385
+ }
4386
+ /**
4387
+ * Get total count of events in all waiting queues.
4388
+ */
4389
+ waitingQueueSize() {
4390
+ let count = this.#waitingForRoot.length;
4391
+ for (const queue of this.#waitingForParent.values()) {
4392
+ count += queue.length;
4393
+ }
4394
+ return count;
4395
+ }
4396
+ /**
4397
+ * Get all queued events across all waiting queues.
4398
+ * Used for cleanup and logging orphaned events.
4399
+ * @returns Array of all queued events
4400
+ */
4401
+ getAllQueuedEvents() {
4402
+ const all = [...this.#waitingForRoot];
4403
+ for (const queue of this.#waitingForParent.values()) {
4404
+ all.push(...queue);
4405
+ }
4406
+ return all;
4407
+ }
4408
+ // ============================================================================
4409
+ // Span Tree Methods
4410
+ // ============================================================================
4411
+ /**
4412
+ * Record the parent-child relationship for a span.
4413
+ * @param args.spanId - The child span ID
4414
+ * @param args.parentSpanId - The parent span ID, or undefined for root spans
4415
+ */
4416
+ addBranch(args) {
4417
+ this.#tree.set(args.spanId, args.parentSpanId);
4418
+ }
4419
+ /**
4420
+ * Get the parent span ID for a given span.
4421
+ * @param args.spanId - The span ID to look up
4422
+ * @returns The parent span ID, or undefined if root or not found
4423
+ */
4424
+ getParentId(args) {
4425
+ return this.#tree.get(args.spanId);
4426
+ }
4427
+ // ============================================================================
4428
+ // Span Management Methods
4429
+ // ============================================================================
4430
+ /**
4431
+ * Register a span and mark it as active.
4432
+ * @param args.spanId - The span ID
4433
+ * @param args.spanData - The vendor-specific span object
4434
+ */
4435
+ addSpan(args) {
4436
+ this.#spans.set(args.spanId, args.spanData);
4437
+ this.#activeSpanIds.add(args.spanId);
4438
+ }
4439
+ /**
4440
+ * Check if a span exists (regardless of active state).
4441
+ * @param args.spanId - The span ID to check
4442
+ * @returns True if the span exists
4443
+ */
4444
+ hasSpan(args) {
4445
+ return this.#spans.has(args.spanId);
4446
+ }
4447
+ /**
4448
+ * Get a span by ID.
4449
+ * @param args.spanId - The span ID to look up
4450
+ * @returns The vendor-specific span object, or undefined if not found
4451
+ */
4452
+ getSpan(args) {
4453
+ return this.#spans.get(args.spanId);
4454
+ }
4455
+ /**
4456
+ * Mark a span as ended (no longer active).
4457
+ * @param args.spanId - The span ID to mark as ended
4458
+ */
4459
+ endSpan(args) {
4460
+ this.#activeSpanIds.delete(args.spanId);
4461
+ }
4462
+ /**
4463
+ * Check if a span is currently active (started but not ended).
4464
+ * @param args.spanId - The span ID to check
4465
+ * @returns True if the span is active
4466
+ */
4467
+ isActiveSpan(args) {
4468
+ return this.#activeSpanIds.has(args.spanId);
4469
+ }
4470
+ /**
4471
+ * Get the count of currently active spans.
4472
+ * @returns Number of active spans
4473
+ */
4474
+ activeSpanCount() {
4475
+ return this.#activeSpanIds.size;
4476
+ }
4477
+ /**
4478
+ * Get all active span IDs.
4479
+ * @returns Array of active span IDs
4480
+ */
4481
+ get activeSpanIds() {
4482
+ return [...this.#activeSpanIds];
4483
+ }
4484
+ // ============================================================================
4485
+ // Event Management Methods
4486
+ // ============================================================================
4487
+ /**
4488
+ * Register an event.
4489
+ * @param args.eventId - The event ID
4490
+ * @param args.eventData - The vendor-specific event object
4491
+ */
4492
+ addEvent(args) {
4493
+ this.#events.set(args.eventId, args.eventData);
4494
+ }
4495
+ // ============================================================================
4496
+ // Metadata Methods
4497
+ // ============================================================================
4498
+ /**
4499
+ * Store vendor-specific metadata for a span.
4500
+ * Note: This overwrites any existing metadata for the span.
4501
+ * @param args.spanId - The span ID
4502
+ * @param args.metadata - The vendor-specific metadata
4503
+ */
4504
+ addMetadata(args) {
4505
+ this.#metadata.set(args.spanId, args.metadata);
4506
+ }
4507
+ /**
4508
+ * Get vendor-specific metadata for a span.
4509
+ * @param args.spanId - The span ID
4510
+ * @returns The metadata, or undefined if not found
4511
+ */
4512
+ getMetadata(args) {
4513
+ return this.#metadata.get(args.spanId);
4514
+ }
4515
+ // ============================================================================
4516
+ // Parent Lookup Methods
4517
+ // ============================================================================
4518
+ /**
4519
+ * Get the parent span or event for a given span.
4520
+ * Looks up in both spans and events maps.
4521
+ * @param args.span - The span to find the parent for
4522
+ * @returns The parent span/event object, or undefined if root or not found
4523
+ */
4524
+ getParent(args) {
4525
+ const parentId = args.span.parentSpanId;
4526
+ if (parentId) {
4527
+ if (this.#spans.has(parentId)) {
4528
+ return this.#spans.get(parentId);
4529
+ }
4530
+ if (this.#events.has(parentId)) {
4531
+ return this.#events.get(parentId);
4532
+ }
4533
+ }
4534
+ return void 0;
4535
+ }
4536
+ /**
4537
+ * Get the parent span/event or fall back to the root object.
4538
+ * Useful for vendors that attach child spans to either parent spans or the trace root.
4539
+ * @param args.span - The span to find the parent for
4540
+ * @returns The parent span/event, the root object, or undefined
4541
+ */
4542
+ getParentOrRoot(args) {
4543
+ return this.getParent(args) ?? this.getRoot();
4544
+ }
4545
+ };
4546
+ var DEFAULT_EARLY_QUEUE_MAX_ATTEMPTS = 5;
4547
+ var DEFAULT_EARLY_QUEUE_TTL_MS = 3e4;
4548
+ var DEFAULT_TRACE_CLEANUP_DELAY_MS = 3e4;
4549
+ var DEFAULT_MAX_PENDING_CLEANUP_TRACES = 100;
4550
+ var DEFAULT_MAX_TOTAL_TRACES = 500;
4551
+ var TrackingExporter = class extends BaseExporter {
4552
+ /** Map of traceId to per-trace data container */
4553
+ #traceMap = /* @__PURE__ */ new Map();
4554
+ /** Flag to prevent processing during shutdown */
4555
+ #shutdownStarted = false;
4556
+ /** Flag to prevent concurrent hard cap enforcement */
4557
+ #hardCapEnforcementInProgress = false;
4558
+ /** Map of traceId to scheduled cleanup timeout */
4559
+ #pendingCleanups = /* @__PURE__ */ new Map();
4560
+ // Note: #traceMap maintains insertion order (JS Map spec), so we use
4561
+ // #traceMap.keys() to iterate traces oldest-first for cap enforcement.
4562
+ /** Subclass configuration with resolved values */
4563
+ config;
4564
+ /** Maximum attempts to process a queued event before dropping */
4565
+ #earlyQueueMaxAttempts;
4566
+ /** TTL in milliseconds for queued events */
4567
+ #earlyQueueTTLMs;
4568
+ /** Delay before cleaning up completed traces */
4569
+ #traceCleanupDelayMs;
4570
+ /** Soft cap on traces awaiting cleanup */
4571
+ #maxPendingCleanupTraces;
4572
+ /** Hard cap on total traces (will abort active spans if exceeded) */
4573
+ #maxTotalTraces;
4574
+ constructor(config) {
4575
+ super(config);
4576
+ this.config = config;
4577
+ this.#earlyQueueMaxAttempts = config.earlyQueueMaxAttempts ?? DEFAULT_EARLY_QUEUE_MAX_ATTEMPTS;
4578
+ this.#earlyQueueTTLMs = config.earlyQueueTTLMs ?? DEFAULT_EARLY_QUEUE_TTL_MS;
4579
+ this.#traceCleanupDelayMs = config.traceCleanupDelayMs ?? DEFAULT_TRACE_CLEANUP_DELAY_MS;
4580
+ this.#maxPendingCleanupTraces = config.maxPendingCleanupTraces ?? DEFAULT_MAX_PENDING_CLEANUP_TRACES;
4581
+ this.#maxTotalTraces = config.maxTotalTraces ?? DEFAULT_MAX_TOTAL_TRACES;
4582
+ }
4583
+ // ============================================================================
4584
+ // Early Queue Processing
4585
+ // ============================================================================
4586
+ /**
4587
+ * Schedule async processing of events waiting for root span.
4588
+ * Called after root span is successfully processed.
4589
+ */
4590
+ #scheduleProcessWaitingForRoot(traceId) {
4591
+ setImmediate(() => {
4592
+ this.#processWaitingForRoot(traceId).catch((error) => {
4593
+ this.logger.error(`${this.name}: Error processing waiting-for-root queue`, { error, traceId });
4594
+ });
4595
+ });
4596
+ }
4597
+ /**
4598
+ * Schedule async processing of events waiting for a specific parent span.
4599
+ * Called after a span/event is successfully created.
4600
+ */
4601
+ #scheduleProcessWaitingFor(traceId, spanId) {
4602
+ setImmediate(() => {
4603
+ this.#processWaitingFor(traceId, spanId).catch((error) => {
4604
+ this.logger.error(`${this.name}: Error processing waiting queue`, { error, traceId, spanId });
4605
+ });
4606
+ });
4607
+ }
4608
+ /**
4609
+ * Process all events waiting for root span.
4610
+ */
4611
+ async #processWaitingForRoot(traceId) {
4612
+ if (this.#shutdownStarted) return;
4613
+ const traceData = this.#traceMap.get(traceId);
4614
+ if (!traceData) return;
4615
+ const queue = traceData.getEventsWaitingForRoot();
4616
+ if (queue.length === 0) return;
4617
+ this.logger.debug(`${this.name}: Processing ${queue.length} events waiting for root`, { traceId });
4618
+ const toKeep = [];
4619
+ const now = Date.now();
4620
+ for (const queuedEvent of queue) {
4621
+ if (now - queuedEvent.queuedAt.getTime() > this.#earlyQueueTTLMs) {
4622
+ this.logger.warn(`${this.name}: Dropping event due to TTL expiry`, {
4623
+ traceId,
4624
+ spanId: queuedEvent.event.exportedSpan.id,
4625
+ waitingFor: queuedEvent.waitingFor,
4626
+ queuedAt: queuedEvent.queuedAt,
4627
+ attempts: queuedEvent.attempts
4628
+ });
4629
+ continue;
4630
+ }
4631
+ if (queuedEvent.attempts >= this.#earlyQueueMaxAttempts) {
4632
+ this.logger.warn(`${this.name}: Dropping event due to max attempts`, {
4633
+ traceId,
4634
+ spanId: queuedEvent.event.exportedSpan.id,
4635
+ waitingFor: queuedEvent.waitingFor,
4636
+ attempts: queuedEvent.attempts
4637
+ });
4638
+ continue;
4639
+ }
4640
+ queuedEvent.attempts++;
4641
+ const processed = await this.#tryProcessQueuedEvent(queuedEvent, traceData);
4642
+ if (!processed) {
4643
+ const parentId = queuedEvent.event.exportedSpan.parentSpanId;
4644
+ if (parentId && traceData.isRootProcessed()) {
4645
+ traceData.addToWaitingQueue({
4646
+ event: queuedEvent.event,
4647
+ waitingFor: parentId,
4648
+ attempts: queuedEvent.attempts,
4649
+ queuedAt: queuedEvent.queuedAt
4650
+ });
4651
+ } else {
4652
+ toKeep.push(queuedEvent);
4653
+ }
4654
+ }
4655
+ }
4656
+ traceData.clearWaitingForRoot();
4657
+ for (const event of toKeep) {
4658
+ traceData.addToWaitingQueue({
4659
+ event: event.event,
4660
+ waitingFor: "root",
4661
+ attempts: event.attempts,
4662
+ queuedAt: event.queuedAt
4663
+ });
4664
+ }
4665
+ }
4666
+ /**
4667
+ * Process events waiting for a specific parent span.
4668
+ */
4669
+ async #processWaitingFor(traceId, spanId) {
4670
+ if (this.#shutdownStarted) return;
4671
+ const traceData = this.#traceMap.get(traceId);
4672
+ if (!traceData) return;
4673
+ const queue = traceData.getEventsWaitingFor({ spanId });
4674
+ if (queue.length === 0) return;
4675
+ this.logger.debug(`${this.name}: Processing ${queue.length} events waiting for span`, { traceId, spanId });
4676
+ const toKeep = [];
4677
+ const now = Date.now();
4678
+ for (const queuedEvent of queue) {
4679
+ if (now - queuedEvent.queuedAt.getTime() > this.#earlyQueueTTLMs) {
4680
+ this.logger.warn(`${this.name}: Dropping event due to TTL expiry`, {
4681
+ traceId,
4682
+ spanId: queuedEvent.event.exportedSpan.id,
4683
+ waitingFor: queuedEvent.waitingFor,
4684
+ queuedAt: queuedEvent.queuedAt,
4685
+ attempts: queuedEvent.attempts
4686
+ });
4687
+ continue;
4688
+ }
4689
+ if (queuedEvent.attempts >= this.#earlyQueueMaxAttempts) {
4690
+ this.logger.warn(`${this.name}: Dropping event due to max attempts`, {
4691
+ traceId,
4692
+ spanId: queuedEvent.event.exportedSpan.id,
4693
+ waitingFor: queuedEvent.waitingFor,
4694
+ attempts: queuedEvent.attempts
4695
+ });
4696
+ continue;
4697
+ }
4698
+ queuedEvent.attempts++;
4699
+ const processed = await this.#tryProcessQueuedEvent(queuedEvent, traceData);
4700
+ if (!processed) {
4701
+ toKeep.push(queuedEvent);
4702
+ }
4703
+ }
4704
+ traceData.clearWaitingFor({ spanId });
4705
+ for (const event of toKeep) {
4706
+ traceData.addToWaitingQueue({
4707
+ event: event.event,
4708
+ waitingFor: spanId,
4709
+ attempts: event.attempts,
4710
+ queuedAt: event.queuedAt
4711
+ });
4712
+ }
4713
+ }
4714
+ /**
4715
+ * Try to process a queued event.
4716
+ * Returns true if successfully processed, false if still waiting for dependencies.
4717
+ */
4718
+ async #tryProcessQueuedEvent(queuedEvent, traceData) {
4719
+ const { event } = queuedEvent;
4720
+ const { exportedSpan } = event;
4721
+ const method = this.getMethod(event);
4722
+ try {
4723
+ switch (method) {
4724
+ case "handleEventSpan": {
4725
+ traceData.addBranch({ spanId: exportedSpan.id, parentSpanId: exportedSpan.parentSpanId });
4726
+ const eventData = await this._buildEvent({ span: exportedSpan, traceData });
4727
+ if (eventData) {
4728
+ if (!this.skipCachingEventSpans) {
4729
+ traceData.addEvent({ eventId: exportedSpan.id, eventData });
4730
+ }
4731
+ this.#scheduleProcessWaitingFor(exportedSpan.traceId, exportedSpan.id);
4732
+ return true;
4733
+ }
4734
+ return false;
4735
+ }
4736
+ case "handleSpanStart": {
4737
+ traceData.addBranch({ spanId: exportedSpan.id, parentSpanId: exportedSpan.parentSpanId });
4738
+ const spanData = await this._buildSpan({ span: exportedSpan, traceData });
4739
+ if (spanData) {
4740
+ traceData.addSpan({ spanId: exportedSpan.id, spanData });
4741
+ if (exportedSpan.isRootSpan) {
4742
+ traceData.markRootSpanProcessed();
4743
+ }
4744
+ this.#scheduleProcessWaitingFor(exportedSpan.traceId, exportedSpan.id);
4745
+ return true;
4746
+ }
4747
+ return false;
4748
+ }
4749
+ case "handleSpanUpdate": {
4750
+ await this._updateSpan({ span: exportedSpan, traceData });
4751
+ return true;
4752
+ }
4753
+ case "handleSpanEnd": {
4754
+ traceData.endSpan({ spanId: exportedSpan.id });
4755
+ await this._finishSpan({ span: exportedSpan, traceData });
4756
+ if (traceData.activeSpanCount() === 0) {
4757
+ this.#scheduleCleanup(exportedSpan.traceId);
4758
+ }
4759
+ return true;
4760
+ }
4761
+ default:
4762
+ return false;
4763
+ }
4764
+ } catch (error) {
4765
+ this.logger.error(`${this.name}: Error processing queued event`, { error, event, method });
4766
+ return false;
4767
+ }
4768
+ }
4769
+ // ============================================================================
4770
+ // Delayed Cleanup
4771
+ // ============================================================================
4772
+ /**
4773
+ * Schedule cleanup of trace data after a delay.
4774
+ * Allows late-arriving data to still be processed.
4775
+ */
4776
+ #scheduleCleanup(traceId) {
4777
+ this.#cancelScheduledCleanup(traceId);
4778
+ this.logger.debug(`${this.name}: Scheduling cleanup in ${this.#traceCleanupDelayMs}ms`, { traceId });
4779
+ const timeout = setTimeout(() => {
4780
+ this.#pendingCleanups.delete(traceId);
4781
+ this.#performCleanup(traceId);
4782
+ }, this.#traceCleanupDelayMs);
4783
+ this.#pendingCleanups.set(traceId, timeout);
4784
+ this.#enforcePendingCleanupCap();
4785
+ }
4786
+ /**
4787
+ * Cancel a scheduled cleanup for a trace.
4788
+ */
4789
+ #cancelScheduledCleanup(traceId) {
4790
+ const existingTimeout = this.#pendingCleanups.get(traceId);
4791
+ if (existingTimeout) {
4792
+ clearTimeout(existingTimeout);
4793
+ this.#pendingCleanups.delete(traceId);
4794
+ this.logger.debug(`${this.name}: Cancelled scheduled cleanup`, { traceId });
4795
+ }
4796
+ }
4797
+ /**
4798
+ * Perform the actual cleanup of trace data.
4799
+ */
4800
+ #performCleanup(traceId) {
4801
+ const traceData = this.#traceMap.get(traceId);
4802
+ if (!traceData) return;
4803
+ const orphanedEvents = traceData.getAllQueuedEvents();
4804
+ if (orphanedEvents.length > 0) {
4805
+ this.logger.warn(`${this.name}: Dropping ${orphanedEvents.length} orphaned events on cleanup`, {
4806
+ traceId,
4807
+ orphanedEvents: orphanedEvents.map((e) => ({
4808
+ spanId: e.event.exportedSpan.id,
4809
+ waitingFor: e.waitingFor,
4810
+ attempts: e.attempts,
4811
+ queuedAt: e.queuedAt
4812
+ }))
4813
+ });
4814
+ }
4815
+ this.#traceMap.delete(traceId);
4816
+ this.logger.debug(`${this.name}: Cleaned up trace data`, { traceId });
4817
+ }
4818
+ // ============================================================================
4819
+ // Cap Enforcement
4820
+ // ============================================================================
4821
+ /**
4822
+ * Enforce soft cap on pending cleanup traces.
4823
+ * Only removes traces with activeSpanCount == 0.
4824
+ */
4825
+ #enforcePendingCleanupCap() {
4826
+ if (this.#pendingCleanups.size <= this.#maxPendingCleanupTraces) {
4827
+ return;
4828
+ }
4829
+ const toRemove = this.#pendingCleanups.size - this.#maxPendingCleanupTraces;
4830
+ this.logger.warn(`${this.name}: Pending cleanup cap exceeded, force-cleaning ${toRemove} traces`, {
4831
+ pendingCount: this.#pendingCleanups.size,
4832
+ cap: this.#maxPendingCleanupTraces
4833
+ });
4834
+ let removed = 0;
4835
+ for (const traceId of this.#traceMap.keys()) {
4836
+ if (removed >= toRemove) break;
4837
+ if (this.#pendingCleanups.has(traceId)) {
4838
+ this.#cancelScheduledCleanup(traceId);
4839
+ this.#performCleanup(traceId);
4840
+ removed++;
4841
+ }
4842
+ }
4843
+ }
4844
+ /**
4845
+ * Enforce hard cap on total traces.
4846
+ * Will kill even active traces if necessary.
4847
+ * Uses a flag to prevent concurrent executions when called fire-and-forget.
4848
+ */
4849
+ async #enforceHardCap() {
4850
+ if (this.#traceMap.size <= this.#maxTotalTraces || this.#hardCapEnforcementInProgress) {
4851
+ return;
4852
+ }
4853
+ this.#hardCapEnforcementInProgress = true;
4854
+ try {
4855
+ if (this.#traceMap.size <= this.#maxTotalTraces) {
4856
+ return;
4857
+ }
4858
+ const toRemove = this.#traceMap.size - this.#maxTotalTraces;
4859
+ this.logger.warn(`${this.name}: Total trace cap exceeded, killing ${toRemove} oldest traces`, {
4860
+ traceCount: this.#traceMap.size,
4861
+ cap: this.#maxTotalTraces
4862
+ });
4863
+ const reason = {
4864
+ id: "TRACE_CAP_EXCEEDED",
4865
+ message: "Trace killed due to memory cap enforcement.",
4866
+ domain: "MASTRA_OBSERVABILITY",
4867
+ category: "SYSTEM"
4868
+ };
4869
+ let removed = 0;
4870
+ for (const traceId of [...this.#traceMap.keys()]) {
4871
+ if (removed >= toRemove) break;
4872
+ const traceData = this.#traceMap.get(traceId);
4873
+ if (traceData) {
4874
+ for (const spanId of traceData.activeSpanIds) {
4875
+ const span = traceData.getSpan({ spanId });
4876
+ if (span) {
4877
+ await this._abortSpan({ span, traceData, reason });
4878
+ }
4879
+ }
4880
+ this.#cancelScheduledCleanup(traceId);
4881
+ this.#performCleanup(traceId);
4882
+ removed++;
4883
+ }
4884
+ }
4885
+ } finally {
4886
+ this.#hardCapEnforcementInProgress = false;
4887
+ }
4888
+ }
4889
+ // ============================================================================
4890
+ // Lifecycle Hooks (Override in subclass)
4891
+ // ============================================================================
4892
+ /**
4893
+ * Hook called before processing each tracing event.
4894
+ * Override to transform or enrich the event before processing.
4895
+ * @param event - The incoming tracing event
4896
+ * @returns The (possibly modified) event to process
4897
+ */
4898
+ async _preExportTracingEvent(event) {
4899
+ return event;
4900
+ }
4901
+ /**
4902
+ * Hook called after processing each tracing event.
4903
+ * Override to perform post-processing actions like flushing.
4904
+ */
4905
+ async _postExportTracingEvent() {
4906
+ }
4907
+ // ============================================================================
4908
+ // Behavior Flags (Override in subclass as needed)
4909
+ // ============================================================================
4910
+ /**
4911
+ * If true, skip calling _buildRoot and let root spans go through _buildSpan.
4912
+ * Use when the vendor doesn't have a separate trace/root concept.
4913
+ * @default false
4914
+ */
4915
+ skipBuildRootTask = false;
4916
+ /**
4917
+ * If true, skip processing span_updated events entirely.
4918
+ * Use when the vendor doesn't support incremental span updates.
4919
+ * @default false
4920
+ */
4921
+ skipSpanUpdateEvents = false;
4922
+ /**
4923
+ * If true, don't cache event spans in TraceData.
4924
+ * Use when events can't be parents of other spans.
4925
+ * @default false
4926
+ */
4927
+ skipCachingEventSpans = false;
4928
+ getMethod(event) {
4929
+ if (event.exportedSpan.isEvent) {
4930
+ return "handleEventSpan";
4931
+ }
4932
+ const eventType = event.type;
4933
+ switch (eventType) {
4934
+ case observability.TracingEventType.SPAN_STARTED:
4935
+ return "handleSpanStart";
4936
+ case observability.TracingEventType.SPAN_UPDATED:
4937
+ return "handleSpanUpdate";
4938
+ case observability.TracingEventType.SPAN_ENDED:
4939
+ return "handleSpanEnd";
4940
+ default: {
4941
+ const _exhaustiveCheck = eventType;
4942
+ throw new Error(`Unhandled event type: ${_exhaustiveCheck}`);
4943
+ }
4944
+ }
4945
+ }
4946
+ async _exportTracingEvent(event) {
4947
+ if (this.#shutdownStarted) {
4948
+ return;
4949
+ }
4950
+ const method = this.getMethod(event);
4951
+ if (method == "handleSpanUpdate" && this.skipSpanUpdateEvents) {
4952
+ return;
4953
+ }
4954
+ const traceId = event.exportedSpan.traceId;
4955
+ const traceData = this.getTraceData({ traceId, method });
4956
+ const { exportedSpan } = await this._preExportTracingEvent(event);
4957
+ if (!this.skipBuildRootTask && !traceData.hasRoot()) {
4958
+ if (exportedSpan.isRootSpan) {
4959
+ this.logger.debug(`${this.name}: Building root`, {
4960
+ traceId: exportedSpan.traceId,
4961
+ spanId: exportedSpan.id
4962
+ });
4963
+ const rootData = await this._buildRoot({ span: exportedSpan, traceData });
4964
+ if (rootData) {
4965
+ this.logger.debug(`${this.name}: Adding root`, {
4966
+ traceId: exportedSpan.traceId,
4967
+ spanId: exportedSpan.id
4968
+ });
4969
+ traceData.addRoot({ rootId: exportedSpan.id, rootData });
4970
+ this.#scheduleProcessWaitingForRoot(traceId);
4971
+ }
4972
+ } else {
4973
+ this.logger.debug(`${this.name}: Root does not exist, adding span to waiting queue.`, {
4974
+ traceId: exportedSpan.traceId,
4975
+ spanId: exportedSpan.id
4976
+ });
4977
+ traceData.addToWaitingQueue({ event, waitingFor: "root" });
4978
+ return;
4979
+ }
4980
+ }
4981
+ if (exportedSpan.metadata && this.name in exportedSpan.metadata) {
4982
+ const metadata = exportedSpan.metadata[this.name];
4983
+ this.logger.debug(`${this.name}: Found provider metadata in span`, {
4984
+ traceId: exportedSpan.traceId,
4985
+ spanId: exportedSpan.id,
4986
+ metadata
4987
+ });
4988
+ traceData.addMetadata({ spanId: exportedSpan.id, metadata });
4989
+ }
4990
+ try {
4991
+ switch (method) {
4992
+ case "handleEventSpan": {
4993
+ this.logger.debug(`${this.name}: handling event`, {
4994
+ traceId: exportedSpan.traceId,
4995
+ spanId: exportedSpan.id
4996
+ });
4997
+ traceData.addBranch({ spanId: exportedSpan.id, parentSpanId: exportedSpan.parentSpanId });
4998
+ const eventData = await this._buildEvent({ span: exportedSpan, traceData });
4999
+ if (eventData) {
5000
+ if (!this.skipCachingEventSpans) {
5001
+ this.logger.debug(`${this.name}: adding event to traceData`, {
5002
+ traceId: exportedSpan.traceId,
5003
+ spanId: exportedSpan.id
5004
+ });
5005
+ traceData.addEvent({ eventId: exportedSpan.id, eventData });
5006
+ }
5007
+ this.#scheduleProcessWaitingFor(traceId, exportedSpan.id);
5008
+ } else {
5009
+ const parentId = exportedSpan.parentSpanId;
5010
+ this.logger.debug(`${this.name}: adding event to waiting queue`, {
5011
+ traceId: exportedSpan.traceId,
5012
+ spanId: exportedSpan.id,
5013
+ waitingFor: parentId ?? "root"
5014
+ });
5015
+ traceData.addToWaitingQueue({ event, waitingFor: parentId ?? "root" });
5016
+ }
5017
+ break;
5018
+ }
5019
+ case "handleSpanStart": {
5020
+ this.logger.debug(`${this.name}: handling span start`, {
5021
+ traceId: exportedSpan.traceId,
5022
+ spanId: exportedSpan.id
5023
+ });
5024
+ traceData.addBranch({ spanId: exportedSpan.id, parentSpanId: exportedSpan.parentSpanId });
5025
+ const spanData = await this._buildSpan({ span: exportedSpan, traceData });
5026
+ if (spanData) {
5027
+ this.logger.debug(`${this.name}: adding span to traceData`, {
5028
+ traceId: exportedSpan.traceId,
5029
+ spanId: exportedSpan.id
5030
+ });
5031
+ traceData.addSpan({ spanId: exportedSpan.id, spanData });
5032
+ if (exportedSpan.isRootSpan) {
5033
+ traceData.markRootSpanProcessed();
5034
+ this.#scheduleProcessWaitingForRoot(traceId);
5035
+ }
5036
+ this.#scheduleProcessWaitingFor(traceId, exportedSpan.id);
5037
+ } else {
5038
+ const parentId = exportedSpan.parentSpanId;
5039
+ this.logger.debug(`${this.name}: adding span to waiting queue`, {
5040
+ traceId: exportedSpan.traceId,
5041
+ waitingFor: parentId ?? "root"
5042
+ });
5043
+ traceData.addToWaitingQueue({ event, waitingFor: parentId ?? "root" });
5044
+ }
5045
+ break;
5046
+ }
5047
+ case "handleSpanUpdate":
5048
+ this.logger.debug(`${this.name}: handling span update`, {
5049
+ traceId: exportedSpan.traceId,
5050
+ spanId: exportedSpan.id
5051
+ });
5052
+ await this._updateSpan({ span: exportedSpan, traceData });
5053
+ break;
5054
+ case "handleSpanEnd":
5055
+ this.logger.debug(`${this.name}: handling span end`, {
5056
+ traceId: exportedSpan.traceId,
5057
+ spanId: exportedSpan.id
5058
+ });
5059
+ traceData.endSpan({ spanId: exportedSpan.id });
5060
+ await this._finishSpan({ span: exportedSpan, traceData });
5061
+ if (traceData.activeSpanCount() === 0) {
5062
+ this.#scheduleCleanup(traceId);
5063
+ }
5064
+ break;
5065
+ }
5066
+ } catch (error) {
5067
+ this.logger.error(`${this.name}: exporter error`, { error, event, method });
5068
+ }
5069
+ if (traceData.activeSpanCount() === 0) {
5070
+ this.#scheduleCleanup(traceId);
5071
+ }
5072
+ await this._postExportTracingEvent();
5073
+ }
5074
+ // ============================================================================
5075
+ // Protected Helpers
5076
+ // ============================================================================
5077
+ /**
5078
+ * Get or create the TraceData container for a trace.
5079
+ * Also cancels any pending cleanup since new data has arrived.
5080
+ *
5081
+ * @param args.traceId - The trace ID
5082
+ * @param args.method - The calling method name (for logging)
5083
+ * @returns The TraceData container for this trace
5084
+ */
5085
+ getTraceData(args) {
5086
+ const { traceId, method } = args;
5087
+ this.#cancelScheduledCleanup(traceId);
5088
+ if (!this.#traceMap.has(traceId)) {
5089
+ this.#traceMap.set(traceId, new TraceData());
5090
+ this.logger.debug(`${this.name}: Created new trace data cache`, {
5091
+ traceId,
5092
+ method
5093
+ });
5094
+ this.#enforceHardCap().catch((error) => {
5095
+ this.logger.error(`${this.name}: Error enforcing hard cap`, { error });
5096
+ });
5097
+ }
5098
+ return this.#traceMap.get(traceId);
5099
+ }
5100
+ /**
5101
+ * Get the current number of traces being tracked.
5102
+ * @returns The trace count
5103
+ */
5104
+ traceMapSize() {
5105
+ return this.#traceMap.size;
5106
+ }
5107
+ // ============================================================================
5108
+ // Shutdown Hooks (Override in subclass as needed)
5109
+ // ============================================================================
5110
+ /**
5111
+ * Hook called at the start of shutdown, before cancelling timers and aborting spans.
5112
+ * Override to perform vendor-specific pre-shutdown tasks.
5113
+ */
5114
+ async _preShutdown() {
5115
+ }
5116
+ /**
5117
+ * Hook called at the end of shutdown, after all spans are aborted.
5118
+ * Override to perform vendor-specific cleanup (e.g., flushing).
5119
+ */
5120
+ async _postShutdown() {
5121
+ }
5122
+ /**
5123
+ * Gracefully shut down the exporter.
5124
+ * Cancels all pending cleanup timers, aborts all active spans, and clears state.
5125
+ */
5126
+ async shutdown() {
5127
+ if (this.isDisabled) {
5128
+ return;
5129
+ }
5130
+ this.#shutdownStarted = true;
5131
+ await this._preShutdown();
5132
+ for (const [traceId, timeout] of this.#pendingCleanups) {
5133
+ clearTimeout(timeout);
5134
+ this.logger.debug(`${this.name}: Cancelled pending cleanup on shutdown`, { traceId });
5135
+ }
5136
+ this.#pendingCleanups.clear();
5137
+ const reason = {
5138
+ id: "SHUTDOWN",
5139
+ message: "Observability is shutting down.",
5140
+ domain: "MASTRA_OBSERVABILITY",
5141
+ category: "SYSTEM"
5142
+ };
5143
+ for (const [traceId, traceData] of this.#traceMap) {
5144
+ const orphanedEvents = traceData.getAllQueuedEvents();
5145
+ if (orphanedEvents.length > 0) {
5146
+ this.logger.warn(`${this.name}: Dropping ${orphanedEvents.length} orphaned events on shutdown`, {
5147
+ traceId,
5148
+ orphanedEvents: orphanedEvents.map((e) => ({
5149
+ spanId: e.event.exportedSpan.id,
5150
+ waitingFor: e.waitingFor,
5151
+ attempts: e.attempts
5152
+ }))
5153
+ });
5154
+ }
5155
+ for (const spanId of traceData.activeSpanIds) {
5156
+ const span = traceData.getSpan({ spanId });
5157
+ if (span) {
5158
+ await this._abortSpan({ span, traceData, reason });
5159
+ }
5160
+ }
5161
+ }
5162
+ this.#traceMap.clear();
5163
+ await this._postShutdown();
5164
+ await super.shutdown();
5165
+ }
5166
+ };
4230
5167
  var CloudExporter = class extends BaseExporter {
4231
5168
  name = "mastra-cloud-observability-exporter";
4232
5169
  config;
@@ -5480,10 +6417,39 @@ var ModelSpanTracker = class {
5480
6417
  case "step-finish":
5481
6418
  this.#endStepSpan(chunk.payload);
5482
6419
  break;
6420
+ // Infrastructure chunks - skip creating spans for these
6421
+ // They are either redundant, metadata-only, or error/control flow
5483
6422
  case "raw":
5484
- // Skip raw chunks as they're redundant
6423
+ // Redundant raw data
5485
6424
  case "start":
6425
+ // Stream start marker
5486
6426
  case "finish":
6427
+ // Stream finish marker (step-finish already captures this)
6428
+ case "response-metadata":
6429
+ // Response metadata (not semantic content)
6430
+ case "source":
6431
+ // Source references (metadata)
6432
+ case "file":
6433
+ // Binary file data (too large/not semantic)
6434
+ case "error":
6435
+ // Error handling
6436
+ case "abort":
6437
+ // Abort signal
6438
+ case "tripwire":
6439
+ // Processor rejection
6440
+ case "watch":
6441
+ // Internal watch event
6442
+ case "tool-error":
6443
+ // Tool error handling
6444
+ case "tool-call-approval":
6445
+ // Approval request (not content)
6446
+ case "tool-call-suspended":
6447
+ // Suspension (not content)
6448
+ case "reasoning-signature":
6449
+ // Signature metadata
6450
+ case "redacted-reasoning":
6451
+ // Redacted content metadata
6452
+ case "step-output":
5487
6453
  break;
5488
6454
  case "tool-output":
5489
6455
  this.#handleToolOutputChunk(chunk);
@@ -5498,20 +6464,6 @@ var ModelSpanTracker = class {
5498
6464
  this.#createEventSpan(chunk.type, cleanPayload);
5499
6465
  break;
5500
6466
  }
5501
- // Default: auto-create event span for all other chunk types
5502
- default: {
5503
- let outputPayload = chunk.payload;
5504
- if (outputPayload && typeof outputPayload === "object" && "data" in outputPayload) {
5505
- const typedPayload = outputPayload;
5506
- outputPayload = { ...typedPayload };
5507
- if (typedPayload.data) {
5508
- outputPayload.size = typeof typedPayload.data === "string" ? typedPayload.data.length : typedPayload.data instanceof Uint8Array ? typedPayload.data.length : void 0;
5509
- delete outputPayload.data;
5510
- }
5511
- }
5512
- this.#createEventSpan(chunk.type, outputPayload);
5513
- break;
5514
- }
5515
6467
  }
5516
6468
  }
5517
6469
  })
@@ -5712,15 +6664,15 @@ var BaseSpan = class {
5712
6664
  this.attributes = deepClean(options.attributes, this.deepCleanOptions) || {};
5713
6665
  this.metadata = deepClean(options.metadata, this.deepCleanOptions);
5714
6666
  this.parent = options.parent;
5715
- this.startTime = /* @__PURE__ */ new Date();
6667
+ this.startTime = options.startTime ?? /* @__PURE__ */ new Date();
5716
6668
  this.observabilityInstance = observabilityInstance;
5717
6669
  this.isEvent = options.isEvent ?? false;
5718
6670
  this.isInternal = isSpanInternal(this.type, options.tracingPolicy?.internal);
5719
6671
  this.traceState = options.traceState;
5720
6672
  this.tags = !options.parent && options.tags?.length ? options.tags : void 0;
5721
- this.entityType = options.entityType;
5722
- this.entityId = options.entityId;
5723
- this.entityName = options.entityName;
6673
+ this.entityType = options.entityType ?? options.parent?.entityType;
6674
+ this.entityId = options.entityId ?? options.parent?.entityId;
6675
+ this.entityName = options.entityName ?? options.parent?.entityName;
5724
6676
  if (this.isEvent) {
5725
6677
  this.output = deepClean(options.output, this.deepCleanOptions);
5726
6678
  } else {
@@ -5769,6 +6721,8 @@ var BaseSpan = class {
5769
6721
  }
5770
6722
  /** Returns a lightweight span ready for export */
5771
6723
  exportSpan(includeInternalSpans) {
6724
+ const hideInput = this.traceState?.hideInput ?? false;
6725
+ const hideOutput = this.traceState?.hideOutput ?? false;
5772
6726
  return {
5773
6727
  id: this.id,
5774
6728
  traceId: this.traceId,
@@ -5781,8 +6735,8 @@ var BaseSpan = class {
5781
6735
  metadata: this.metadata,
5782
6736
  startTime: this.startTime,
5783
6737
  endTime: this.endTime,
5784
- input: this.input,
5785
- output: this.output,
6738
+ input: hideInput ? void 0 : this.input,
6739
+ output: hideOutput ? void 0 : this.output,
5786
6740
  errorInfo: this.errorInfo,
5787
6741
  isEvent: this.isEvent,
5788
6742
  isRootSpan: this.isRootSpan,
@@ -5822,6 +6776,14 @@ var DefaultSpan = class extends BaseSpan {
5822
6776
  traceId;
5823
6777
  constructor(options, observabilityInstance) {
5824
6778
  super(options, observabilityInstance);
6779
+ if (options.spanId && options.traceId) {
6780
+ this.id = options.spanId;
6781
+ this.traceId = options.traceId;
6782
+ if (options.parentSpanId) {
6783
+ this.parentSpanId = options.parentSpanId;
6784
+ }
6785
+ return;
6786
+ }
5825
6787
  const bridge = observabilityInstance.getBridge();
5826
6788
  if (bridge && !this.isInternal) {
5827
6789
  const bridgeIds = bridge.createSpan(options);
@@ -6066,8 +7028,12 @@ var BaseObservabilityInstance = class extends base.MastraBase {
6066
7028
  const mergedMetadata = metadata || tracingMetadata ? { ...metadata, ...tracingMetadata } : void 0;
6067
7029
  const enrichedMetadata = this.extractMetadataFromRequestContext(requestContext, mergedMetadata, traceState);
6068
7030
  const tags = !options.parent ? tracingOptions?.tags : void 0;
7031
+ const traceId = !options.parent ? options.traceId ?? tracingOptions?.traceId : options.traceId;
7032
+ const parentSpanId = !options.parent ? options.parentSpanId ?? tracingOptions?.parentSpanId : options.parentSpanId;
6069
7033
  const span = this.createSpan({
6070
7034
  ...rest,
7035
+ traceId,
7036
+ parentSpanId,
6071
7037
  metadata: enrichedMetadata,
6072
7038
  traceState,
6073
7039
  tags
@@ -6080,6 +7046,37 @@ var BaseObservabilityInstance = class extends base.MastraBase {
6080
7046
  }
6081
7047
  return span;
6082
7048
  }
7049
+ /**
7050
+ * Rebuild a span from exported data for lifecycle operations.
7051
+ * Used by durable execution engines (e.g., Inngest) to end/update spans
7052
+ * that were created in a previous durable operation.
7053
+ *
7054
+ * The rebuilt span:
7055
+ * - Does NOT emit SPAN_STARTED (assumes original span already did)
7056
+ * - Can have end(), update(), error() called on it
7057
+ * - Will emit SPAN_ENDED or SPAN_UPDATED when those methods are called
7058
+ *
7059
+ * @param cached - The exported span data to rebuild from
7060
+ * @returns A span that can have lifecycle methods called on it
7061
+ */
7062
+ rebuildSpan(cached) {
7063
+ const span = this.createSpan({
7064
+ name: cached.name,
7065
+ type: cached.type,
7066
+ traceId: cached.traceId,
7067
+ spanId: cached.id,
7068
+ parentSpanId: cached.parentSpanId,
7069
+ startTime: cached.startTime instanceof Date ? cached.startTime : new Date(cached.startTime),
7070
+ input: cached.input,
7071
+ attributes: cached.attributes,
7072
+ metadata: cached.metadata,
7073
+ entityType: cached.entityType,
7074
+ entityId: cached.entityId,
7075
+ entityName: cached.entityName
7076
+ });
7077
+ this.wireSpanLifecycle(span);
7078
+ return span;
7079
+ }
6083
7080
  // ============================================================================
6084
7081
  // Configuration Management
6085
7082
  // ============================================================================
@@ -6182,11 +7179,15 @@ var BaseObservabilityInstance = class extends base.MastraBase {
6182
7179
  const configuredKeys = this.config.requestContextKeys ?? [];
6183
7180
  const additionalKeys = tracingOptions?.requestContextKeys ?? [];
6184
7181
  const allKeys = [...configuredKeys, ...additionalKeys];
6185
- if (allKeys.length === 0) {
7182
+ const hideInput = tracingOptions?.hideInput;
7183
+ const hideOutput = tracingOptions?.hideOutput;
7184
+ if (allKeys.length === 0 && !hideInput && !hideOutput) {
6186
7185
  return void 0;
6187
7186
  }
6188
7187
  return {
6189
- requestContextKeys: allKeys
7188
+ requestContextKeys: allKeys,
7189
+ ...hideInput !== void 0 && { hideInput },
7190
+ ...hideOutput !== void 0 && { hideOutput }
6190
7191
  };
6191
7192
  }
6192
7193
  /**
@@ -6732,6 +7733,8 @@ exports.Observability = Observability;
6732
7733
  exports.SamplingStrategyType = SamplingStrategyType;
6733
7734
  exports.SensitiveDataFilter = SensitiveDataFilter;
6734
7735
  exports.TestExporter = TestExporter;
7736
+ exports.TraceData = TraceData;
7737
+ exports.TrackingExporter = TrackingExporter;
6735
7738
  exports.buildTracingOptions = buildTracingOptions;
6736
7739
  exports.deepClean = deepClean;
6737
7740
  exports.getExternalParentId = getExternalParentId;