@mastra/observability 1.21.1-alpha.0 → 1.21.1-alpha.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.cjs CHANGED
@@ -2219,6 +2219,9 @@ function isDefined(value) {
2219
2219
  * - Google/Gemini: cachedContentTokenCount, thoughtsTokenCount in providerMetadata.google.usageMetadata
2220
2220
  * - OpenRouter: Uses OpenAI-compatible structure (cache tokens in usage)
2221
2221
  *
2222
+ * Kept in sync with `packages/core/src/observability/usage.ts` (duplicated so exporters do not need a newer core).
2223
+ * Change both copies together; `usage.parity.test.ts` fails if they drift.
2224
+ *
2222
2225
  * @param usage - The LanguageModelV2Usage from AI SDK response
2223
2226
  * @param providerMetadata - Optional provider-specific metadata
2224
2227
  * @returns UsageStats with inputDetails and outputDetails
@@ -3195,6 +3198,28 @@ function mergeMetadata$1(parentMetadata, metadata) {
3195
3198
  }
3196
3199
  //#endregion
3197
3200
  //#region src/spans/base.ts
3201
+ const LINEAGE_KEYS = [
3202
+ "parentEntityType",
3203
+ "parentEntityId",
3204
+ "parentEntityName",
3205
+ "parentEntityVersionId",
3206
+ "rootEntityType",
3207
+ "rootEntityId",
3208
+ "rootEntityName",
3209
+ "rootEntityVersionId"
3210
+ ];
3211
+ /** Copy only the lineage fields that have values, so spans don't carry undefined keys */
3212
+ function ownEntityVersionId(span) {
3213
+ return span instanceof BaseSpan ? span.ownEntityVersionId : void 0;
3214
+ }
3215
+ function definedLineage(source) {
3216
+ const lineage = {};
3217
+ for (const key of LINEAGE_KEYS) {
3218
+ const value = source[key];
3219
+ if (value !== void 0 && value !== null) lineage[key] = value;
3220
+ }
3221
+ return lineage;
3222
+ }
3198
3223
  /**
3199
3224
  * Determines if a span type should be considered internal based on flags.
3200
3225
  * Returns false if flags are undefined.
@@ -3316,6 +3341,17 @@ var BaseSpan = class BaseSpan {
3316
3341
  isExcluded;
3317
3342
  /** Cached canonical correlation context for this live span */
3318
3343
  correlationContext;
3344
+ /**
3345
+ * Parent and root entity restored by `rebuildSpan()`. A rebuilt span has no
3346
+ * live `parent`, so its original ancestors are only known from the cached export.
3347
+ */
3348
+ restoredLineage;
3349
+ /**
3350
+ * Version declared for this span's own entity, or inherited from a parent span
3351
+ * of the same entity. Unlike `metadata.entityVersionId`, never an ancestor's
3352
+ * version for a different entity.
3353
+ */
3354
+ ownEntityVersionId;
3319
3355
  /** Child spans that have started but not yet ended */
3320
3356
  #openChildren;
3321
3357
  /** The span whose open-child set currently tracks this span: the parent, or a live ancestor after promotion */
@@ -3353,6 +3389,9 @@ var BaseSpan = class BaseSpan {
3353
3389
  this.entityType = options.entityType ?? entityParent?.entityType;
3354
3390
  this.entityId = options.entityId ?? entityParent?.entityId;
3355
3391
  this.entityName = options.entityName ?? entityParent?.entityName;
3392
+ const declaredVersion = options.metadata?.entityVersionId;
3393
+ const sameEntityParent = entityParent instanceof BaseSpan && entityParent.entityType === this.entityType && entityParent.entityId === this.entityId;
3394
+ this.ownEntityVersionId = typeof declaredVersion === "string" ? declaredVersion : sameEntityParent ? entityParent.ownEntityVersionId : void 0;
3356
3395
  if (this.isExcluded) {
3357
3396
  this.attributes = {};
3358
3397
  return;
@@ -3501,18 +3540,62 @@ var BaseSpan = class BaseSpan {
3501
3540
  current = current.parent;
3502
3541
  }
3503
3542
  }
3504
- /** Build and cache the canonical correlation context for this live span. */
3543
+ /**
3544
+ * Restore the parent and root entity a span had before it was exported and
3545
+ * rebuilt (durable execution), so it and its new children keep their lineage.
3546
+ */
3547
+ restoreEntityLineage(cached) {
3548
+ this.ownEntityVersionId = cached.ownEntityVersionId ?? void 0;
3549
+ const lineage = definedLineage(cached);
3550
+ if (Object.keys(lineage).length > 0) {
3551
+ this.restoredLineage = lineage;
3552
+ this.correlationContext = void 0;
3553
+ }
3554
+ }
3555
+ /**
3556
+ * Build and cache the canonical correlation context for this live span.
3557
+ *
3558
+ * Parent entity: the nearest ancestor that is not internal or excluded, the
3559
+ * same rule used for entity inheritance. Root entity: the top of the
3560
+ * in-process parent chain, which is not necessarily the distributed trace's
3561
+ * root when the trace continues from another service. The root walk does not
3562
+ * skip internal spans, so the root can name an entity whose span is not
3563
+ * exported. Logs, metrics, scores and feedback share these values.
3564
+ *
3565
+ * When the top of the live chain was rebuilt, its original ancestors only
3566
+ * survive in the restored lineage, so it supplies the root and, when no live
3567
+ * ancestor qualifies, the parent.
3568
+ */
3505
3569
  getCorrelationContext() {
3506
3570
  if (this.correlationContext) return this.correlationContext;
3507
3571
  const metadata = this.metadata ?? {};
3508
3572
  const getMetadataString = (key) => typeof metadata[key] === "string" ? metadata[key] : void 0;
3509
- const getSpanMetadataString = (span, key) => {
3510
- const m = span?.metadata;
3511
- return m && typeof m[key] === "string" ? m[key] : void 0;
3512
- };
3513
3573
  const parentSpan = this.getParentSpan(false);
3514
3574
  let rootSpan = this;
3515
3575
  while (rootSpan.parent) rootSpan = rootSpan.parent;
3576
+ const restored = rootSpan instanceof BaseSpan ? rootSpan.restoredLineage : void 0;
3577
+ const parentLineage = parentSpan ? {
3578
+ parentEntityType: parentSpan.entityType,
3579
+ parentEntityId: parentSpan.entityId,
3580
+ parentEntityName: parentSpan.entityName,
3581
+ parentEntityVersionId: ownEntityVersionId(parentSpan)
3582
+ } : {
3583
+ parentEntityType: restored?.parentEntityType,
3584
+ parentEntityId: restored?.parentEntityId,
3585
+ parentEntityName: restored?.parentEntityName,
3586
+ parentEntityVersionId: restored?.parentEntityVersionId
3587
+ };
3588
+ const rootLineage = restored ? {
3589
+ rootEntityType: restored.rootEntityType,
3590
+ rootEntityId: restored.rootEntityId,
3591
+ rootEntityName: restored.rootEntityName,
3592
+ rootEntityVersionId: restored.rootEntityVersionId
3593
+ } : {
3594
+ rootEntityType: rootSpan.entityType,
3595
+ rootEntityId: rootSpan.entityId,
3596
+ rootEntityName: rootSpan.entityName,
3597
+ rootEntityVersionId: ownEntityVersionId(rootSpan)
3598
+ };
3516
3599
  const rootTags = rootSpan.tags?.length ? [...rootSpan.tags] : void 0;
3517
3600
  this.correlationContext = {
3518
3601
  traceId: this.traceId,
@@ -3522,14 +3605,8 @@ var BaseSpan = class BaseSpan {
3522
3605
  entityId: this.entityId,
3523
3606
  entityName: this.entityName,
3524
3607
  entityVersionId: getMetadataString("entityVersionId"),
3525
- parentEntityType: parentSpan?.entityType,
3526
- parentEntityId: parentSpan?.entityId,
3527
- parentEntityName: parentSpan?.entityName,
3528
- parentEntityVersionId: getSpanMetadataString(parentSpan, "entityVersionId"),
3529
- rootEntityType: rootSpan.entityType,
3530
- rootEntityId: rootSpan.entityId,
3531
- rootEntityName: rootSpan.entityName,
3532
- rootEntityVersionId: getSpanMetadataString(rootSpan, "entityVersionId"),
3608
+ ...parentLineage,
3609
+ ...rootLineage,
3533
3610
  userId: getMetadataString("userId"),
3534
3611
  organizationId: getMetadataString("organizationId"),
3535
3612
  resourceId: getMetadataString("resourceId"),
@@ -3550,6 +3627,7 @@ var BaseSpan = class BaseSpan {
3550
3627
  const hideOutput = this.traceState?.hideOutput ?? false;
3551
3628
  const nestedUnderParent = this.traceState?.nestedUnderParent ?? false;
3552
3629
  const links = validLinks(this.links);
3630
+ const correlation = this.getCorrelationContext();
3553
3631
  return {
3554
3632
  id: this.id,
3555
3633
  traceId: this.traceId,
@@ -3569,6 +3647,7 @@ var BaseSpan = class BaseSpan {
3569
3647
  isEvent: this.isEvent,
3570
3648
  isRootSpan: this.isRootSpan,
3571
3649
  ...this.isInternal ? { isInternal: true } : {},
3650
+ ...definedLineage(correlation),
3572
3651
  parentSpanId: this.getParentSpanId(includeInternalSpans),
3573
3652
  externalParentSpanId: this.getExportedExternalParentSpanId(includeInternalSpans),
3574
3653
  ...nestedUnderParent ? { nestedUnderParent: true } : {},
@@ -3580,6 +3659,7 @@ var BaseSpan = class BaseSpan {
3580
3659
  snapshot() {
3581
3660
  return {
3582
3661
  ...this.exportSpan(),
3662
+ ownEntityVersionId: this.ownEntityVersionId ?? null,
3583
3663
  ...this.traceState ? { traceState: this.traceState } : {}
3584
3664
  };
3585
3665
  }
@@ -5211,6 +5291,7 @@ var BaseObservabilityInstance = class extends _mastra_core_base.MastraBase {
5211
5291
  tracingPolicy: cached.isInternal ? { internal: _mastra_core_observability.InternalSpans.ALL } : void 0,
5212
5292
  traceState: this.rebuildTraceState(cached)
5213
5293
  });
5294
+ if (span instanceof BaseSpan) span.restoreEntityLineage(cached);
5214
5295
  this.wireSpanLifecycle(span);
5215
5296
  return span;
5216
5297
  }