@mastra/observability 1.17.1-alpha.1 → 1.17.1

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
@@ -192,6 +192,12 @@ const LOGGER_METHODS = [
192
192
  "warn",
193
193
  "error"
194
194
  ];
195
+ /** Keys whose value decides the outcome in `shouldStripEntry()`. */
196
+ const VALUE_STRIP_KEYS = /* @__PURE__ */ new Set([
197
+ "logger",
198
+ "tracingContext",
199
+ ...FUNCTION_KEYS_TO_STRIP
200
+ ]);
195
201
  const DEFAULT_DEEP_CLEAN_OPTIONS = Object.freeze({
196
202
  keysToStrip: [],
197
203
  maxDepth: 8,
@@ -273,6 +279,25 @@ function shouldStripEntry(key, value, stripSet) {
273
279
  if (key === "logger") return typeof value === "function" || isLoggerLike(value);
274
280
  return FUNCTION_KEYS_TO_STRIP.has(key) && typeof value === "function";
275
281
  }
282
+ /**
283
+ * Whether an entry past the object-key limit would have been stripped anyway.
284
+ *
285
+ * The entry is dropped either way, so the value is taken from its property descriptor
286
+ * rather than read: a getter must not run for data that is being discarded. That keeps
287
+ * the truncation count the same wherever a runtime-shaped key sits. An accessor cannot
288
+ * be classified without invoking it, so it is left to the limit and counted.
289
+ */
290
+ function wouldBeStripped(key, val, stripSet) {
291
+ if (!VALUE_STRIP_KEYS.has(key)) return false;
292
+ let descriptor;
293
+ try {
294
+ descriptor = Object.getOwnPropertyDescriptor(val, key);
295
+ } catch {
296
+ return false;
297
+ }
298
+ if (!descriptor || !("value" in descriptor)) return false;
299
+ return shouldStripEntry(key, descriptor.value, stripSet);
300
+ }
276
301
  function restoreSerializedMapKey(keyType, key) {
277
302
  switch (keyType) {
278
303
  case "undefined": return;
@@ -458,25 +483,22 @@ function deepClean(value, options = DEFAULT_DEEP_CLEAN_OPTIONS) {
458
483
  return formatSerializationError(error);
459
484
  }
460
485
  let keyCount = 0;
486
+ let omittedByLimit = 0;
461
487
  for (const key of keys) {
462
488
  if (stripSet.has(key)) continue;
489
+ if (keyCount >= maxObjectKeys) {
490
+ if (!wouldBeStripped(key, val, stripSet)) omittedByLimit++;
491
+ continue;
492
+ }
463
493
  let rawValue;
464
494
  try {
465
495
  rawValue = val[key];
466
496
  } catch (error) {
467
- if (keyCount >= maxObjectKeys) {
468
- cleaned["__truncated"] = `${keys.length - keyCount} more keys omitted`;
469
- break;
470
- }
471
497
  cleaned[key] = formatSerializationError(error);
472
498
  keyCount++;
473
499
  continue;
474
500
  }
475
501
  if (shouldStripEntry(key, rawValue, stripSet)) continue;
476
- if (keyCount >= maxObjectKeys) {
477
- cleaned["__truncated"] = `${keys.length - keyCount} more keys omitted`;
478
- break;
479
- }
480
502
  try {
481
503
  cleaned[key] = helper(rawValue, depth + 1);
482
504
  keyCount++;
@@ -485,6 +507,7 @@ function deepClean(value, options = DEFAULT_DEEP_CLEAN_OPTIONS) {
485
507
  keyCount++;
486
508
  }
487
509
  }
510
+ if (omittedByLimit > 0) cleaned["__truncated"] = `${omittedByLimit} more keys omitted`;
488
511
  return cleaned;
489
512
  } finally {
490
513
  if (typeof val === "object" && val !== null) ancestors.delete(val);