@mastra/observability 1.17.5-alpha.0 → 1.17.5-alpha.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/README.md +14 -85
- package/dist/context/logger.d.ts.map +1 -1
- package/dist/context/metrics.d.ts.map +1 -1
- package/dist/ids.d.ts +66 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/index.cjs +75 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +68 -12
- package/dist/index.js.map +1 -1
- package/dist/instances/base.d.ts.map +1 -1
- package/dist/recorded.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @mastra/observability
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Monitor Mastra agents, workflows, tools, and model calls with hierarchical traces, automatically extracted metrics, and structured logs correlated to the active trace.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ Tracing, metrics, and structured logging for AI operations in Mastra.
|
|
|
8
8
|
npm install @mastra/observability
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Usage
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
import { Mastra } from '@mastra/core';
|
|
@@ -19,100 +19,29 @@ export const mastra = new Mastra({
|
|
|
19
19
|
configs: {
|
|
20
20
|
default: {
|
|
21
21
|
serviceName: 'my-app',
|
|
22
|
-
exporters: [
|
|
23
|
-
new MastraStorageExporter(), // Persists observability events to Mastra Storage
|
|
24
|
-
new MastraPlatformExporter(), // Sends observability events to Mastra Platform
|
|
25
|
-
],
|
|
22
|
+
exporters: [new MastraStorageExporter(), new MastraPlatformExporter()],
|
|
26
23
|
},
|
|
27
24
|
},
|
|
28
25
|
}),
|
|
29
26
|
});
|
|
30
27
|
```
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
## Features
|
|
35
|
-
|
|
36
|
-
- **Auto-instrumentation** - Traces agent runs, LLM calls, tool executions, and workflows
|
|
37
|
-
- **Pluggable Exporters** - Exporters for Studio, plus integrations for Arize, Braintrust, Langfuse, LangSmith, and OpenTelemetry
|
|
38
|
-
- **Sampling Strategies** - Always, ratio-based, or custom sampling
|
|
39
|
-
- **Span Processors** - Transform or filter span data before export
|
|
40
|
-
- **OpenTelemetry Compatible** - Standard trace/span ID formats for integration
|
|
41
|
-
|
|
42
|
-
## Architecture
|
|
43
|
-
|
|
44
|
-
### ObservabilityBus
|
|
45
|
-
|
|
46
|
-
Central event router that dispatches tracing, metric, and log events to registered exporters. All handler promises are tracked for reliable flush and shutdown — no events are silently dropped.
|
|
47
|
-
|
|
48
|
-
Exporters register via `registerExporter()` and can optionally implement `onLogEvent` and `onMetricEvent` handlers alongside the existing `exportTracingEvent`.
|
|
49
|
-
|
|
50
|
-
### Auto-extracted metrics
|
|
51
|
-
|
|
52
|
-
Metrics are automatically extracted from span lifecycle events by `AutoExtractedMetrics`:
|
|
53
|
-
|
|
54
|
-
- `mastra_agent_duration_ms`
|
|
55
|
-
- `mastra_tool_duration_ms`
|
|
56
|
-
- `mastra_workflow_duration_ms`
|
|
57
|
-
- `mastra_model_duration_ms`
|
|
58
|
-
- `mastra_model_total_input_tokens` / `mastra_model_total_output_tokens`
|
|
59
|
-
- `mastra_model_input_text_tokens` / `mastra_model_input_cache_read_tokens` / `mastra_model_input_cache_write_tokens` / `mastra_model_input_cache_write_5m_tokens` / `mastra_model_input_cache_write_1h_tokens` / `mastra_model_input_audio_tokens` / `mastra_model_input_image_tokens`
|
|
60
|
-
- `mastra_model_output_text_tokens` / `mastra_model_output_reasoning_tokens` / `mastra_model_output_audio_tokens` / `mastra_model_output_image_tokens`
|
|
61
|
-
|
|
62
|
-
For Anthropic models, the aggregate cache-write metric remains available while the 5-minute and 1-hour metrics preserve the provider's TTL-specific token counts and pricing.
|
|
63
|
-
|
|
64
|
-
Auto-extracted metrics carry labels: `entity_type`, `entity_name`, `status`, plus `model` and `provider` on model generation spans.
|
|
65
|
-
|
|
66
|
-
### Structured logging
|
|
67
|
-
|
|
68
|
-
`LoggerContextImpl` emits log events with automatic trace correlation (traceId, spanId), inherited tags, and entity metadata. Supports minimum log level filtering (debug/info/warn/error/fatal).
|
|
69
|
-
|
|
70
|
-
### Metrics context
|
|
71
|
-
|
|
72
|
-
`MetricsContextImpl` provides counter, gauge, and histogram instruments. All labels pass through a `CardinalityFilter` that blocks high-cardinality keys (trace_id, user_id, etc.) to protect metric backends.
|
|
73
|
-
|
|
74
|
-
## Span Types
|
|
75
|
-
|
|
76
|
-
- `WORKFLOW_RUN` - Workflow execution
|
|
77
|
-
- `WORKFLOW_STEP` - Individual workflow step
|
|
78
|
-
- `AGENT_RUN` - Agent processing
|
|
79
|
-
- `MODEL_GENERATION` - LLM API calls
|
|
80
|
-
- `TOOL_CALL` - Tool execution
|
|
81
|
-
- `MCP_TOOL_CALL` - MCP tool execution
|
|
82
|
-
- `PROCESSOR_RUN` - Processor execution
|
|
83
|
-
- `GENERIC` - Custom operations
|
|
84
|
-
|
|
85
|
-
## Metrics Labels
|
|
29
|
+
## Documentation
|
|
86
30
|
|
|
87
|
-
|
|
31
|
+
`Observability` instruments agent runs, model generations, tool and MCP calls, processor execution, workflow runs, and workflow steps. Each configured observability instance has its own service name, exporters, sampling strategy, and span processors.
|
|
88
32
|
|
|
89
|
-
|
|
90
|
-
| ------------- | -------------------------------------------------------------------- | --------------------------- |
|
|
91
|
-
| `entity_type` | What is being measured (e.g., `agent`, `tool`, `workflow_run`) | Small enum (~9 values) |
|
|
92
|
-
| `entity_name` | Name of the entity (e.g., `researcher`, `search`) | Bounded by defined entities |
|
|
93
|
-
| `model` | LLM model ID (only on model generation spans) | Bounded by LLM providers |
|
|
94
|
-
| `provider` | LLM provider (only on model generation spans) | Bounded by LLM providers |
|
|
95
|
-
| `status` | Outcome of the operation (`ok` or `error`), on `_ended` metrics only | 2 values |
|
|
33
|
+
Exporters receive tracing events through the central observability bus. `MastraStorageExporter` persists them to the configured Mastra storage so Studio can query them, while `MastraPlatformExporter` sends them to Mastra Platform. Additional packages provide exporters for services such as Arize, Braintrust, Langfuse, LangSmith, Sentry, and OpenTelemetry-compatible backends.
|
|
96
34
|
|
|
97
|
-
|
|
35
|
+
A `SensitiveDataFilter` output processor is enabled by default and redacts common secrets before spans reach exporters. Set `sensitiveDataFilter: false` to disable it, or provide filter options to customize its behavior. Sampling can retain every trace, use a ratio, or apply application-specific logic.
|
|
98
36
|
|
|
99
|
-
|
|
37
|
+
The package automatically derives duration, status, model token, and cache token metrics from span lifecycle events. Structured logs inherit trace and span IDs, tags, and entity metadata, while metric labels pass through cardinality filtering to prevent user IDs, trace IDs, and other unbounded values from overwhelming metrics backends.
|
|
100
38
|
|
|
101
|
-
|
|
102
|
-
| -------------- | --------------------------------------------------------------------------- | --------------------------- |
|
|
103
|
-
| `parent_type` | Entity type of the nearest parent | Same small enum |
|
|
104
|
-
| `parent_name` | Name of the nearest parent entity | Bounded by defined entities |
|
|
105
|
-
| `root_type` | Entity type of the outermost ancestor (only set when different from parent) | Same small enum |
|
|
106
|
-
| `root_name` | Name of the outermost ancestor entity | Bounded by defined entities |
|
|
107
|
-
| `service_name` | Service name from observability config | Single value per deployment |
|
|
39
|
+
- [Observability documentation](https://mastra.ai/docs/studio/observability)
|
|
108
40
|
|
|
109
|
-
|
|
41
|
+
## Changelog
|
|
110
42
|
|
|
111
|
-
|
|
112
|
-
- **Why is this tool slow only sometimes?** → group by `parent_name`
|
|
113
|
-
- **What's the total cost of this user-facing flow?** → group by `root_name`
|
|
114
|
-
- **Which model is cheapest for this agent?** → group by `model` where `entity_name=X`
|
|
43
|
+
See the [package changelog](https://github.com/mastra-ai/mastra/blob/main/observability/mastra/CHANGELOG.md) for version history and release notes.
|
|
115
44
|
|
|
116
|
-
##
|
|
45
|
+
## Support
|
|
117
46
|
|
|
118
|
-
|
|
47
|
+
We have an [open community Discord](https://discord.gg/mastra-ai). Come and say hello and let us know if you have any questions or need any help getting things running.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/context/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/context/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAyB,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAG/C,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IAExC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC,6BAA6B;IAC7B,gBAAgB,EAAE,gBAAgB,CAAC;IAEnC,wDAAwD;IACxD,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAWD,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,MAAM,CAAsB;IAEpC;;;OAGG;IACH,YAAY,MAAM,EAAE,mBAAmB,EAUtC;IAED,0BAA0B;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE3D;IAED,yBAAyB;IACzB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE1D;IAED,yBAAyB;IACzB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE1D;IAED,0BAA0B;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE3D;IAED,0BAA0B;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE3D;IAED;;OAEG;IACH,OAAO,CAAC,GAAG;CAqBZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/context/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/context/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,OAAO,EACP,KAAK,EACL,SAAS,EACT,kBAAkB,EAIlB,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IAExC,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC,0DAA0D;IAC1D,iBAAiB,EAAE,iBAAiB,CAAC;IAErC,6BAA6B;IAC7B,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,cAAc;IACvD,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,CAA0B;IAC3C,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,gBAAgB,CAAmB;IAE3C;;;OAGG;IACH,YAAY,MAAM,EAAE,oBAAoB,EAOvC;IAED,iCAAiC;IACjC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAuBpG;IAED,wCAAwC;IACxC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM7B;IAED,wCAAwC;IACxC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAMzB;IAED,wCAAwC;IACxC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAMjC;CACF"}
|
package/dist/ids.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signal and span id helpers.
|
|
3
|
+
*
|
|
4
|
+
* These two utilities also exist in `@mastra/core/observability`. This package
|
|
5
|
+
* deliberately keeps local copies rather than importing them.
|
|
6
|
+
*
|
|
7
|
+
* Importing a helper from core ties this package's real minimum core version to
|
|
8
|
+
* whichever release happened to add that helper. A named ESM import of an export
|
|
9
|
+
* that does not exist fails at link time, before any application code runs, so
|
|
10
|
+
* the mismatch surfaces as a startup crash rather than a resolvable install
|
|
11
|
+
* error. That is how `resolveExportedSpanId` (added in `@mastra/core@1.63.0`)
|
|
12
|
+
* broke deployments pinned to an older core while the declared peer floor still
|
|
13
|
+
* said `>=1.16.0`; `generateSignalId` (added in `@mastra/core@1.26.0`) had
|
|
14
|
+
* already raised the true floor the same way, unnoticed.
|
|
15
|
+
*
|
|
16
|
+
* Both helpers are self-contained: `generateSignalId` wraps `crypto.randomUUID`,
|
|
17
|
+
* and `resolveExportedSpanId` is structurally typed against an optional method
|
|
18
|
+
* rather than any core class. A local copy costs a few lines and lets the
|
|
19
|
+
* declared peer range stay honest.
|
|
20
|
+
*
|
|
21
|
+
* Keep them local. Re-importing either from core silently raises this package's
|
|
22
|
+
* minimum core version again.
|
|
23
|
+
*
|
|
24
|
+
* TODO(mastra-v2): delete this file and import both helpers from
|
|
25
|
+
* `@mastra/core/observability` again.
|
|
26
|
+
*
|
|
27
|
+
* The duplication exists only because a peer floor cannot be raised inside a
|
|
28
|
+
* major version without breaking consumers pinned to an older core. A v2
|
|
29
|
+
* release resets that floor anyway, so importing from core stops being a
|
|
30
|
+
* compatibility hazard at that point. On v2:
|
|
31
|
+
*
|
|
32
|
+
* 1. Set the `@mastra/core` peer range to the v2 line.
|
|
33
|
+
* 2. Re-point the four import sites -- `generateSignalId` in
|
|
34
|
+
* `context/logger.ts`, `context/metrics.ts` and `recorded.ts`, and
|
|
35
|
+
* `resolveExportedSpanId` in `instances/base.ts`.
|
|
36
|
+
* 3. Delete this file.
|
|
37
|
+
*
|
|
38
|
+
* Do not undo it before then: both helpers are still missing from cores inside
|
|
39
|
+
* this package's currently declared range (`generateSignalId` landed in core
|
|
40
|
+
* 1.26.0, `resolveExportedSpanId` in 1.63.0, floor is 1.16.0).
|
|
41
|
+
*
|
|
42
|
+
* Context: https://github.com/mastra-ai/mastra/issues/22885
|
|
43
|
+
*/
|
|
44
|
+
/** Generate a unique id for an observability signal (log, metric, score, feedback). */
|
|
45
|
+
export declare function generateSignalId(): string;
|
|
46
|
+
/**
|
|
47
|
+
* Resolve the spanId an observability signal should reference for a span.
|
|
48
|
+
*
|
|
49
|
+
* Signals (logs, metrics, and a suspending run's resume link) must name a span
|
|
50
|
+
* that actually reached exporters. An internal or excluded span is never stored,
|
|
51
|
+
* so referencing its raw id leaves the signal pointing at nothing: log/metric
|
|
52
|
+
* span lookups 404, and a resumed run's exported children inherit a dangling
|
|
53
|
+
* parentSpanId and land as orphans. `undefined` is a valid answer, omitting the
|
|
54
|
+
* reference rather than pointing it at a span that does not exist.
|
|
55
|
+
*
|
|
56
|
+
* `getExportedSpanId` is optional on the `Span` interface, so the typeof guard
|
|
57
|
+
* separates "this implementation predates the method" (keep the old behavior of
|
|
58
|
+
* referencing the span's own id) from "the method ran and found nothing
|
|
59
|
+
* exportable" (undefined). Without it the two collapse and custom span
|
|
60
|
+
* implementations silently lose correlation.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveExportedSpanId(span: {
|
|
63
|
+
id?: string;
|
|
64
|
+
getExportedSpanId?: () => string | undefined;
|
|
65
|
+
} | undefined | null): string | undefined;
|
|
66
|
+
//# sourceMappingURL=ids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,uFAAuF;AACvF,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,SAAS,GAAG,IAAI,GACrF,MAAM,GAAG,SAAS,CAGpB"}
|
package/dist/index.cjs
CHANGED
|
@@ -35,7 +35,7 @@ path = __toESM(path, 1);
|
|
|
35
35
|
let stream_web = require("stream/web");
|
|
36
36
|
let _mastra_core_features = require("@mastra/core/features");
|
|
37
37
|
let _mastra_core_storage = require("@mastra/core/storage");
|
|
38
|
-
let crypto = require("crypto");
|
|
38
|
+
let crypto$1 = require("crypto");
|
|
39
39
|
//#region src/bus/route-event.ts
|
|
40
40
|
/**
|
|
41
41
|
* Route a single event to the appropriate method on a handler.
|
|
@@ -887,13 +887,76 @@ const observabilityRegistryConfigSchema = zod_v4.z.object({
|
|
|
887
887
|
return true;
|
|
888
888
|
}, { message: "A \"configSelector\" requires at least one config or default observability to be configured." });
|
|
889
889
|
//#endregion
|
|
890
|
-
//#region src/
|
|
890
|
+
//#region src/ids.ts
|
|
891
|
+
/**
|
|
892
|
+
* Signal and span id helpers.
|
|
893
|
+
*
|
|
894
|
+
* These two utilities also exist in `@mastra/core/observability`. This package
|
|
895
|
+
* deliberately keeps local copies rather than importing them.
|
|
896
|
+
*
|
|
897
|
+
* Importing a helper from core ties this package's real minimum core version to
|
|
898
|
+
* whichever release happened to add that helper. A named ESM import of an export
|
|
899
|
+
* that does not exist fails at link time, before any application code runs, so
|
|
900
|
+
* the mismatch surfaces as a startup crash rather than a resolvable install
|
|
901
|
+
* error. That is how `resolveExportedSpanId` (added in `@mastra/core@1.63.0`)
|
|
902
|
+
* broke deployments pinned to an older core while the declared peer floor still
|
|
903
|
+
* said `>=1.16.0`; `generateSignalId` (added in `@mastra/core@1.26.0`) had
|
|
904
|
+
* already raised the true floor the same way, unnoticed.
|
|
905
|
+
*
|
|
906
|
+
* Both helpers are self-contained: `generateSignalId` wraps `crypto.randomUUID`,
|
|
907
|
+
* and `resolveExportedSpanId` is structurally typed against an optional method
|
|
908
|
+
* rather than any core class. A local copy costs a few lines and lets the
|
|
909
|
+
* declared peer range stay honest.
|
|
910
|
+
*
|
|
911
|
+
* Keep them local. Re-importing either from core silently raises this package's
|
|
912
|
+
* minimum core version again.
|
|
913
|
+
*
|
|
914
|
+
* TODO(mastra-v2): delete this file and import both helpers from
|
|
915
|
+
* `@mastra/core/observability` again.
|
|
916
|
+
*
|
|
917
|
+
* The duplication exists only because a peer floor cannot be raised inside a
|
|
918
|
+
* major version without breaking consumers pinned to an older core. A v2
|
|
919
|
+
* release resets that floor anyway, so importing from core stops being a
|
|
920
|
+
* compatibility hazard at that point. On v2:
|
|
921
|
+
*
|
|
922
|
+
* 1. Set the `@mastra/core` peer range to the v2 line.
|
|
923
|
+
* 2. Re-point the four import sites -- `generateSignalId` in
|
|
924
|
+
* `context/logger.ts`, `context/metrics.ts` and `recorded.ts`, and
|
|
925
|
+
* `resolveExportedSpanId` in `instances/base.ts`.
|
|
926
|
+
* 3. Delete this file.
|
|
927
|
+
*
|
|
928
|
+
* Do not undo it before then: both helpers are still missing from cores inside
|
|
929
|
+
* this package's currently declared range (`generateSignalId` landed in core
|
|
930
|
+
* 1.26.0, `resolveExportedSpanId` in 1.63.0, floor is 1.16.0).
|
|
931
|
+
*
|
|
932
|
+
* Context: https://github.com/mastra-ai/mastra/issues/22885
|
|
933
|
+
*/
|
|
934
|
+
/** Generate a unique id for an observability signal (log, metric, score, feedback). */
|
|
935
|
+
function generateSignalId() {
|
|
936
|
+
return crypto.randomUUID();
|
|
937
|
+
}
|
|
891
938
|
/**
|
|
892
|
-
*
|
|
939
|
+
* Resolve the spanId an observability signal should reference for a span.
|
|
893
940
|
*
|
|
894
|
-
*
|
|
895
|
-
*
|
|
941
|
+
* Signals (logs, metrics, and a suspending run's resume link) must name a span
|
|
942
|
+
* that actually reached exporters. An internal or excluded span is never stored,
|
|
943
|
+
* so referencing its raw id leaves the signal pointing at nothing: log/metric
|
|
944
|
+
* span lookups 404, and a resumed run's exported children inherit a dangling
|
|
945
|
+
* parentSpanId and land as orphans. `undefined` is a valid answer, omitting the
|
|
946
|
+
* reference rather than pointing it at a span that does not exist.
|
|
947
|
+
*
|
|
948
|
+
* `getExportedSpanId` is optional on the `Span` interface, so the typeof guard
|
|
949
|
+
* separates "this implementation predates the method" (keep the old behavior of
|
|
950
|
+
* referencing the span's own id) from "the method ran and found nothing
|
|
951
|
+
* exportable" (undefined). Without it the two collapse and custom span
|
|
952
|
+
* implementations silently lose correlation.
|
|
896
953
|
*/
|
|
954
|
+
function resolveExportedSpanId(span) {
|
|
955
|
+
if (!span) return void 0;
|
|
956
|
+
return typeof span.getExportedSpanId === "function" ? span.getExportedSpanId() : span.id;
|
|
957
|
+
}
|
|
958
|
+
//#endregion
|
|
959
|
+
//#region src/context/logger.ts
|
|
897
960
|
/** Numeric priority used to compare log levels against the configured minimum. */
|
|
898
961
|
const LOG_LEVEL_PRIORITY = {
|
|
899
962
|
debug: 0,
|
|
@@ -947,7 +1010,7 @@ var LoggerContextImpl = class {
|
|
|
947
1010
|
const event = {
|
|
948
1011
|
type: "log",
|
|
949
1012
|
log: {
|
|
950
|
-
logId:
|
|
1013
|
+
logId: generateSignalId(),
|
|
951
1014
|
timestamp: /* @__PURE__ */ new Date(),
|
|
952
1015
|
level,
|
|
953
1016
|
message,
|
|
@@ -964,13 +1027,6 @@ var LoggerContextImpl = class {
|
|
|
964
1027
|
//#endregion
|
|
965
1028
|
//#region src/context/metrics.ts
|
|
966
1029
|
/**
|
|
967
|
-
* MetricsContextImpl - User-facing metric emission API.
|
|
968
|
-
*
|
|
969
|
-
* All metrics are validated, cardinality-filtered, and constructed here
|
|
970
|
-
* before being routed through ObservabilityBus.emit().
|
|
971
|
-
* CorrelationContext and metadata are snapshotted at construction time.
|
|
972
|
-
*/
|
|
973
|
-
/**
|
|
974
1030
|
* User-facing metric emission API. All metrics are routed through
|
|
975
1031
|
* ObservabilityBus.emit() after validation and cardinality filtering.
|
|
976
1032
|
*/
|
|
@@ -1001,7 +1057,7 @@ var MetricsContextImpl = class {
|
|
|
1001
1057
|
const event = {
|
|
1002
1058
|
type: "metric",
|
|
1003
1059
|
metric: {
|
|
1004
|
-
metricId:
|
|
1060
|
+
metricId: generateSignalId(),
|
|
1005
1061
|
timestamp: /* @__PURE__ */ new Date(),
|
|
1006
1062
|
traceId: this.traceId,
|
|
1007
1063
|
spanId: this.spanId,
|
|
@@ -3482,7 +3538,7 @@ var BaseObservabilityInstance = class extends _mastra_core_base.MastraBase {
|
|
|
3482
3538
|
const metadata = span?.metadata ? structuredClone(span.metadata) : void 0;
|
|
3483
3539
|
return new LoggerContextImpl({
|
|
3484
3540
|
traceId: span?.traceId,
|
|
3485
|
-
spanId:
|
|
3541
|
+
spanId: resolveExportedSpanId(span),
|
|
3486
3542
|
correlationContext,
|
|
3487
3543
|
metadata,
|
|
3488
3544
|
observabilityBus: this.observabilityBus,
|
|
@@ -3499,7 +3555,7 @@ var BaseObservabilityInstance = class extends _mastra_core_base.MastraBase {
|
|
|
3499
3555
|
const metadata = span?.metadata ? structuredClone(span.metadata) : void 0;
|
|
3500
3556
|
return new MetricsContextImpl({
|
|
3501
3557
|
traceId: span?.traceId,
|
|
3502
|
-
spanId:
|
|
3558
|
+
spanId: resolveExportedSpanId(span),
|
|
3503
3559
|
correlationContext,
|
|
3504
3560
|
metadata,
|
|
3505
3561
|
cardinalityFilter: this.cardinalityFilter,
|
|
@@ -8695,7 +8751,7 @@ function buildScoreEvent(args) {
|
|
|
8695
8751
|
return {
|
|
8696
8752
|
type: "score",
|
|
8697
8753
|
score: {
|
|
8698
|
-
scoreId:
|
|
8754
|
+
scoreId: generateSignalId(),
|
|
8699
8755
|
timestamp: /* @__PURE__ */ new Date(),
|
|
8700
8756
|
traceId,
|
|
8701
8757
|
spanId,
|
|
@@ -8719,7 +8775,7 @@ function buildFeedbackEvent(args) {
|
|
|
8719
8775
|
return {
|
|
8720
8776
|
type: "feedback",
|
|
8721
8777
|
feedback: {
|
|
8722
|
-
feedbackId:
|
|
8778
|
+
feedbackId: generateSignalId(),
|
|
8723
8779
|
timestamp: /* @__PURE__ */ new Date(),
|
|
8724
8780
|
traceId,
|
|
8725
8781
|
spanId,
|
|
@@ -9214,7 +9270,7 @@ var SensitiveDataFilter = class {
|
|
|
9214
9270
|
return str.slice(0, 3) + "…" + str.slice(len - 3);
|
|
9215
9271
|
}
|
|
9216
9272
|
if (this.redactionStyle === "indexed" && indexedState) {
|
|
9217
|
-
const valueKey = (0, crypto.createHash)("sha256").update(String(value)).digest("hex");
|
|
9273
|
+
const valueKey = (0, crypto$1.createHash)("sha256").update(String(value)).digest("hex");
|
|
9218
9274
|
const existing = indexedState.tokensByValue.get(valueKey);
|
|
9219
9275
|
if (existing) return existing;
|
|
9220
9276
|
if (indexedState.tokensByValue.size >= MAX_TRACKED_VALUES_PER_TRACE) return this.redactionToken;
|