@mastra/observability 1.16.0 → 1.16.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5946,6 +5946,7 @@ function resolveTracingStorageStrategy(config, observabilityStorage, storageName
5946
5946
  }
5947
5947
  return observabilityStrategy.preferred;
5948
5948
  }
5949
+ var FLUSH_SUCCEEDED = { failed: false };
5949
5950
  var DefaultExporter = class extends BaseExporter {
5950
5951
  name = "mastra-default-observability-exporter";
5951
5952
  #config;
@@ -6040,17 +6041,37 @@ var DefaultExporter = class extends BaseExporter {
6040
6041
  /**
6041
6042
  * Schedules a flush using setTimeout
6042
6043
  */
6043
- scheduleFlush() {
6044
+ scheduleFlush(delayMs = this.#config.maxBatchWaitMs) {
6044
6045
  if (this.#flushTimer) {
6045
6046
  clearTimeout(this.#flushTimer);
6046
6047
  }
6047
6048
  this.#flushTimer = setTimeout(() => {
6049
+ this.#flushTimer = void 0;
6048
6050
  this.flushBuffer().catch((error) => {
6049
6051
  this.logger.error("Scheduled flush failed", {
6050
6052
  error: error instanceof Error ? error.message : String(error)
6051
6053
  });
6052
6054
  });
6053
- }, this.#config.maxBatchWaitMs);
6055
+ }, delayMs);
6056
+ }
6057
+ retryDelay(retryAttempt) {
6058
+ return this.#config.retryDelayMs * 2 ** (retryAttempt - 1);
6059
+ }
6060
+ retryAttempt(events) {
6061
+ return events.reduce((earliestAttempt, event) => {
6062
+ if (event.retryCount > this.#config.maxRetries) return earliestAttempt;
6063
+ return earliestAttempt === void 0 ? event.retryCount : Math.min(earliestAttempt, event.retryCount);
6064
+ }, void 0);
6065
+ }
6066
+ logStorageFailure(signal, events, retryAttempt, error) {
6067
+ this.logger.warn("Failed to persist observability events", {
6068
+ signal,
6069
+ eventCount: events.length,
6070
+ retryAttempt: retryAttempt ?? events.reduce((latestAttempt, event) => Math.max(latestAttempt, event.retryCount), 0),
6071
+ maxRetries: this.#config.maxRetries,
6072
+ ...retryAttempt === void 0 ? {} : { nextRetryDelayMs: this.retryDelay(retryAttempt) },
6073
+ error: error instanceof Error ? error.message : String(error)
6074
+ });
6054
6075
  }
6055
6076
  /**
6056
6077
  * Checks flush triggers and schedules/triggers flush as needed.
@@ -6097,22 +6118,26 @@ var DefaultExporter = class extends BaseExporter {
6097
6118
  * On other errors, re-adds events to the buffer for retry.
6098
6119
  */
6099
6120
  async flushCreates(signal, events, storageCall) {
6100
- if (events.length === 0) return;
6121
+ if (events.length === 0) return FLUSH_SUCCEEDED;
6101
6122
  if (this.#unsupportedSignals.has(signal)) {
6102
6123
  this.emitDrop(signal, "unsupported-storage", events.length);
6103
- return;
6124
+ return { failed: true };
6104
6125
  }
6105
6126
  try {
6106
6127
  await storageCall(events);
6128
+ return FLUSH_SUCCEEDED;
6107
6129
  } catch (error) {
6108
6130
  if (error instanceof MastraError && error.domain === ErrorDomain.MASTRA_OBSERVABILITY && error.id.endsWith("_NOT_IMPLEMENTED")) {
6109
6131
  this.logger.warn(error.message);
6110
6132
  this.#unsupportedSignals.add(signal);
6111
6133
  this.emitDrop(signal, "unsupported-storage", events.length, error);
6112
- } else {
6113
- const dropped = this.#eventBuffer.reAddCreates(events);
6114
- this.emitDrop(signal, "retry-exhausted", dropped.length, error);
6134
+ return { failed: true };
6115
6135
  }
6136
+ const dropped = this.#eventBuffer.reAddCreates(events);
6137
+ const retryAttempt = this.retryAttempt(events);
6138
+ this.logStorageFailure(signal, events, retryAttempt, error);
6139
+ this.emitDrop(signal, "retry-exhausted", dropped.length, error);
6140
+ return { failed: true, retryAttempt };
6116
6141
  }
6117
6142
  }
6118
6143
  /**
@@ -6121,10 +6146,10 @@ var DefaultExporter = class extends BaseExporter {
6121
6146
  */
6122
6147
  async flushSpanUpdates(events, deferredUpdates, isEnd) {
6123
6148
  const deferredCountAtEntry = deferredUpdates.length;
6124
- if (events.length === 0) return;
6149
+ if (events.length === 0) return FLUSH_SUCCEEDED;
6125
6150
  if (this.#unsupportedSignals.has("tracing")) {
6126
6151
  this.emitDrop("tracing", "unsupported-storage", events.length);
6127
- return;
6152
+ return { failed: true };
6128
6153
  }
6129
6154
  const partials = [];
6130
6155
  for (const event of events) {
@@ -6139,26 +6164,30 @@ var DefaultExporter = class extends BaseExporter {
6139
6164
  deferredUpdates.push(event);
6140
6165
  }
6141
6166
  }
6142
- if (partials.length === 0) return;
6167
+ if (partials.length === 0) return FLUSH_SUCCEEDED;
6143
6168
  try {
6144
6169
  await this.#observabilityStorage.batchUpdateSpans({ records: partials });
6145
6170
  if (isEnd) {
6146
6171
  this.#eventBuffer.endFinishedSpans({ records: partials });
6147
6172
  }
6173
+ return FLUSH_SUCCEEDED;
6148
6174
  } catch (error) {
6149
6175
  if (error instanceof MastraError && error.domain === ErrorDomain.MASTRA_OBSERVABILITY && error.id.endsWith("_NOT_IMPLEMENTED")) {
6150
6176
  this.logger.warn(error.message);
6151
6177
  this.#unsupportedSignals.add("tracing");
6152
6178
  deferredUpdates.length = 0;
6153
6179
  this.emitDrop("tracing", "unsupported-storage", events.length + deferredCountAtEntry, error);
6154
- } else {
6155
- const newlyDeferred = deferredUpdates.length - deferredCountAtEntry;
6156
- if (newlyDeferred > 0) {
6157
- deferredUpdates.splice(deferredUpdates.length - newlyDeferred, newlyDeferred);
6158
- }
6159
- const dropped = this.#eventBuffer.reAddUpdates(events);
6160
- this.emitDrop("tracing", "retry-exhausted", dropped.length, error);
6180
+ return { failed: true };
6181
+ }
6182
+ const newlyDeferred = deferredUpdates.length - deferredCountAtEntry;
6183
+ if (newlyDeferred > 0) {
6184
+ deferredUpdates.splice(deferredUpdates.length - newlyDeferred, newlyDeferred);
6161
6185
  }
6186
+ const dropped = this.#eventBuffer.reAddUpdates(events);
6187
+ const retryAttempt = this.retryAttempt(events);
6188
+ this.logStorageFailure("tracing", events, retryAttempt, error);
6189
+ this.emitDrop("tracing", "retry-exhausted", dropped.length, error);
6190
+ return { failed: true, retryAttempt };
6162
6191
  }
6163
6192
  }
6164
6193
  /**
@@ -6226,7 +6255,7 @@ var DefaultExporter = class extends BaseExporter {
6226
6255
  break;
6227
6256
  }
6228
6257
  }
6229
- await Promise.all([
6258
+ const flushResults = await Promise.all([
6230
6259
  this.flushCreates(
6231
6260
  "feedback",
6232
6261
  createFeedbackEvents,
@@ -6254,25 +6283,36 @@ var DefaultExporter = class extends BaseExporter {
6254
6283
  })
6255
6284
  ]);
6256
6285
  const deferredUpdates = [];
6257
- await this.flushSpanUpdates(updateSpanEvents, deferredUpdates, false);
6258
- await this.flushSpanUpdates(endSpanEvents, deferredUpdates, true);
6286
+ flushResults.push(await this.flushSpanUpdates(updateSpanEvents, deferredUpdates, false));
6287
+ flushResults.push(await this.flushSpanUpdates(endSpanEvents, deferredUpdates, true));
6288
+ let deferredDropCount = 0;
6259
6289
  if (deferredUpdates.length > 0) {
6260
6290
  if (this.#unsupportedSignals.has("tracing")) {
6261
- this.emitDrop("tracing", "unsupported-storage", deferredUpdates.length);
6291
+ deferredDropCount = deferredUpdates.length;
6292
+ this.emitDrop("tracing", "unsupported-storage", deferredDropCount);
6262
6293
  deferredUpdates.length = 0;
6263
6294
  } else {
6264
6295
  const dropped = this.#eventBuffer.reAddUpdates(deferredUpdates);
6265
- this.emitDrop("tracing", "retry-exhausted", dropped.length);
6296
+ deferredDropCount = dropped.length;
6297
+ this.emitDrop("tracing", "retry-exhausted", deferredDropCount);
6266
6298
  }
6267
6299
  }
6268
- const elapsed = Date.now() - startTime;
6269
- this.logger.debug("Batch flushed", {
6270
- strategy: this.#resolvedStrategy,
6271
- batchSize,
6272
- durationMs: elapsed,
6273
- deferredUpdates: deferredUpdates.length > 0 ? deferredUpdates.length : void 0
6274
- });
6275
- return;
6300
+ const retryAttempt = flushResults.reduce((earliestAttempt, result) => {
6301
+ if (result.retryAttempt === void 0) return earliestAttempt;
6302
+ return earliestAttempt === void 0 ? result.retryAttempt : Math.min(earliestAttempt, result.retryAttempt);
6303
+ }, void 0);
6304
+ if (retryAttempt !== void 0) {
6305
+ this.scheduleFlush(this.retryDelay(retryAttempt));
6306
+ }
6307
+ if (!flushResults.some((result) => result.failed) && deferredDropCount === 0) {
6308
+ const elapsed = Date.now() - startTime;
6309
+ this.logger.debug("Batch flushed", {
6310
+ strategy: this.#resolvedStrategy,
6311
+ batchSize,
6312
+ durationMs: elapsed,
6313
+ deferredUpdates: deferredUpdates.length > 0 ? deferredUpdates.length : void 0
6314
+ });
6315
+ }
6276
6316
  }
6277
6317
  async _exportTracingEvent(event) {
6278
6318
  await this.waitForInit();
@@ -6349,6 +6389,10 @@ var DefaultExporter = class extends BaseExporter {
6349
6389
  this.#flushTimer = void 0;
6350
6390
  }
6351
6391
  await this.flush();
6392
+ if (this.#flushTimer) {
6393
+ clearTimeout(this.#flushTimer);
6394
+ this.#flushTimer = void 0;
6395
+ }
6352
6396
  this.logger.info("DefaultExporter shutdown complete");
6353
6397
  }
6354
6398
  };
@@ -6881,6 +6925,7 @@ function resolveTracingStorageStrategy2(config, observabilityStorage, storageNam
6881
6925
  }
6882
6926
  return observabilityStrategy.preferred;
6883
6927
  }
6928
+ var FLUSH_SUCCEEDED2 = { failed: false };
6884
6929
  var MastraStorageExporter = class extends BaseExporter {
6885
6930
  name = "mastra-storage-exporter";
6886
6931
  #config;
@@ -6975,17 +7020,37 @@ var MastraStorageExporter = class extends BaseExporter {
6975
7020
  /**
6976
7021
  * Schedules a flush using setTimeout
6977
7022
  */
6978
- scheduleFlush() {
7023
+ scheduleFlush(delayMs = this.#config.maxBatchWaitMs) {
6979
7024
  if (this.#flushTimer) {
6980
7025
  clearTimeout(this.#flushTimer);
6981
7026
  }
6982
7027
  this.#flushTimer = setTimeout(() => {
7028
+ this.#flushTimer = void 0;
6983
7029
  this.flushBuffer().catch((error) => {
6984
7030
  this.logger.error("Scheduled flush failed", {
6985
7031
  error: error instanceof Error ? error.message : String(error)
6986
7032
  });
6987
7033
  });
6988
- }, this.#config.maxBatchWaitMs);
7034
+ }, delayMs);
7035
+ }
7036
+ retryDelay(retryAttempt) {
7037
+ return this.#config.retryDelayMs * 2 ** (retryAttempt - 1);
7038
+ }
7039
+ retryAttempt(events) {
7040
+ return events.reduce((earliestAttempt, event) => {
7041
+ if (event.retryCount > this.#config.maxRetries) return earliestAttempt;
7042
+ return earliestAttempt === void 0 ? event.retryCount : Math.min(earliestAttempt, event.retryCount);
7043
+ }, void 0);
7044
+ }
7045
+ logStorageFailure(signal, events, retryAttempt, error) {
7046
+ this.logger.warn("Failed to persist observability events", {
7047
+ signal,
7048
+ eventCount: events.length,
7049
+ retryAttempt: retryAttempt ?? events.reduce((latestAttempt, event) => Math.max(latestAttempt, event.retryCount), 0),
7050
+ maxRetries: this.#config.maxRetries,
7051
+ ...retryAttempt === void 0 ? {} : { nextRetryDelayMs: this.retryDelay(retryAttempt) },
7052
+ error: error instanceof Error ? error.message : String(error)
7053
+ });
6989
7054
  }
6990
7055
  /**
6991
7056
  * Checks flush triggers and schedules/triggers flush as needed.
@@ -7032,22 +7097,26 @@ var MastraStorageExporter = class extends BaseExporter {
7032
7097
  * On other errors, re-adds events to the buffer for retry.
7033
7098
  */
7034
7099
  async flushCreates(signal, events, storageCall) {
7035
- if (events.length === 0) return;
7100
+ if (events.length === 0) return FLUSH_SUCCEEDED2;
7036
7101
  if (this.#unsupportedSignals.has(signal)) {
7037
7102
  this.emitDrop(signal, "unsupported-storage", events.length);
7038
- return;
7103
+ return { failed: true };
7039
7104
  }
7040
7105
  try {
7041
7106
  await storageCall(events);
7107
+ return FLUSH_SUCCEEDED2;
7042
7108
  } catch (error) {
7043
7109
  if (error instanceof MastraError && error.domain === ErrorDomain.MASTRA_OBSERVABILITY && error.id.endsWith("_NOT_IMPLEMENTED")) {
7044
7110
  this.logger.warn(error.message);
7045
7111
  this.#unsupportedSignals.add(signal);
7046
7112
  this.emitDrop(signal, "unsupported-storage", events.length, error);
7047
- } else {
7048
- const dropped = this.#eventBuffer.reAddCreates(events);
7049
- this.emitDrop(signal, "retry-exhausted", dropped.length, error);
7113
+ return { failed: true };
7050
7114
  }
7115
+ const dropped = this.#eventBuffer.reAddCreates(events);
7116
+ const retryAttempt = this.retryAttempt(events);
7117
+ this.logStorageFailure(signal, events, retryAttempt, error);
7118
+ this.emitDrop(signal, "retry-exhausted", dropped.length, error);
7119
+ return { failed: true, retryAttempt };
7051
7120
  }
7052
7121
  }
7053
7122
  /**
@@ -7056,10 +7125,10 @@ var MastraStorageExporter = class extends BaseExporter {
7056
7125
  */
7057
7126
  async flushSpanUpdates(events, deferredUpdates, isEnd) {
7058
7127
  const deferredCountAtEntry = deferredUpdates.length;
7059
- if (events.length === 0) return;
7128
+ if (events.length === 0) return FLUSH_SUCCEEDED2;
7060
7129
  if (this.#unsupportedSignals.has("tracing")) {
7061
7130
  this.emitDrop("tracing", "unsupported-storage", events.length);
7062
- return;
7131
+ return { failed: true };
7063
7132
  }
7064
7133
  const partials = [];
7065
7134
  for (const event of events) {
@@ -7074,26 +7143,30 @@ var MastraStorageExporter = class extends BaseExporter {
7074
7143
  deferredUpdates.push(event);
7075
7144
  }
7076
7145
  }
7077
- if (partials.length === 0) return;
7146
+ if (partials.length === 0) return FLUSH_SUCCEEDED2;
7078
7147
  try {
7079
7148
  await this.#observabilityStorage.batchUpdateSpans({ records: partials });
7080
7149
  if (isEnd) {
7081
7150
  this.#eventBuffer.endFinishedSpans({ records: partials });
7082
7151
  }
7152
+ return FLUSH_SUCCEEDED2;
7083
7153
  } catch (error) {
7084
7154
  if (error instanceof MastraError && error.domain === ErrorDomain.MASTRA_OBSERVABILITY && error.id.endsWith("_NOT_IMPLEMENTED")) {
7085
7155
  this.logger.warn(error.message);
7086
7156
  this.#unsupportedSignals.add("tracing");
7087
7157
  deferredUpdates.length = 0;
7088
7158
  this.emitDrop("tracing", "unsupported-storage", events.length + deferredCountAtEntry, error);
7089
- } else {
7090
- const newlyDeferred = deferredUpdates.length - deferredCountAtEntry;
7091
- if (newlyDeferred > 0) {
7092
- deferredUpdates.splice(deferredUpdates.length - newlyDeferred, newlyDeferred);
7093
- }
7094
- const dropped = this.#eventBuffer.reAddUpdates(events);
7095
- this.emitDrop("tracing", "retry-exhausted", dropped.length, error);
7159
+ return { failed: true };
7160
+ }
7161
+ const newlyDeferred = deferredUpdates.length - deferredCountAtEntry;
7162
+ if (newlyDeferred > 0) {
7163
+ deferredUpdates.splice(deferredUpdates.length - newlyDeferred, newlyDeferred);
7096
7164
  }
7165
+ const dropped = this.#eventBuffer.reAddUpdates(events);
7166
+ const retryAttempt = this.retryAttempt(events);
7167
+ this.logStorageFailure("tracing", events, retryAttempt, error);
7168
+ this.emitDrop("tracing", "retry-exhausted", dropped.length, error);
7169
+ return { failed: true, retryAttempt };
7097
7170
  }
7098
7171
  }
7099
7172
  /**
@@ -7161,7 +7234,7 @@ var MastraStorageExporter = class extends BaseExporter {
7161
7234
  break;
7162
7235
  }
7163
7236
  }
7164
- await Promise.all([
7237
+ const flushResults = await Promise.all([
7165
7238
  this.flushCreates(
7166
7239
  "feedback",
7167
7240
  createFeedbackEvents,
@@ -7189,25 +7262,36 @@ var MastraStorageExporter = class extends BaseExporter {
7189
7262
  })
7190
7263
  ]);
7191
7264
  const deferredUpdates = [];
7192
- await this.flushSpanUpdates(updateSpanEvents, deferredUpdates, false);
7193
- await this.flushSpanUpdates(endSpanEvents, deferredUpdates, true);
7265
+ flushResults.push(await this.flushSpanUpdates(updateSpanEvents, deferredUpdates, false));
7266
+ flushResults.push(await this.flushSpanUpdates(endSpanEvents, deferredUpdates, true));
7267
+ let deferredDropCount = 0;
7194
7268
  if (deferredUpdates.length > 0) {
7195
7269
  if (this.#unsupportedSignals.has("tracing")) {
7196
- this.emitDrop("tracing", "unsupported-storage", deferredUpdates.length);
7270
+ deferredDropCount = deferredUpdates.length;
7271
+ this.emitDrop("tracing", "unsupported-storage", deferredDropCount);
7197
7272
  deferredUpdates.length = 0;
7198
7273
  } else {
7199
7274
  const dropped = this.#eventBuffer.reAddUpdates(deferredUpdates);
7200
- this.emitDrop("tracing", "retry-exhausted", dropped.length);
7275
+ deferredDropCount = dropped.length;
7276
+ this.emitDrop("tracing", "retry-exhausted", deferredDropCount);
7201
7277
  }
7202
7278
  }
7203
- const elapsed = Date.now() - startTime;
7204
- this.logger.debug("Batch flushed", {
7205
- strategy: this.#resolvedStrategy,
7206
- batchSize,
7207
- durationMs: elapsed,
7208
- deferredUpdates: deferredUpdates.length > 0 ? deferredUpdates.length : void 0
7209
- });
7210
- return;
7279
+ const retryAttempt = flushResults.reduce((earliestAttempt, result) => {
7280
+ if (result.retryAttempt === void 0) return earliestAttempt;
7281
+ return earliestAttempt === void 0 ? result.retryAttempt : Math.min(earliestAttempt, result.retryAttempt);
7282
+ }, void 0);
7283
+ if (retryAttempt !== void 0) {
7284
+ this.scheduleFlush(this.retryDelay(retryAttempt));
7285
+ }
7286
+ if (!flushResults.some((result) => result.failed) && deferredDropCount === 0) {
7287
+ const elapsed = Date.now() - startTime;
7288
+ this.logger.debug("Batch flushed", {
7289
+ strategy: this.#resolvedStrategy,
7290
+ batchSize,
7291
+ durationMs: elapsed,
7292
+ deferredUpdates: deferredUpdates.length > 0 ? deferredUpdates.length : void 0
7293
+ });
7294
+ }
7211
7295
  }
7212
7296
  async _exportTracingEvent(event) {
7213
7297
  await this.waitForInit();
@@ -7284,6 +7368,10 @@ var MastraStorageExporter = class extends BaseExporter {
7284
7368
  this.#flushTimer = void 0;
7285
7369
  }
7286
7370
  await this.flush();
7371
+ if (this.#flushTimer) {
7372
+ clearTimeout(this.#flushTimer);
7373
+ this.#flushTimer = void 0;
7374
+ }
7287
7375
  this.logger.info("MastraStorageExporter shutdown complete");
7288
7376
  }
7289
7377
  };