@mastra/observability 1.15.0 → 1.15.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
@@ -2917,6 +2917,12 @@ var BaseObservabilityInstance = class extends MastraBase {
2917
2917
  * a span's `metadata.environment` isn't set.
2918
2918
  */
2919
2919
  #mastraEnvironment;
2920
+ /**
2921
+ * For excluded MODEL_GENERATION spans whose constructor clears `attributes`,
2922
+ * we stash the lightweight provider/model from creation options so
2923
+ * `captureExcludedModelUsage` can still build cost context.
2924
+ */
2925
+ #excludedModelMeta = /* @__PURE__ */ new WeakMap();
2920
2926
  constructor(config) {
2921
2927
  super({ component: RegisteredLogger.OBSERVABILITY, name: config.serviceName });
2922
2928
  this.config = {
@@ -3022,6 +3028,13 @@ var BaseObservabilityInstance = class extends MastraBase {
3022
3028
  tags,
3023
3029
  requestContext
3024
3030
  });
3031
+ if (rest.type === SpanType.MODEL_GENERATION && this.config.excludeSpanTypes?.includes(SpanType.MODEL_GENERATION)) {
3032
+ const attrs = rest.attributes;
3033
+ const model = attrs?.responseModel ?? attrs?.model;
3034
+ if (attrs?.provider || model) {
3035
+ this.#excludedModelMeta.set(span, { provider: attrs?.provider, model });
3036
+ }
3037
+ }
3025
3038
  if (span.isEvent) {
3026
3039
  this.emitSpanEnded(span);
3027
3040
  } else {
@@ -3218,11 +3231,12 @@ var BaseObservabilityInstance = class extends MastraBase {
3218
3231
  return;
3219
3232
  }
3220
3233
  const rollupTarget = this.captureModelUsageRollup(span, options);
3234
+ const excludedModelUsage = this.captureExcludedModelUsage(span, options);
3221
3235
  originalEnd(options);
3222
3236
  if (rollupTarget) {
3223
3237
  this.applyUsageRollup(rollupTarget);
3224
3238
  }
3225
- this.emitSpanEnded(span);
3239
+ this.emitSpanEnded(span, excludedModelUsage);
3226
3240
  };
3227
3241
  span.update = (options) => {
3228
3242
  if (span.isEvent) {
@@ -3356,6 +3370,22 @@ var BaseObservabilityInstance = class extends MastraBase {
3356
3370
  }
3357
3371
  return exportedSpan;
3358
3372
  }
3373
+ /** Export an already-processed span, returning undefined if filtered out. */
3374
+ getProcessedSpanForExport(span) {
3375
+ if (!span.isValid) return void 0;
3376
+ if (span.isInternal && !this.config.includeInternalSpans) return void 0;
3377
+ if (this.config.excludeSpanTypes?.includes(span.type)) return void 0;
3378
+ const exportedSpan = span.exportSpan(this.config.includeInternalSpans);
3379
+ if (!exportedSpan) return void 0;
3380
+ if (this.config.spanFilter) {
3381
+ try {
3382
+ if (!this.config.spanFilter(exportedSpan)) return void 0;
3383
+ } catch (error) {
3384
+ this.logger.error(`[Observability] spanFilter error`, error);
3385
+ }
3386
+ }
3387
+ return exportedSpan;
3388
+ }
3359
3389
  /**
3360
3390
  * Emit a span started event.
3361
3391
  * Routes through the ObservabilityBus so exporters receive it via onTracingEvent.
@@ -3372,14 +3402,31 @@ var BaseObservabilityInstance = class extends MastraBase {
3372
3402
  * Emits any auto-extracted metrics while the live span tree is still available,
3373
3403
  * then routes the exported tracing event through the ObservabilityBus.
3374
3404
  */
3375
- emitSpanEnded(span) {
3376
- const exportedSpan = this.getSpanForExport(span);
3377
- if (exportedSpan) {
3405
+ emitSpanEnded(span, excludedModelUsage) {
3406
+ let processedSpan;
3407
+ let spanWasProcessed = false;
3408
+ if (span.isValid && !(span.isInternal && !this.config.includeInternalSpans)) {
3409
+ processedSpan = this.processSpan(span);
3410
+ spanWasProcessed = true;
3378
3411
  try {
3379
- emitAutoExtractedMetrics(span, this.getMetricsContext(span));
3412
+ if (processedSpan) {
3413
+ emitAutoExtractedMetrics(processedSpan, this.getMetricsContext(processedSpan));
3414
+ const processedAttrs = processedSpan.attributes;
3415
+ if (excludedModelUsage && !processedAttrs?.usage) {
3416
+ emitTokenMetricsForUsage(
3417
+ excludedModelUsage.usage,
3418
+ excludedModelUsage.provider,
3419
+ excludedModelUsage.model,
3420
+ this.getMetricsContext(processedSpan)
3421
+ );
3422
+ }
3423
+ }
3380
3424
  } catch (err) {
3381
3425
  this.logger.error("[Observability] Auto-extraction error:", err);
3382
3426
  }
3427
+ }
3428
+ const exportedSpan = spanWasProcessed ? processedSpan ? this.getProcessedSpanForExport(processedSpan) : void 0 : this.getSpanForExport(span);
3429
+ if (exportedSpan) {
3383
3430
  const event = { type: TracingEventType.SPAN_ENDED, exportedSpan };
3384
3431
  this.emitTracingEvent(event);
3385
3432
  }
@@ -3415,6 +3462,26 @@ var BaseObservabilityInstance = class extends MastraBase {
3415
3462
  const model = endAttrs?.responseModel ?? endAttrs?.model ?? liveAttrs?.responseModel ?? liveAttrs?.model;
3416
3463
  return { ancestor, usage, provider, model };
3417
3464
  }
3465
+ /**
3466
+ * When a non-internal MODEL_GENERATION span is excluded by `excludeSpanTypes`,
3467
+ * the BaseSpan constructor clears start-time attributes and DefaultSpan.end()
3468
+ * drops end-time attributes before auto-extraction can read them. Capture
3469
+ * usage from end options and provider/model from the creation-time stash so
3470
+ * token and cost metrics still emit even though the trace span is filtered out.
3471
+ */
3472
+ captureExcludedModelUsage(span, endOptions) {
3473
+ if (span.type !== SpanType.MODEL_GENERATION) return void 0;
3474
+ if (span.isInternal) return void 0;
3475
+ if (!this.config.excludeSpanTypes?.includes(SpanType.MODEL_GENERATION)) return void 0;
3476
+ const endAttrs = endOptions?.attributes ?? void 0;
3477
+ const liveAttrs = span.attributes;
3478
+ const usage = endAttrs?.usage ?? liveAttrs?.usage;
3479
+ if (!usage) return void 0;
3480
+ const stashed = this.#excludedModelMeta.get(span);
3481
+ const provider = endAttrs?.provider ?? liveAttrs?.provider ?? stashed?.provider;
3482
+ const model = endAttrs?.responseModel ?? endAttrs?.model ?? liveAttrs?.responseModel ?? liveAttrs?.model ?? stashed?.model;
3483
+ return { usage, provider, model };
3484
+ }
3418
3485
  /**
3419
3486
  * Accumulate usage onto the ancestor's `internalUsage` attribute (for trace
3420
3487
  * UI visibility) and emit auto-extracted token metrics now, using the