@mastra/observability 1.0.0-beta.12 → 1.0.0-beta.13

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.js CHANGED
@@ -4253,6 +4253,18 @@ var BaseExporter = class {
4253
4253
  const processedEvent = await this.applySpanFormatter(event);
4254
4254
  await this._exportTracingEvent(processedEvent);
4255
4255
  }
4256
+ /**
4257
+ * Force flush any buffered/queued spans without shutting down the exporter.
4258
+ *
4259
+ * This is useful in serverless environments where you need to ensure spans
4260
+ * are exported before the runtime instance is terminated, while keeping
4261
+ * the exporter active for future requests.
4262
+ *
4263
+ * Default implementation is a no-op. Override to add flush logic.
4264
+ */
4265
+ async flush() {
4266
+ this.logger.debug(`${this.name} flush called (no-op in base class)`);
4267
+ }
4256
4268
  /**
4257
4269
  * Shutdown the exporter and clean up resources
4258
4270
  *
@@ -5140,8 +5152,31 @@ var TrackingExporter = class extends BaseExporter {
5140
5152
  return this.#traceMap.size;
5141
5153
  }
5142
5154
  // ============================================================================
5143
- // Shutdown Hooks (Override in subclass as needed)
5155
+ // Flush and Shutdown Hooks (Override in subclass as needed)
5144
5156
  // ============================================================================
5157
+ /**
5158
+ * Hook called by flush() to perform vendor-specific flush logic.
5159
+ * Override to send buffered data to the vendor's API.
5160
+ *
5161
+ * Unlike _postShutdown(), this method should NOT release resources,
5162
+ * as the exporter will continue to be used after flushing.
5163
+ */
5164
+ async _flush() {
5165
+ }
5166
+ /**
5167
+ * Force flush any buffered data without shutting down the exporter.
5168
+ * This is useful in serverless environments where you need to ensure spans
5169
+ * are exported before the runtime instance is terminated.
5170
+ *
5171
+ * Subclasses should override _flush() to implement vendor-specific flush logic.
5172
+ */
5173
+ async flush() {
5174
+ if (this.isDisabled) {
5175
+ return;
5176
+ }
5177
+ this.logger.debug(`${this.name}: Flushing`);
5178
+ await this._flush();
5179
+ }
5145
5180
  /**
5146
5181
  * Hook called at the start of shutdown, before cancelling timers and aborting spans.
5147
5182
  * Override to perform vendor-specific pre-shutdown tasks.
@@ -5310,7 +5345,7 @@ var CloudExporter = class extends BaseExporter {
5310
5345
  });
5311
5346
  }, this.cloudConfig.maxBatchWaitMs);
5312
5347
  }
5313
- async flush() {
5348
+ async flushBuffer() {
5314
5349
  if (this.flushTimer) {
5315
5350
  clearTimeout(this.flushTimer);
5316
5351
  this.flushTimer = null;
@@ -5366,6 +5401,22 @@ var CloudExporter = class extends BaseExporter {
5366
5401
  this.buffer.firstEventTime = void 0;
5367
5402
  this.buffer.totalSize = 0;
5368
5403
  }
5404
+ /**
5405
+ * Force flush any buffered spans without shutting down the exporter.
5406
+ * This is useful in serverless environments where you need to ensure spans
5407
+ * are exported before the runtime instance is terminated.
5408
+ */
5409
+ async flush() {
5410
+ if (this.isDisabled) {
5411
+ return;
5412
+ }
5413
+ if (this.buffer.totalSize > 0) {
5414
+ this.logger.debug("Flushing buffered events", {
5415
+ bufferedEvents: this.buffer.totalSize
5416
+ });
5417
+ await this.flushBuffer();
5418
+ }
5419
+ }
5369
5420
  async shutdown() {
5370
5421
  if (this.isDisabled) {
5371
5422
  return;
@@ -5374,27 +5425,22 @@ var CloudExporter = class extends BaseExporter {
5374
5425
  clearTimeout(this.flushTimer);
5375
5426
  this.flushTimer = null;
5376
5427
  }
5377
- if (this.buffer.totalSize > 0) {
5378
- this.logger.info("Flushing remaining events on shutdown", {
5379
- remainingEvents: this.buffer.totalSize
5380
- });
5381
- try {
5382
- await this.flush();
5383
- } catch (error) {
5384
- const mastraError = new MastraError(
5385
- {
5386
- id: `CLOUD_EXPORTER_FAILED_TO_FLUSH_REMAINING_EVENTS_DURING_SHUTDOWN`,
5387
- domain: ErrorDomain.MASTRA_OBSERVABILITY,
5388
- category: ErrorCategory.USER,
5389
- details: {
5390
- remainingEvents: this.buffer.totalSize
5391
- }
5392
- },
5393
- error
5394
- );
5395
- this.logger.trackException(mastraError);
5396
- this.logger.error("Failed to flush remaining events during shutdown", mastraError);
5397
- }
5428
+ try {
5429
+ await this.flush();
5430
+ } catch (error) {
5431
+ const mastraError = new MastraError(
5432
+ {
5433
+ id: `CLOUD_EXPORTER_FAILED_TO_FLUSH_REMAINING_EVENTS_DURING_SHUTDOWN`,
5434
+ domain: ErrorDomain.MASTRA_OBSERVABILITY,
5435
+ category: ErrorCategory.USER,
5436
+ details: {
5437
+ remainingEvents: this.buffer.totalSize
5438
+ }
5439
+ },
5440
+ error
5441
+ );
5442
+ this.logger.trackException(mastraError);
5443
+ this.logger.error("Failed to flush remaining events during shutdown", mastraError);
5398
5444
  }
5399
5445
  this.logger.info("CloudExporter shutdown complete");
5400
5446
  }
@@ -5698,7 +5744,7 @@ var DefaultExporter = class extends BaseExporter {
5698
5744
  clearTimeout(this.#flushTimer);
5699
5745
  }
5700
5746
  this.#flushTimer = setTimeout(() => {
5701
- this.flush().catch((error) => {
5747
+ this.flushBuffer().catch((error) => {
5702
5748
  this.logger.error("Scheduled flush failed", {
5703
5749
  error: error instanceof Error ? error.message : String(error)
5704
5750
  });
@@ -5832,7 +5878,7 @@ var DefaultExporter = class extends BaseExporter {
5832
5878
  handleBatchWithUpdatesEvent(event) {
5833
5879
  this.addToBuffer(event);
5834
5880
  if (this.shouldFlush()) {
5835
- this.flush().catch((error) => {
5881
+ this.flushBuffer().catch((error) => {
5836
5882
  this.logger.error("Batch flush failed", {
5837
5883
  error: error instanceof Error ? error.message : String(error)
5838
5884
  });
@@ -5848,7 +5894,7 @@ var DefaultExporter = class extends BaseExporter {
5848
5894
  if (event.type === TracingEventType.SPAN_ENDED) {
5849
5895
  this.addToBuffer(event);
5850
5896
  if (this.shouldFlush()) {
5851
- this.flush().catch((error) => {
5897
+ this.flushBuffer().catch((error) => {
5852
5898
  this.logger.error("Batch flush failed", {
5853
5899
  error: error instanceof Error ? error.message : String(error)
5854
5900
  });
@@ -5865,9 +5911,9 @@ var DefaultExporter = class extends BaseExporter {
5865
5911
  return this.#config.retryDelayMs * Math.pow(2, attempt);
5866
5912
  }
5867
5913
  /**
5868
- * Flushes the current buffer to storage with retry logic
5914
+ * Flushes the current buffer to storage with retry logic (internal implementation)
5869
5915
  */
5870
- async flush() {
5916
+ async flushBuffer() {
5871
5917
  if (!this.#observability) {
5872
5918
  this.logger.debug("Cannot flush traces. Observability storage is not initialized");
5873
5919
  return;
@@ -5974,23 +6020,25 @@ var DefaultExporter = class extends BaseExporter {
5974
6020
  break;
5975
6021
  }
5976
6022
  }
6023
+ /**
6024
+ * Force flush any buffered spans without shutting down the exporter.
6025
+ * This is useful in serverless environments where you need to ensure spans
6026
+ * are exported before the runtime instance is terminated.
6027
+ */
6028
+ async flush() {
6029
+ if (this.buffer.totalSize > 0) {
6030
+ this.logger.debug("Flushing buffered events", {
6031
+ bufferedEvents: this.buffer.totalSize
6032
+ });
6033
+ await this.flushBuffer();
6034
+ }
6035
+ }
5977
6036
  async shutdown() {
5978
6037
  if (this.#flushTimer) {
5979
6038
  clearTimeout(this.#flushTimer);
5980
6039
  this.#flushTimer = null;
5981
6040
  }
5982
- if (this.buffer.totalSize > 0) {
5983
- this.logger.info("Flushing remaining events on shutdown", {
5984
- remainingEvents: this.buffer.totalSize
5985
- });
5986
- try {
5987
- await this.flush();
5988
- } catch (error) {
5989
- this.logger.error("Failed to flush remaining events during shutdown", {
5990
- error: error instanceof Error ? error.message : String(error)
5991
- });
5992
- }
5993
- }
6041
+ await this.flush();
5994
6042
  this.logger.info("DefaultExporter shutdown complete");
5995
6043
  }
5996
6044
  };
@@ -7364,6 +7412,29 @@ var BaseObservabilityInstance = class extends MastraBase {
7364
7412
  this.logger.debug(`[Observability] Initialization started [name=${this.name}]`);
7365
7413
  this.logger.info(`[Observability] Initialized successfully [name=${this.name}]`);
7366
7414
  }
7415
+ /**
7416
+ * Force flush any buffered/queued spans from all exporters and the bridge
7417
+ * without shutting down the observability instance.
7418
+ *
7419
+ * This is useful in serverless environments (like Vercel's fluid compute) where
7420
+ * you need to ensure all spans are exported before the runtime instance is
7421
+ * terminated, while keeping the observability system active for future requests.
7422
+ */
7423
+ async flush() {
7424
+ this.logger.debug(`[Observability] Flush started [name=${this.name}]`);
7425
+ const flushPromises = [...this.exporters.map((e) => e.flush())];
7426
+ if (this.config.bridge) {
7427
+ flushPromises.push(this.config.bridge.flush());
7428
+ }
7429
+ const results = await Promise.allSettled(flushPromises);
7430
+ results.forEach((result, index) => {
7431
+ if (result.status === "rejected") {
7432
+ const targetName = index < this.exporters.length ? this.exporters[index]?.name : "bridge";
7433
+ this.logger.error(`[Observability] Flush error [target=${targetName}]`, result.reason);
7434
+ }
7435
+ });
7436
+ this.logger.debug(`[Observability] Flush completed [name=${this.name}]`);
7437
+ }
7367
7438
  /**
7368
7439
  * Shutdown Observability and clean up resources
7369
7440
  */