@mastra/observability 1.17.2-alpha.1 → 1.17.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # @mastra/observability
2
2
 
3
+ ## 1.17.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix PostgreSQL observability writes failing on NUL characters and unpaired Unicode surrogates ([#21728](https://github.com/mastra-ai/mastra/pull/21728))
8
+
9
+ Span serialization truncated strings by UTF-16 code unit, so a cut inside an emoji left a lone surrogate that PostgreSQL rejected on the jsonb cast (`22P02`). NUL characters were rejected as well (`22P05`). Because observability events are inserted as a single multi-row statement, one malformed field discarded the entire batch.
10
+
11
+ Truncation now preserves complete surrogate pairs, and the v-next PostgreSQL observability encoder sanitizes NUL and unpaired surrogates before the jsonb cast, using the same sanitizer that workflow snapshots already rely on. Valid Unicode, including complete emoji, is preserved.
12
+
13
+ - Fixed `MastraStorageExporter` staying disabled when a configured observability store is temporarily unavailable during startup. The exporter now recovers on a later event, so traces resume without restarting the process. (#21943) ([#21957](https://github.com/mastra-ai/mastra/pull/21957))
14
+
15
+ - Added `span.endTree()` for closing a span together with every descendant span that is still open, so an operation that is abandoned rather than completed can still emit a full trace. The options you pass are applied to every span it closes, so a force-closed child is distinguishable from one that finished on its own. ([#22278](https://github.com/mastra-ai/mastra/pull/22278))
16
+
17
+ ```ts
18
+ // Ends the span and any child spans still open beneath it, marking each canceled
19
+ workflowSpan.endTree({ attributes: { status: 'canceled' } });
20
+ ```
21
+
22
+ Repeat calls to `span.end()` are now ignored. A span that was force-closed this way keeps the state it was closed with and reports its end exactly once, even if the work it covered finishes later and ends the span again.
23
+
24
+ - Updated dependencies [[`79f04a7`](https://github.com/mastra-ai/mastra/commit/79f04a7f6c6829da541139f638f2f1d267916e08), [`65edab1`](https://github.com/mastra-ai/mastra/commit/65edab1c233d17b8f163bad12fca410d0e6f16b1), [`1e47b75`](https://github.com/mastra-ai/mastra/commit/1e47b7520cab4cfaa8daed52f17e2e6d14ff7539), [`ab20a38`](https://github.com/mastra-ai/mastra/commit/ab20a38d0275f8d85e0f3833bd87ef487bcc609f), [`fd4d5fe`](https://github.com/mastra-ai/mastra/commit/fd4d5fe4f943699b85db5e74404f190d5a6b8c2a), [`ae8790c`](https://github.com/mastra-ai/mastra/commit/ae8790c4bfaa088d2ab279d1dcc06f326b9fd109), [`2c85f42`](https://github.com/mastra-ai/mastra/commit/2c85f428e04ccd63ea31a7ec80b5b327afdad555), [`11bbeb9`](https://github.com/mastra-ai/mastra/commit/11bbeb9b108ef2264e05acefc6dafb9cbb342921), [`48ef1f1`](https://github.com/mastra-ai/mastra/commit/48ef1f1d24eedafbb07f64e659a81b52b67b8bf6), [`aa3a85d`](https://github.com/mastra-ai/mastra/commit/aa3a85daf094c683bb97efdf4b6a696d2e474af5), [`d29d06f`](https://github.com/mastra-ai/mastra/commit/d29d06fe00bbd35b4571150ea04c59d2ed783c71), [`e6516df`](https://github.com/mastra-ai/mastra/commit/e6516dfcdae4f4ac0e7971d84359a81385ee602f), [`1a485f3`](https://github.com/mastra-ai/mastra/commit/1a485f3538f5ec64d58bd8b5e1e99de0c695c87b), [`0d37487`](https://github.com/mastra-ai/mastra/commit/0d37487d9f349388a3f1cef6a536cf9dcc4b6273), [`8661d7d`](https://github.com/mastra-ai/mastra/commit/8661d7d7179f0a024456aabdd8679bcecd09ac28), [`dbbfeb8`](https://github.com/mastra-ai/mastra/commit/dbbfeb85ec949dc9ebc0755e1ad262e4f5eba8db), [`575e343`](https://github.com/mastra-ai/mastra/commit/575e343900451021d96110916497d334af7bc252), [`0b2a3d1`](https://github.com/mastra-ai/mastra/commit/0b2a3d1783875c5b97b7b36ab3d03d7360e0dde7), [`6bb5d71`](https://github.com/mastra-ai/mastra/commit/6bb5d7193fe9166b219f0fccae17db7a5ae86e65), [`3cc9d00`](https://github.com/mastra-ai/mastra/commit/3cc9d00b2b4333e0377a5e9df5eff92c17ce7630), [`cacb839`](https://github.com/mastra-ai/mastra/commit/cacb8392d9e74189b56d857290b0615f98a2683d), [`57de7d6`](https://github.com/mastra-ai/mastra/commit/57de7d644ba7146edb4e9e6111ec4fa98c3a59e9), [`c8e4cea`](https://github.com/mastra-ai/mastra/commit/c8e4ceac9a390d78c8327dff3cdb2861dd71957f), [`ed01e9a`](https://github.com/mastra-ai/mastra/commit/ed01e9a807514a904374bf687a7b8f18750f6f78), [`b47b26e`](https://github.com/mastra-ai/mastra/commit/b47b26e6fe95cb8a3482be2c5e52de157fe59d0b), [`0d37487`](https://github.com/mastra-ai/mastra/commit/0d37487d9f349388a3f1cef6a536cf9dcc4b6273), [`733a537`](https://github.com/mastra-ai/mastra/commit/733a537489a858b5880b2e98809334fba895a221), [`e8e299c`](https://github.com/mastra-ai/mastra/commit/e8e299cc6abdfc39947e2fec25803493015d3882), [`edfc548`](https://github.com/mastra-ai/mastra/commit/edfc548886bc7bae17b681f8b6b41a47eb32bcd2), [`b05f486`](https://github.com/mastra-ai/mastra/commit/b05f48612984d5fe2447ea2d6cdd5c604d285b97), [`a8a4871`](https://github.com/mastra-ai/mastra/commit/a8a4871215f51da95c47129602157ce5372f634a), [`eb9ecaa`](https://github.com/mastra-ai/mastra/commit/eb9ecaa89c36e889749e3b825cfc507ce7f7980b), [`4ff3ee2`](https://github.com/mastra-ai/mastra/commit/4ff3ee2bff7ed07528b4817f8f49639031c72a4d), [`9207dfa`](https://github.com/mastra-ai/mastra/commit/9207dfab8062e5fc68b751684797ff86fe0b4e70), [`5165cdc`](https://github.com/mastra-ai/mastra/commit/5165cdcdcf50e144bb8113278535196cc9b07065), [`e737014`](https://github.com/mastra-ai/mastra/commit/e737014e0fc7035759762bb5b48baef1d6c0f6a7), [`6bb5d71`](https://github.com/mastra-ai/mastra/commit/6bb5d7193fe9166b219f0fccae17db7a5ae86e65), [`f591643`](https://github.com/mastra-ai/mastra/commit/f591643becdf0be9bddce6ba1748e64bc30d77f1), [`63796ba`](https://github.com/mastra-ai/mastra/commit/63796ba0fda60253be17535e68f6bbbf1e6ffa09), [`b1ad324`](https://github.com/mastra-ai/mastra/commit/b1ad324d657f3544b0701332aef7eb10e9a36258), [`61c566d`](https://github.com/mastra-ai/mastra/commit/61c566dd2f2cde2b23ed8f139924e530d4202214), [`c24754c`](https://github.com/mastra-ai/mastra/commit/c24754c1fb6fe144e5051e536e98c8a18b0214ac), [`12c61d2`](https://github.com/mastra-ai/mastra/commit/12c61d280c8cb208bc3c8dbcbe5dcc60cf9d1cd0), [`c46eb09`](https://github.com/mastra-ai/mastra/commit/c46eb09ce4987509af57a0ac582c61241a6dd2f1), [`9ee8120`](https://github.com/mastra-ai/mastra/commit/9ee8120ce17f76b9f617489e05a283353742690a), [`d975e92`](https://github.com/mastra-ai/mastra/commit/d975e924d4936f46c386bd3dee39c671720289f6), [`45dd6ee`](https://github.com/mastra-ai/mastra/commit/45dd6ee089bd7df0d0c98a10098e483fd388e04a), [`4e9a228`](https://github.com/mastra-ai/mastra/commit/4e9a2283d5fd6ed1b70a2751eb3dc2cbf82ada20), [`d6ce34a`](https://github.com/mastra-ai/mastra/commit/d6ce34aeceb06ddf3d595a1eed5cc74f481a46a1), [`f95f468`](https://github.com/mastra-ai/mastra/commit/f95f468cf1e7c2b924a13826494f98b8f2ccd581), [`30ed33e`](https://github.com/mastra-ai/mastra/commit/30ed33ee14084a26019aba15fceadda6d6ddefaf), [`04a815f`](https://github.com/mastra-ai/mastra/commit/04a815fc8971d29e97fcdcc5008a1eb472fc00ff), [`1cfa878`](https://github.com/mastra-ai/mastra/commit/1cfa8784d8da0dfaa0317e5048bc48b6084a5ea5), [`9a12ef3`](https://github.com/mastra-ai/mastra/commit/9a12ef3fccf3f4186db0f294f4ee1f02cf4d8db2), [`32d3583`](https://github.com/mastra-ai/mastra/commit/32d358332cb8ac2306b83b73cf3536e74dbd435e), [`7960688`](https://github.com/mastra-ai/mastra/commit/7960688828e04eaf3106e34f7758fa580257eef6), [`91ad69d`](https://github.com/mastra-ai/mastra/commit/91ad69d64994c89199b0c55399e64ed91c61df2f), [`8dc408d`](https://github.com/mastra-ai/mastra/commit/8dc408d34438f9e13297f792c11a5cfd6cf952e1), [`c92def1`](https://github.com/mastra-ai/mastra/commit/c92def10a13c822972c96f0a4ca6ffc1f4258aed), [`63041eb`](https://github.com/mastra-ai/mastra/commit/63041eb4c50b520a0a80e03d4cd6ea99f67715a0), [`c118318`](https://github.com/mastra-ai/mastra/commit/c1183181c9804303db4b511c2e2648f8b714712b), [`c5eaec5`](https://github.com/mastra-ai/mastra/commit/c5eaec5a860d80d0e3805e67db0414b87ac8cbed), [`fc07c64`](https://github.com/mastra-ai/mastra/commit/fc07c6465043e08e99193a6751a01c56ffc2e7a1), [`cced745`](https://github.com/mastra-ai/mastra/commit/cced745a056ec2225c5bc702e32d848847aa8b65), [`542dee2`](https://github.com/mastra-ai/mastra/commit/542dee254167f974ff8cbbbfc0ce10f9a2616a7b), [`3c19dce`](https://github.com/mastra-ai/mastra/commit/3c19dcef8e73062a80627a4927eae3ec11145afd), [`aca2869`](https://github.com/mastra-ai/mastra/commit/aca2869b2031982f3c4a2f52525c9be7cf123ef8), [`a58483c`](https://github.com/mastra-ai/mastra/commit/a58483cff1a9d41fce7c931843f48cb0ac450f64), [`a58483c`](https://github.com/mastra-ai/mastra/commit/a58483cff1a9d41fce7c931843f48cb0ac450f64), [`e6f8450`](https://github.com/mastra-ai/mastra/commit/e6f845074d478527026b18d85031b23353e1d0a4), [`895e9df`](https://github.com/mastra-ai/mastra/commit/895e9dfc17d6f34299eca64e317ded9e5f5e5ef8), [`e66b2ba`](https://github.com/mastra-ai/mastra/commit/e66b2ba100db63eaeab6e21e1ea34b113f2ec781), [`3e8727e`](https://github.com/mastra-ai/mastra/commit/3e8727e11ec1a5d733acedb5c872896394be18c1)]:
25
+ - @mastra/core@1.62.0
26
+
27
+ ## 1.17.2-alpha.2
28
+
29
+ ### Patch Changes
30
+
31
+ - Added `span.endTree()` for closing a span together with every descendant span that is still open, so an operation that is abandoned rather than completed can still emit a full trace. The options you pass are applied to every span it closes, so a force-closed child is distinguishable from one that finished on its own. ([#22278](https://github.com/mastra-ai/mastra/pull/22278))
32
+
33
+ ```ts
34
+ // Ends the span and any child spans still open beneath it, marking each canceled
35
+ workflowSpan.endTree({ attributes: { status: 'canceled' } });
36
+ ```
37
+
38
+ Repeat calls to `span.end()` are now ignored. A span that was force-closed this way keeps the state it was closed with and reports its end exactly once, even if the work it covered finishes later and ends the span again.
39
+
40
+ - Updated dependencies [[`b05f486`](https://github.com/mastra-ai/mastra/commit/b05f48612984d5fe2447ea2d6cdd5c604d285b97), [`7960688`](https://github.com/mastra-ai/mastra/commit/7960688828e04eaf3106e34f7758fa580257eef6)]:
41
+ - @mastra/core@1.62.0-alpha.10
42
+
3
43
  ## 1.17.2-alpha.1
4
44
 
5
45
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -2718,7 +2718,7 @@ function getExternalParentId(options) {
2718
2718
  if (parent.isInternal || parent.isExcluded) return parent.getParentSpanId(false);
2719
2719
  return parent.id;
2720
2720
  }
2721
- var BaseSpan = class {
2721
+ var BaseSpan = class BaseSpan {
2722
2722
  name;
2723
2723
  type;
2724
2724
  attributes;
@@ -2768,6 +2768,8 @@ var BaseSpan = class {
2768
2768
  isExcluded;
2769
2769
  /** Cached canonical correlation context for this live span */
2770
2770
  correlationContext;
2771
+ /** Child spans that have started but not yet ended */
2772
+ #openChildren;
2771
2773
  /**
2772
2774
  * Subclasses can override to unconditionally mark the span as excluded.
2773
2775
  * NoOpSpan uses this because it is never exported regardless of config.
@@ -2789,6 +2791,8 @@ var BaseSpan = class {
2789
2791
  this.isEvent = options.isEvent ?? false;
2790
2792
  this.tracingPolicy = options.tracingPolicy;
2791
2793
  this.traceState = options.traceState;
2794
+ const parent = options.parent;
2795
+ if (!this.isEvent && parent instanceof BaseSpan && parent.isValid) (parent.#openChildren ??= /* @__PURE__ */ new Set()).add(this);
2792
2796
  this.tags = !options.parent && options.tags?.length ? options.tags : void 0;
2793
2797
  const entityParent = this.getParentSpan(false);
2794
2798
  this.entityType = options.entityType ?? entityParent?.entityType;
@@ -2826,6 +2830,16 @@ var BaseSpan = class {
2826
2830
  return value;
2827
2831
  }
2828
2832
  }
2833
+ /** End the span and any descendant spans that are still open, applying `options` to each */
2834
+ endTree(options) {
2835
+ if (this.#openChildren) for (const child of [...this.#openChildren]) child.endTree(options);
2836
+ this.end(options);
2837
+ }
2838
+ /** Release this span from its parent's open-child set once it has ended */
2839
+ detachFromParent() {
2840
+ const parent = this.parent;
2841
+ if (parent instanceof BaseSpan) parent.#openChildren?.delete(this);
2842
+ }
2829
2843
  createChildSpan(options) {
2830
2844
  return this.observabilityInstance.startSpan({
2831
2845
  ...options,
@@ -3029,7 +3043,9 @@ var DefaultSpan = class extends BaseSpan {
3029
3043
  }
3030
3044
  end(options) {
3031
3045
  if (this.isEvent) return;
3046
+ if (this.endTime) return;
3032
3047
  this.endTime = /* @__PURE__ */ new Date();
3048
+ this.detachFromParent();
3033
3049
  if (options?.metadata) this.metadata = {
3034
3050
  ...this.metadata,
3035
3051
  ...deepClean(this.prepareSpanMetadata(options.metadata), this.deepCleanOptions)
@@ -3485,6 +3501,7 @@ var BaseObservabilityInstance = class extends _mastra_core_base.MastraBase {
3485
3501
  this.logger.warn(`End event is not available on event spans`);
3486
3502
  return;
3487
3503
  }
3504
+ if (span.endTime) return;
3488
3505
  const rollupTarget = this.captureModelUsageRollup(span, options);
3489
3506
  const excludedModelUsage = this.captureExcludedModelUsage(span, options);
3490
3507
  originalEnd(options);