@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.js CHANGED
@@ -2193,6 +2193,9 @@ function isDefined(value) {
2193
2193
  * - Google/Gemini: cachedContentTokenCount, thoughtsTokenCount in providerMetadata.google.usageMetadata
2194
2194
  * - OpenRouter: Uses OpenAI-compatible structure (cache tokens in usage)
2195
2195
  *
2196
+ * Kept in sync with `packages/core/src/observability/usage.ts` (duplicated so exporters do not need a newer core).
2197
+ * Change both copies together; `usage.parity.test.ts` fails if they drift.
2198
+ *
2196
2199
  * @param usage - The LanguageModelV2Usage from AI SDK response
2197
2200
  * @param providerMetadata - Optional provider-specific metadata
2198
2201
  * @returns UsageStats with inputDetails and outputDetails
@@ -3169,6 +3172,28 @@ function mergeMetadata$1(parentMetadata, metadata) {
3169
3172
  }
3170
3173
  //#endregion
3171
3174
  //#region src/spans/base.ts
3175
+ const LINEAGE_KEYS = [
3176
+ "parentEntityType",
3177
+ "parentEntityId",
3178
+ "parentEntityName",
3179
+ "parentEntityVersionId",
3180
+ "rootEntityType",
3181
+ "rootEntityId",
3182
+ "rootEntityName",
3183
+ "rootEntityVersionId"
3184
+ ];
3185
+ /** Copy only the lineage fields that have values, so spans don't carry undefined keys */
3186
+ function ownEntityVersionId(span) {
3187
+ return span instanceof BaseSpan ? span.ownEntityVersionId : void 0;
3188
+ }
3189
+ function definedLineage(source) {
3190
+ const lineage = {};
3191
+ for (const key of LINEAGE_KEYS) {
3192
+ const value = source[key];
3193
+ if (value !== void 0 && value !== null) lineage[key] = value;
3194
+ }
3195
+ return lineage;
3196
+ }
3172
3197
  /**
3173
3198
  * Determines if a span type should be considered internal based on flags.
3174
3199
  * Returns false if flags are undefined.
@@ -3290,6 +3315,17 @@ var BaseSpan = class BaseSpan {
3290
3315
  isExcluded;
3291
3316
  /** Cached canonical correlation context for this live span */
3292
3317
  correlationContext;
3318
+ /**
3319
+ * Parent and root entity restored by `rebuildSpan()`. A rebuilt span has no
3320
+ * live `parent`, so its original ancestors are only known from the cached export.
3321
+ */
3322
+ restoredLineage;
3323
+ /**
3324
+ * Version declared for this span's own entity, or inherited from a parent span
3325
+ * of the same entity. Unlike `metadata.entityVersionId`, never an ancestor's
3326
+ * version for a different entity.
3327
+ */
3328
+ ownEntityVersionId;
3293
3329
  /** Child spans that have started but not yet ended */
3294
3330
  #openChildren;
3295
3331
  /** The span whose open-child set currently tracks this span: the parent, or a live ancestor after promotion */
@@ -3327,6 +3363,9 @@ var BaseSpan = class BaseSpan {
3327
3363
  this.entityType = options.entityType ?? entityParent?.entityType;
3328
3364
  this.entityId = options.entityId ?? entityParent?.entityId;
3329
3365
  this.entityName = options.entityName ?? entityParent?.entityName;
3366
+ const declaredVersion = options.metadata?.entityVersionId;
3367
+ const sameEntityParent = entityParent instanceof BaseSpan && entityParent.entityType === this.entityType && entityParent.entityId === this.entityId;
3368
+ this.ownEntityVersionId = typeof declaredVersion === "string" ? declaredVersion : sameEntityParent ? entityParent.ownEntityVersionId : void 0;
3330
3369
  if (this.isExcluded) {
3331
3370
  this.attributes = {};
3332
3371
  return;
@@ -3475,18 +3514,62 @@ var BaseSpan = class BaseSpan {
3475
3514
  current = current.parent;
3476
3515
  }
3477
3516
  }
3478
- /** Build and cache the canonical correlation context for this live span. */
3517
+ /**
3518
+ * Restore the parent and root entity a span had before it was exported and
3519
+ * rebuilt (durable execution), so it and its new children keep their lineage.
3520
+ */
3521
+ restoreEntityLineage(cached) {
3522
+ this.ownEntityVersionId = cached.ownEntityVersionId ?? void 0;
3523
+ const lineage = definedLineage(cached);
3524
+ if (Object.keys(lineage).length > 0) {
3525
+ this.restoredLineage = lineage;
3526
+ this.correlationContext = void 0;
3527
+ }
3528
+ }
3529
+ /**
3530
+ * Build and cache the canonical correlation context for this live span.
3531
+ *
3532
+ * Parent entity: the nearest ancestor that is not internal or excluded, the
3533
+ * same rule used for entity inheritance. Root entity: the top of the
3534
+ * in-process parent chain, which is not necessarily the distributed trace's
3535
+ * root when the trace continues from another service. The root walk does not
3536
+ * skip internal spans, so the root can name an entity whose span is not
3537
+ * exported. Logs, metrics, scores and feedback share these values.
3538
+ *
3539
+ * When the top of the live chain was rebuilt, its original ancestors only
3540
+ * survive in the restored lineage, so it supplies the root and, when no live
3541
+ * ancestor qualifies, the parent.
3542
+ */
3479
3543
  getCorrelationContext() {
3480
3544
  if (this.correlationContext) return this.correlationContext;
3481
3545
  const metadata = this.metadata ?? {};
3482
3546
  const getMetadataString = (key) => typeof metadata[key] === "string" ? metadata[key] : void 0;
3483
- const getSpanMetadataString = (span, key) => {
3484
- const m = span?.metadata;
3485
- return m && typeof m[key] === "string" ? m[key] : void 0;
3486
- };
3487
3547
  const parentSpan = this.getParentSpan(false);
3488
3548
  let rootSpan = this;
3489
3549
  while (rootSpan.parent) rootSpan = rootSpan.parent;
3550
+ const restored = rootSpan instanceof BaseSpan ? rootSpan.restoredLineage : void 0;
3551
+ const parentLineage = parentSpan ? {
3552
+ parentEntityType: parentSpan.entityType,
3553
+ parentEntityId: parentSpan.entityId,
3554
+ parentEntityName: parentSpan.entityName,
3555
+ parentEntityVersionId: ownEntityVersionId(parentSpan)
3556
+ } : {
3557
+ parentEntityType: restored?.parentEntityType,
3558
+ parentEntityId: restored?.parentEntityId,
3559
+ parentEntityName: restored?.parentEntityName,
3560
+ parentEntityVersionId: restored?.parentEntityVersionId
3561
+ };
3562
+ const rootLineage = restored ? {
3563
+ rootEntityType: restored.rootEntityType,
3564
+ rootEntityId: restored.rootEntityId,
3565
+ rootEntityName: restored.rootEntityName,
3566
+ rootEntityVersionId: restored.rootEntityVersionId
3567
+ } : {
3568
+ rootEntityType: rootSpan.entityType,
3569
+ rootEntityId: rootSpan.entityId,
3570
+ rootEntityName: rootSpan.entityName,
3571
+ rootEntityVersionId: ownEntityVersionId(rootSpan)
3572
+ };
3490
3573
  const rootTags = rootSpan.tags?.length ? [...rootSpan.tags] : void 0;
3491
3574
  this.correlationContext = {
3492
3575
  traceId: this.traceId,
@@ -3496,14 +3579,8 @@ var BaseSpan = class BaseSpan {
3496
3579
  entityId: this.entityId,
3497
3580
  entityName: this.entityName,
3498
3581
  entityVersionId: getMetadataString("entityVersionId"),
3499
- parentEntityType: parentSpan?.entityType,
3500
- parentEntityId: parentSpan?.entityId,
3501
- parentEntityName: parentSpan?.entityName,
3502
- parentEntityVersionId: getSpanMetadataString(parentSpan, "entityVersionId"),
3503
- rootEntityType: rootSpan.entityType,
3504
- rootEntityId: rootSpan.entityId,
3505
- rootEntityName: rootSpan.entityName,
3506
- rootEntityVersionId: getSpanMetadataString(rootSpan, "entityVersionId"),
3582
+ ...parentLineage,
3583
+ ...rootLineage,
3507
3584
  userId: getMetadataString("userId"),
3508
3585
  organizationId: getMetadataString("organizationId"),
3509
3586
  resourceId: getMetadataString("resourceId"),
@@ -3524,6 +3601,7 @@ var BaseSpan = class BaseSpan {
3524
3601
  const hideOutput = this.traceState?.hideOutput ?? false;
3525
3602
  const nestedUnderParent = this.traceState?.nestedUnderParent ?? false;
3526
3603
  const links = validLinks(this.links);
3604
+ const correlation = this.getCorrelationContext();
3527
3605
  return {
3528
3606
  id: this.id,
3529
3607
  traceId: this.traceId,
@@ -3543,6 +3621,7 @@ var BaseSpan = class BaseSpan {
3543
3621
  isEvent: this.isEvent,
3544
3622
  isRootSpan: this.isRootSpan,
3545
3623
  ...this.isInternal ? { isInternal: true } : {},
3624
+ ...definedLineage(correlation),
3546
3625
  parentSpanId: this.getParentSpanId(includeInternalSpans),
3547
3626
  externalParentSpanId: this.getExportedExternalParentSpanId(includeInternalSpans),
3548
3627
  ...nestedUnderParent ? { nestedUnderParent: true } : {},
@@ -3554,6 +3633,7 @@ var BaseSpan = class BaseSpan {
3554
3633
  snapshot() {
3555
3634
  return {
3556
3635
  ...this.exportSpan(),
3636
+ ownEntityVersionId: this.ownEntityVersionId ?? null,
3557
3637
  ...this.traceState ? { traceState: this.traceState } : {}
3558
3638
  };
3559
3639
  }
@@ -5185,6 +5265,7 @@ var BaseObservabilityInstance = class extends MastraBase {
5185
5265
  tracingPolicy: cached.isInternal ? { internal: InternalSpans.ALL } : void 0,
5186
5266
  traceState: this.rebuildTraceState(cached)
5187
5267
  });
5268
+ if (span instanceof BaseSpan) span.restoreEntityLineage(cached);
5188
5269
  this.wireSpanLifecycle(span);
5189
5270
  return span;
5190
5271
  }