@mastra/datadog 1.1.1-alpha.0 → 1.2.0-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/CHANGELOG.md +21 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/features.d.ts +26 -0
- package/dist/features.d.ts.map +1 -0
- package/dist/index.cjs +92 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +92 -8
- package/dist/index.js.map +1 -1
- package/dist/tracing.d.ts +15 -1
- package/dist/tracing.d.ts.map +1 -1
- package/dist/utils.d.ts +7 -3
- package/dist/utils.d.ts.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @mastra/datadog
|
|
2
2
|
|
|
3
|
+
## 1.2.0-alpha.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Mastra Eval results are now forwarded to Datadog. ([#16185](https://github.com/mastra-ai/mastra/pull/16185))
|
|
8
|
+
|
|
9
|
+
- Mapped `MODEL_INFERENCE` spans to Datadog's `llm` kind (with token usage and model/provider attached) and `MODEL_STEP` to `workflow`. Falls back to the previous mapping when paired with an older `@mastra/core` that does not emit `MODEL_INFERENCE`. ([#16363](https://github.com/mastra-ai/mastra/pull/16363))
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`6742347`](https://github.com/mastra-ai/mastra/commit/6742347d71955d7639adc9ddf6ff8282de7ee3ba), [`7b0ad1f`](https://github.com/mastra-ai/mastra/commit/7b0ad1f5c53dc118c6da12ae82ae2587037dc2b8), [`62666c3`](https://github.com/mastra-ai/mastra/commit/62666c367eaeac3941ead454b1d38810cc855721), [`4af2160`](https://github.com/mastra-ai/mastra/commit/4af2160322f4718cac421930cce85641e9512389), [`b2fd6be`](https://github.com/mastra-ai/mastra/commit/b2fd6beef989f5e463c9a33d8a6c20ac1800e011), [`136c959`](https://github.com/mastra-ai/mastra/commit/136c9592fb0eeb0cd212f28629d8a29b7557a2fc), [`00106be`](https://github.com/mastra-ai/mastra/commit/00106bede59b81e5b0e9cd6aad8d3b5dbc336387), [`4df7cc7`](https://github.com/mastra-ai/mastra/commit/4df7cc79342fd065fe7fdeef93c094db14b12bcd), [`aca3121`](https://github.com/mastra-ai/mastra/commit/aca31211233dac25459f140ea4fcfb3a5af64c18), [`7b0ad1f`](https://github.com/mastra-ai/mastra/commit/7b0ad1f5c53dc118c6da12ae82ae2587037dc2b8), [`9cdf38e`](https://github.com/mastra-ai/mastra/commit/9cdf38e58506e1109c8b38f97cd7770978a4218e), [`990851e`](https://github.com/mastra-ai/mastra/commit/990851edcb0e30be5c2c18b6532f1a876cc2d335), [`6068a6c`](https://github.com/mastra-ai/mastra/commit/6068a6c42950fad3ebfc92346417896ba60803d2), [`00106be`](https://github.com/mastra-ai/mastra/commit/00106bede59b81e5b0e9cd6aad8d3b5dbc336387), [`e2a079c`](https://github.com/mastra-ai/mastra/commit/e2a079cc3755b1895f7bd5dc36e9be81b11c7c22), [`534a456`](https://github.com/mastra-ai/mastra/commit/534a456a25e4df1e5407e7e632f4cb3b1fa14f9d), [`36bae07`](https://github.com/mastra-ai/mastra/commit/36bae07c0e70b1b3006f2fd20830e8883dcbd066)]:
|
|
14
|
+
- @mastra/core@1.33.0-alpha.7
|
|
15
|
+
- @mastra/observability@1.12.0-alpha.1
|
|
16
|
+
|
|
17
|
+
## 1.1.1-alpha.1
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies [[`00ef282`](https://github.com/mastra-ai/mastra/commit/00ef2826034d006b984b3f19cd33ba0bba14d6c6)]:
|
|
22
|
+
- @mastra/observability@1.12.0-alpha.0
|
|
23
|
+
|
|
3
24
|
## 1.1.1-alpha.0
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/dist/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,YAAY,
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,YAAY,EAKZ,mBAAmB,EACnB,iBAAiB,EACjB,QAAQ,EACR,OAAO,EACR,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,YAAY,EAAuB,MAAM,uBAAuB,CAAC;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AA+DhE;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,YAAa,YAAW,mBAAmB;IAC5E,IAAI,SAAoB;IAExB,OAAO,CAAC,MAAM,CAA8E;IAC5F,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,cAAc,CAA6B;gBAEvC,MAAM,GAAE,mBAAwB;IAyC5C;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,iBAAiB,CAAC,QAAQ,CAAC,GAAG,OAAO,GAAG,SAAS;IAgErE;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAIrE;;OAEG;IACH,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAIvD,OAAO,CAAC,sBAAsB;IAmB9B;;OAEG;cACa,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BvE,OAAO,CAAC,kBAAkB;IA0C1B,OAAO,CAAC,eAAe;IASvB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAwD7B,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,gBAAgB;IA8FxB,OAAO,CAAC,YAAY;IASd,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CA2BhC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature detection for paired @mastra/core and @mastra/observability versions.
|
|
3
|
+
*
|
|
4
|
+
* `coreFeatures` is a hard peer dependency, so it can be imported statically.
|
|
5
|
+
* `observabilityFeatures` is loaded via dynamic import so this exporter degrades
|
|
6
|
+
* gracefully against older `@mastra/observability` versions that don't export it
|
|
7
|
+
* (per the pattern documented in `observability/mastra/src/features.ts`).
|
|
8
|
+
*
|
|
9
|
+
* Detection runs once at module load. Callers consume the result through the
|
|
10
|
+
* sync `isModelInferenceEnabled()` accessor, which conservatively returns
|
|
11
|
+
* `false` until detection settles — long enough only to cover the microtask
|
|
12
|
+
* window before any spans are emitted in practice.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Returns true when both packages report the `model-inference-span` feature,
|
|
16
|
+
* meaning MODEL_INFERENCE spans are emitted by the tracker. Drives the
|
|
17
|
+
* Datadog kind mapping and usage-source switch (legacy: MODEL_STEP carries
|
|
18
|
+
* 'llm' kind + usage; new: MODEL_INFERENCE does).
|
|
19
|
+
*/
|
|
20
|
+
export declare function isModelInferenceEnabled(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* @internal Test-only override. Allows tests to simulate a paired older or
|
|
23
|
+
* newer `@mastra/observability` without juggling dynamic imports.
|
|
24
|
+
*/
|
|
25
|
+
export declare function __setObservabilityFeaturesForTest(features: ReadonlySet<string> | undefined): void;
|
|
26
|
+
//# sourceMappingURL=features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../src/features.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA0BH;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAED;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,GAAG,IAAI,CAIjG"}
|
package/dist/index.cjs
CHANGED
|
@@ -4,12 +4,29 @@ var observability$1 = require('@mastra/core/observability');
|
|
|
4
4
|
var utils = require('@mastra/core/utils');
|
|
5
5
|
var observability = require('@mastra/observability');
|
|
6
6
|
var tracer3 = require('dd-trace');
|
|
7
|
+
var features = require('@mastra/core/features');
|
|
7
8
|
|
|
8
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
10
|
|
|
10
11
|
var tracer3__default = /*#__PURE__*/_interopDefault(tracer3);
|
|
11
12
|
|
|
12
13
|
// src/bridge.ts
|
|
14
|
+
var FEATURE = "model-inference-span";
|
|
15
|
+
var observabilityFeatures;
|
|
16
|
+
var featureLoadPromise;
|
|
17
|
+
function loadObservabilityFeatures() {
|
|
18
|
+
if (!featureLoadPromise) {
|
|
19
|
+
featureLoadPromise = import('@mastra/observability').then((mod) => {
|
|
20
|
+
observabilityFeatures = mod.observabilityFeatures;
|
|
21
|
+
}).catch(() => {
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return featureLoadPromise;
|
|
25
|
+
}
|
|
26
|
+
void loadObservabilityFeatures();
|
|
27
|
+
function isModelInferenceEnabled() {
|
|
28
|
+
return observabilityFeatures?.has(FEATURE) === true && features.coreFeatures.has(FEATURE);
|
|
29
|
+
}
|
|
13
30
|
|
|
14
31
|
// src/metrics.ts
|
|
15
32
|
function formatUsageMetrics(usage) {
|
|
@@ -35,18 +52,26 @@ function formatUsageMetrics(usage) {
|
|
|
35
52
|
}
|
|
36
53
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
37
54
|
}
|
|
38
|
-
var
|
|
55
|
+
var SPAN_TYPE_TO_KIND_LEGACY = {
|
|
39
56
|
[observability$1.SpanType.AGENT_RUN]: "agent",
|
|
40
|
-
// MODEL_GENERATION is the wrapper around 1..N MODEL_STEPs (the actual API calls).
|
|
41
|
-
// It maps to 'workflow' so Datadog doesn't double-count it as an LLM call.
|
|
42
57
|
[observability$1.SpanType.MODEL_GENERATION]: "workflow",
|
|
43
|
-
// MODEL_STEP is "Single model execution step within a generation (one API call)"
|
|
44
|
-
// per packages/core/src/observability/types/tracing.ts, so it is the real LLM span.
|
|
45
58
|
[observability$1.SpanType.MODEL_STEP]: "llm",
|
|
46
59
|
[observability$1.SpanType.TOOL_CALL]: "tool",
|
|
47
60
|
[observability$1.SpanType.MCP_TOOL_CALL]: "tool",
|
|
48
61
|
[observability$1.SpanType.WORKFLOW_RUN]: "workflow"
|
|
49
62
|
};
|
|
63
|
+
var SPAN_TYPE_TO_KIND_INFERENCE = {
|
|
64
|
+
[observability$1.SpanType.AGENT_RUN]: "agent",
|
|
65
|
+
[observability$1.SpanType.MODEL_GENERATION]: "workflow",
|
|
66
|
+
[observability$1.SpanType.MODEL_STEP]: "workflow",
|
|
67
|
+
[observability$1.SpanType.MODEL_INFERENCE]: "llm",
|
|
68
|
+
[observability$1.SpanType.TOOL_CALL]: "tool",
|
|
69
|
+
[observability$1.SpanType.MCP_TOOL_CALL]: "tool",
|
|
70
|
+
[observability$1.SpanType.WORKFLOW_RUN]: "workflow"
|
|
71
|
+
};
|
|
72
|
+
function getSpanTypeToKind() {
|
|
73
|
+
return isModelInferenceEnabled() ? SPAN_TYPE_TO_KIND_INFERENCE : SPAN_TYPE_TO_KIND_LEGACY;
|
|
74
|
+
}
|
|
50
75
|
var tracerInitFlag = { done: false };
|
|
51
76
|
function ensureTracer(config) {
|
|
52
77
|
if (tracerInitFlag.done) return;
|
|
@@ -72,7 +97,7 @@ function ensureTracer(config) {
|
|
|
72
97
|
tracerInitFlag.done = true;
|
|
73
98
|
}
|
|
74
99
|
function kindFor(spanType) {
|
|
75
|
-
return
|
|
100
|
+
return getSpanTypeToKind()[spanType] || "task";
|
|
76
101
|
}
|
|
77
102
|
function toDate(value) {
|
|
78
103
|
return value instanceof Date ? value : new Date(value);
|
|
@@ -447,7 +472,8 @@ var DatadogBridge = class extends observability.BaseExporter {
|
|
|
447
472
|
if (span.output !== void 0) {
|
|
448
473
|
annotations.outputData = formatOutput(span.output, span.type);
|
|
449
474
|
}
|
|
450
|
-
|
|
475
|
+
const usageSpanType = isModelInferenceEnabled() ? observability$1.SpanType.MODEL_INFERENCE : observability$1.SpanType.MODEL_STEP;
|
|
476
|
+
if (span.type === usageSpanType) {
|
|
451
477
|
const usage = span.attributes?.usage;
|
|
452
478
|
const metrics = formatUsageMetrics(usage);
|
|
453
479
|
if (metrics) {
|
|
@@ -713,7 +739,8 @@ var DatadogExporter = class extends observability.BaseExporter {
|
|
|
713
739
|
if (span.output !== void 0) {
|
|
714
740
|
annotations.outputData = formatOutput(span.output, span.type);
|
|
715
741
|
}
|
|
716
|
-
|
|
742
|
+
const usageSpanType = isModelInferenceEnabled() ? observability$1.SpanType.MODEL_INFERENCE : observability$1.SpanType.MODEL_STEP;
|
|
743
|
+
if (span.type === usageSpanType) {
|
|
717
744
|
const usage = span.attributes?.usage;
|
|
718
745
|
const metrics = formatUsageMetrics(usage);
|
|
719
746
|
if (metrics) {
|
|
@@ -783,6 +810,63 @@ var DatadogExporter = class extends observability.BaseExporter {
|
|
|
783
810
|
}
|
|
784
811
|
return annotations;
|
|
785
812
|
}
|
|
813
|
+
/**
|
|
814
|
+
* Submit an eval score to Datadog LLM Observability for the matching ddSpan.
|
|
815
|
+
*
|
|
816
|
+
* Ordering constraint: the matching span must have already been emitted to dd-trace
|
|
817
|
+
* (i.e. its `SPAN_ENDED` event must have been processed and the trace tree flushed).
|
|
818
|
+
* On Mastra's normal scoring path this is always true — scorer hooks fire after the
|
|
819
|
+
* scored entity completes, so the root span has ended by the time `onScoreEvent` runs.
|
|
820
|
+
*
|
|
821
|
+
* If a score arrives for an unexported span (either before `SPAN_ENDED` or after the
|
|
822
|
+
* `traceState` entry has been cleaned up), the event is dropped and a warning is logged
|
|
823
|
+
* so the misuse is observable. Scores must therefore only be submitted for spans whose
|
|
824
|
+
* lifecycle has completed.
|
|
825
|
+
*/
|
|
826
|
+
async onScoreEvent(event) {
|
|
827
|
+
if (this.isDisabled || !tracer3__default.default.llmobs?.submitEvaluation) return;
|
|
828
|
+
const { score } = event;
|
|
829
|
+
if (!score.traceId || !score.spanId) {
|
|
830
|
+
this.logger.warn("Datadog exporter: dropping score with no traceId/spanId", {
|
|
831
|
+
scorerId: score.scorerId
|
|
832
|
+
});
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
const ctx = this.traceState.get(score.traceId)?.contexts.get(score.spanId);
|
|
836
|
+
const exported = ctx?.exported;
|
|
837
|
+
if (!exported) {
|
|
838
|
+
this.logger.warn(
|
|
839
|
+
"Datadog exporter: dropping score for span that has not been emitted to dd-trace yet (span_ended must be processed before submitting a score for it)",
|
|
840
|
+
{
|
|
841
|
+
traceId: score.traceId,
|
|
842
|
+
spanId: score.spanId,
|
|
843
|
+
scorerId: score.scorerId
|
|
844
|
+
}
|
|
845
|
+
);
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
try {
|
|
849
|
+
tracer3__default.default.llmobs.submitEvaluation(
|
|
850
|
+
{ traceId: exported.traceId, spanId: exported.spanId },
|
|
851
|
+
{
|
|
852
|
+
label: score.scorerName ?? score.scorerId,
|
|
853
|
+
value: score.score,
|
|
854
|
+
metricType: "score",
|
|
855
|
+
mlApp: this.config.mlApp,
|
|
856
|
+
timestampMs: score.timestamp instanceof Date ? score.timestamp.getTime() : Date.now(),
|
|
857
|
+
...score.reason ? { reasoning: score.reason } : {},
|
|
858
|
+
...score.metadata ? { metadata: score.metadata } : {}
|
|
859
|
+
}
|
|
860
|
+
);
|
|
861
|
+
} catch (err) {
|
|
862
|
+
this.logger.error("Datadog exporter: Failed to submit evaluation", {
|
|
863
|
+
error: err,
|
|
864
|
+
traceId: score.traceId,
|
|
865
|
+
spanId: score.spanId,
|
|
866
|
+
scorerId: score.scorerId
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
}
|
|
786
870
|
/**
|
|
787
871
|
* Force flush any buffered spans without shutting down the exporter.
|
|
788
872
|
* This is useful in serverless environments where you need to ensure spans
|