@mastra/braintrust 0.0.0-scorers-ui-refactored-20250916094952 → 0.0.0-scorers-logs-20251208093427

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
@@ -1,63 +1,87 @@
1
- import { AISpanType, omitKeys } from '@mastra/core/ai-tracing';
2
- import { ConsoleLogger } from '@mastra/core/logger';
3
- import { initLogger } from 'braintrust';
1
+ import { SpanType } from '@mastra/core/observability';
2
+ import { omitKeys } from '@mastra/core/utils';
3
+ import { BaseExporter } from '@mastra/observability';
4
+ import { initLogger, currentSpan } from 'braintrust';
4
5
 
5
- // src/ai-tracing.ts
6
+ // src/tracing.ts
6
7
 
7
8
  // src/metrics.ts
8
- function normalizeUsageMetrics(llmAttr) {
9
+ function normalizeUsageMetrics(modelAttr) {
9
10
  const metrics = {};
10
- if (llmAttr.usage?.promptTokens !== void 0) {
11
- metrics.prompt_tokens = llmAttr.usage?.promptTokens;
11
+ if (modelAttr.usage?.inputTokens !== void 0) {
12
+ metrics.prompt_tokens = modelAttr.usage?.inputTokens;
13
+ } else if (modelAttr.usage?.promptTokens !== void 0) {
14
+ metrics.prompt_tokens = modelAttr.usage?.promptTokens;
12
15
  }
13
- if (llmAttr.usage?.completionTokens !== void 0) {
14
- metrics.completion_tokens = llmAttr.usage?.completionTokens;
16
+ if (modelAttr.usage?.outputTokens !== void 0) {
17
+ metrics.completion_tokens = modelAttr.usage?.outputTokens;
18
+ } else if (modelAttr.usage?.completionTokens !== void 0) {
19
+ metrics.completion_tokens = modelAttr.usage?.completionTokens;
15
20
  }
16
- if (llmAttr.usage?.totalTokens !== void 0) {
17
- metrics.tokens = llmAttr.usage?.totalTokens;
21
+ if (modelAttr.usage?.totalTokens !== void 0) {
22
+ metrics.tokens = modelAttr.usage?.totalTokens;
18
23
  }
19
- if (llmAttr.usage?.promptCacheHitTokens !== void 0) {
20
- metrics.prompt_cached_tokens = llmAttr.usage?.promptCacheHitTokens;
24
+ if (modelAttr.usage?.reasoningTokens !== void 0) {
25
+ metrics.completion_reasoning_tokens = modelAttr.usage?.reasoningTokens;
21
26
  }
22
- if (llmAttr.usage?.promptCacheMissTokens !== void 0) {
23
- metrics.prompt_cache_creation_tokens = llmAttr.usage?.promptCacheMissTokens;
27
+ if (modelAttr.usage?.promptCacheHitTokens !== void 0) {
28
+ metrics.prompt_cached_tokens = modelAttr.usage?.promptCacheHitTokens;
29
+ }
30
+ if (modelAttr.usage?.promptCacheMissTokens !== void 0) {
31
+ metrics.prompt_cache_creation_tokens = modelAttr.usage?.promptCacheMissTokens;
32
+ }
33
+ if (modelAttr.completionStartTime) {
34
+ const startTime = modelAttr.completionStartTime;
35
+ if (startTime instanceof Date) {
36
+ metrics.time_to_first_token = startTime.getTime();
37
+ } else if (typeof startTime === "number") {
38
+ metrics.time_to_first_token = startTime;
39
+ } else if (typeof startTime === "string") {
40
+ metrics.time_to_first_token = new Date(startTime).getTime();
41
+ }
24
42
  }
25
43
  return metrics;
26
44
  }
27
45
 
28
- // src/ai-tracing.ts
46
+ // src/tracing.ts
47
+ var MASTRA_TRACE_ID_METADATA_KEY = "mastra-trace-id";
29
48
  var DEFAULT_SPAN_TYPE = "task";
30
49
  var SPAN_TYPE_EXCEPTIONS = {
31
- [AISpanType.LLM_GENERATION]: "llm",
32
- [AISpanType.LLM_CHUNK]: "llm",
33
- [AISpanType.TOOL_CALL]: "tool",
34
- [AISpanType.MCP_TOOL_CALL]: "tool",
35
- [AISpanType.WORKFLOW_CONDITIONAL_EVAL]: "function",
36
- [AISpanType.WORKFLOW_WAIT_EVENT]: "function"
50
+ [SpanType.MODEL_GENERATION]: "llm",
51
+ [SpanType.MODEL_CHUNK]: "llm",
52
+ [SpanType.TOOL_CALL]: "tool",
53
+ [SpanType.MCP_TOOL_CALL]: "tool",
54
+ [SpanType.WORKFLOW_CONDITIONAL_EVAL]: "function",
55
+ [SpanType.WORKFLOW_WAIT_EVENT]: "function"
37
56
  };
38
57
  function mapSpanType(spanType) {
39
58
  return SPAN_TYPE_EXCEPTIONS[spanType] ?? DEFAULT_SPAN_TYPE;
40
59
  }
41
- var BraintrustExporter = class {
60
+ var BraintrustExporter = class extends BaseExporter {
42
61
  name = "braintrust";
43
62
  traceMap = /* @__PURE__ */ new Map();
44
- logger;
45
63
  config;
64
+ // Flags and logger for context-aware mode
65
+ useProvidedLogger;
66
+ providedLogger;
46
67
  constructor(config) {
47
- this.logger = new ConsoleLogger({ level: config.logLevel ?? "warn" });
48
- if (!config.apiKey) {
49
- this.logger.error("BraintrustExporter: Missing required credentials, exporter will be disabled", {
50
- hasApiKey: !!config.apiKey
51
- });
52
- this.config = null;
53
- return;
68
+ super(config);
69
+ if (config.braintrustLogger) {
70
+ this.useProvidedLogger = true;
71
+ this.providedLogger = config.braintrustLogger;
72
+ this.config = config;
73
+ } else {
74
+ if (!config.apiKey) {
75
+ this.setDisabled(`Missing required credentials (apiKey: ${!!config.apiKey})`);
76
+ this.config = null;
77
+ this.useProvidedLogger = false;
78
+ return;
79
+ }
80
+ this.useProvidedLogger = false;
81
+ this.config = config;
54
82
  }
55
- this.config = config;
56
83
  }
57
- async exportEvent(event) {
58
- if (!this.config) {
59
- return;
60
- }
84
+ async _exportTracingEvent(event) {
61
85
  if (event.exportedSpan.isEvent) {
62
86
  await this.handleEventSpan(event.exportedSpan);
63
87
  return;
@@ -76,23 +100,37 @@ var BraintrustExporter = class {
76
100
  }
77
101
  async handleSpanStarted(span) {
78
102
  if (span.isRootSpan) {
79
- await this.initLogger(span);
103
+ if (this.useProvidedLogger) {
104
+ await this.initLoggerOrUseContext(span);
105
+ } else {
106
+ await this.initLoggerPerTrace(span);
107
+ }
80
108
  }
81
109
  const method = "handleSpanStarted";
82
110
  const spanData = this.getSpanData({ span, method });
83
111
  if (!spanData) {
84
112
  return;
85
113
  }
114
+ if (!span.isEvent) {
115
+ spanData.activeIds.add(span.id);
116
+ }
86
117
  const braintrustParent = this.getBraintrustParent({ spanData, span, method });
87
118
  if (!braintrustParent) {
88
119
  return;
89
120
  }
90
121
  const payload = this.buildSpanPayload(span);
91
122
  const braintrustSpan = braintrustParent.startSpan({
123
+ spanId: span.id,
92
124
  name: span.name,
93
125
  type: mapSpanType(span.type),
94
126
  ...payload
95
127
  });
128
+ braintrustSpan.log({
129
+ metadata: {
130
+ [MASTRA_TRACE_ID_METADATA_KEY]: span.traceId
131
+ },
132
+ ...span.isRootSpan && span.tags?.length ? { tags: span.tags } : {}
133
+ });
96
134
  spanData.spans.set(span.id, braintrustSpan);
97
135
  }
98
136
  async handleSpanUpdateOrEnd(span, isEnd) {
@@ -121,7 +159,10 @@ var BraintrustExporter = class {
121
159
  } else {
122
160
  braintrustSpan.end();
123
161
  }
124
- if (span.isRootSpan) {
162
+ if (!span.isEvent) {
163
+ spanData.activeIds.delete(span.id);
164
+ }
165
+ if (spanData.activeIds.size === 0 && !spanData.isExternal) {
125
166
  this.traceMap.delete(span.traceId);
126
167
  }
127
168
  }
@@ -134,7 +175,11 @@ var BraintrustExporter = class {
134
175
  spanName: span.name,
135
176
  method: "handleEventSpan"
136
177
  });
137
- await this.initLogger(span);
178
+ if (this.useProvidedLogger) {
179
+ await this.initLoggerOrUseContext(span);
180
+ } else {
181
+ await this.initLoggerPerTrace(span);
182
+ }
138
183
  }
139
184
  const method = "handleEventSpan";
140
185
  const spanData = this.getSpanData({ span, method });
@@ -147,22 +192,59 @@ var BraintrustExporter = class {
147
192
  }
148
193
  const payload = this.buildSpanPayload(span);
149
194
  const braintrustSpan = braintrustParent.startSpan({
195
+ spanId: span.id,
150
196
  name: span.name,
151
197
  type: mapSpanType(span.type),
152
198
  startTime: span.startTime.getTime() / 1e3,
153
199
  ...payload
154
200
  });
155
201
  braintrustSpan.end({ endTime: span.startTime.getTime() / 1e3 });
156
- spanData.spans.set(span.id, braintrustSpan);
157
202
  }
158
- async initLogger(span) {
203
+ initTraceMap(params) {
204
+ const { traceId, isExternal, logger } = params;
205
+ if (this.traceMap.has(traceId)) {
206
+ this.logger.debug("Braintrust exporter: Reusing existing trace from local map", { traceId });
207
+ return;
208
+ }
209
+ this.traceMap.set(traceId, {
210
+ logger,
211
+ spans: /* @__PURE__ */ new Map(),
212
+ activeIds: /* @__PURE__ */ new Set(),
213
+ isExternal
214
+ });
215
+ }
216
+ /**
217
+ * Creates a new logger per trace using config credentials
218
+ */
219
+ async initLoggerPerTrace(span) {
220
+ if (this.traceMap.has(span.traceId)) {
221
+ this.logger.debug("Braintrust exporter: Reusing existing trace from local map", { traceId: span.traceId });
222
+ return;
223
+ }
159
224
  const logger = await initLogger({
160
225
  projectName: this.config.projectName ?? "mastra-tracing",
161
226
  apiKey: this.config.apiKey,
162
227
  appUrl: this.config.endpoint,
163
228
  ...this.config.tuningParameters
164
229
  });
165
- this.traceMap.set(span.traceId, { logger, spans: /* @__PURE__ */ new Map() });
230
+ this.initTraceMap({ logger, isExternal: false, traceId: span.traceId });
231
+ }
232
+ /**
233
+ * Uses provided logger and detects external Braintrust spans.
234
+ * If a Braintrust span is detected (from logger.traced() or Eval()), attaches to it.
235
+ * Otherwise, uses the provided logger instance.
236
+ */
237
+ async initLoggerOrUseContext(span) {
238
+ if (this.traceMap.has(span.traceId)) {
239
+ this.logger.debug("Braintrust exporter: Reusing existing trace from local map", { traceId: span.traceId });
240
+ return;
241
+ }
242
+ const braintrustSpan = currentSpan();
243
+ if (braintrustSpan && braintrustSpan.id) {
244
+ this.initTraceMap({ logger: braintrustSpan, isExternal: true, traceId: span.traceId });
245
+ } else {
246
+ this.initTraceMap({ logger: this.providedLogger, isExternal: false, traceId: span.traceId });
247
+ }
166
248
  }
167
249
  getSpanData(options) {
168
250
  const { span, method } = options;
@@ -188,6 +270,9 @@ var BraintrustExporter = class {
188
270
  if (spanData.spans.has(parentId)) {
189
271
  return spanData.spans.get(parentId);
190
272
  }
273
+ if (parentId && !spanData.spans.has(parentId)) {
274
+ return spanData.logger;
275
+ }
191
276
  this.logger.warn("Braintrust exporter: No parent data found for span", {
192
277
  traceId: span.traceId,
193
278
  spanId: span.id,
@@ -198,13 +283,36 @@ var BraintrustExporter = class {
198
283
  method
199
284
  });
200
285
  }
286
+ /**
287
+ * Transforms MODEL_GENERATION input to Braintrust Thread view format.
288
+ */
289
+ transformInput(input, spanType) {
290
+ if (spanType === SpanType.MODEL_GENERATION) {
291
+ if (input && Array.isArray(input.messages)) {
292
+ return input.messages;
293
+ } else if (input && typeof input === "object" && "content" in input) {
294
+ return [{ role: input.role, content: input.content }];
295
+ }
296
+ }
297
+ return input;
298
+ }
299
+ /**
300
+ * Transforms MODEL_GENERATION output to Braintrust Thread view format.
301
+ */
302
+ transformOutput(output, spanType) {
303
+ if (spanType === SpanType.MODEL_GENERATION) {
304
+ const { text, ...rest } = output;
305
+ return { role: "assistant", content: text, ...rest };
306
+ }
307
+ return output;
308
+ }
201
309
  buildSpanPayload(span) {
202
310
  const payload = {};
203
311
  if (span.input !== void 0) {
204
- payload.input = span.input;
312
+ payload.input = this.transformInput(span.input, span.type);
205
313
  }
206
314
  if (span.output !== void 0) {
207
- payload.output = span.output;
315
+ payload.output = this.transformOutput(span.output, span.type);
208
316
  }
209
317
  payload.metrics = {};
210
318
  payload.metadata = {
@@ -212,17 +320,17 @@ var BraintrustExporter = class {
212
320
  ...span.metadata
213
321
  };
214
322
  const attributes = span.attributes ?? {};
215
- if (span.type === AISpanType.LLM_GENERATION) {
216
- const llmAttr = attributes;
217
- if (llmAttr.model !== void 0) {
218
- payload.metadata.model = llmAttr.model;
323
+ if (span.type === SpanType.MODEL_GENERATION) {
324
+ const modelAttr = attributes;
325
+ if (modelAttr.model !== void 0) {
326
+ payload.metadata.model = modelAttr.model;
219
327
  }
220
- if (llmAttr.provider !== void 0) {
221
- payload.metadata.provider = llmAttr.provider;
328
+ if (modelAttr.provider !== void 0) {
329
+ payload.metadata.provider = modelAttr.provider;
222
330
  }
223
- payload.metrics = normalizeUsageMetrics(llmAttr);
224
- if (llmAttr.parameters !== void 0) {
225
- payload.metadata.modelParameters = llmAttr.parameters;
331
+ payload.metrics = normalizeUsageMetrics(modelAttr);
332
+ if (modelAttr.parameters !== void 0) {
333
+ payload.metadata.modelParameters = modelAttr.parameters;
226
334
  }
227
335
  const otherAttributes = omitKeys(attributes, ["model", "usage", "parameters"]);
228
336
  payload.metadata = {
@@ -254,6 +362,7 @@ var BraintrustExporter = class {
254
362
  }
255
363
  }
256
364
  this.traceMap.clear();
365
+ await super.shutdown();
257
366
  }
258
367
  };
259
368
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/metrics.ts","../src/ai-tracing.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { LLMGenerationAttributes } from '@mastra/core/ai-tracing';\n/**\n * BraintrustUsageMetrics\n *\n * Canonical metric keys expected by Braintrust for LLM usage accounting.\n * These map various provider/SDK-specific usage fields to a common schema.\n * - prompt_tokens: input-side tokens (aka inputTokens/promptTokens)\n * - completion_tokens: output-side tokens (aka outputTokens/completionTokens)\n * - tokens: total tokens (provided or derived)\n * - completion_reasoning_tokens: reasoning tokens, when available\n * - prompt_cached_tokens: tokens served from cache (provider-specific)\n * - prompt_cache_creation_tokens: tokens used to create cache (provider-specific)\n */\nexport interface BraintrustUsageMetrics {\n prompt_tokens?: number;\n completion_tokens?: number;\n tokens?: number;\n completion_reasoning_tokens?: number;\n prompt_cached_tokens?: number;\n prompt_cache_creation_tokens?: number;\n [key: string]: number | undefined;\n}\n\nexport function normalizeUsageMetrics(llmAttr: LLMGenerationAttributes): BraintrustUsageMetrics {\n const metrics: BraintrustUsageMetrics = {};\n\n if (llmAttr.usage?.promptTokens !== undefined) {\n metrics.prompt_tokens = llmAttr.usage?.promptTokens;\n }\n if (llmAttr.usage?.completionTokens !== undefined) {\n metrics.completion_tokens = llmAttr.usage?.completionTokens;\n }\n if (llmAttr.usage?.totalTokens !== undefined) {\n metrics.tokens = llmAttr.usage?.totalTokens;\n }\n if (llmAttr.usage?.promptCacheHitTokens !== undefined) {\n metrics.prompt_cached_tokens = llmAttr.usage?.promptCacheHitTokens;\n }\n if (llmAttr.usage?.promptCacheMissTokens !== undefined) {\n metrics.prompt_cache_creation_tokens = llmAttr.usage?.promptCacheMissTokens;\n }\n\n return metrics;\n}\n","/**\n * Braintrust Exporter for Mastra AI Tracing\n *\n * This exporter sends tracing data to Braintrust for AI observability.\n * Root spans become top-level Braintrust spans (no trace wrapper).\n * Events are handled as zero-duration spans with matching start/end times.\n */\n\nimport type {\n AITracingExporter,\n AITracingEvent,\n AnyExportedAISpan,\n LLMGenerationAttributes,\n} from '@mastra/core/ai-tracing';\nimport { AISpanType, omitKeys } from '@mastra/core/ai-tracing';\nimport { ConsoleLogger } from '@mastra/core/logger';\nimport { initLogger } from 'braintrust';\nimport type { Span, Logger } from 'braintrust';\nimport { normalizeUsageMetrics } from './metrics';\n\nexport interface BraintrustExporterConfig {\n /** Braintrust API key */\n apiKey?: string;\n /** Optional custom endpoint */\n endpoint?: string;\n /** Braintrust project name (default: 'mastra-tracing') */\n projectName?: string;\n /** Logger level for diagnostic messages (default: 'warn') */\n logLevel?: 'debug' | 'info' | 'warn' | 'error';\n /** Support tuning parameters */\n tuningParameters?: Record<string, any>;\n}\n\ntype SpanData = {\n logger: Logger<true>; // Braintrust logger (for root spans)\n spans: Map<string, Span>; // Maps span.id to Braintrust span\n};\n\n// Default span type for all spans\nconst DEFAULT_SPAN_TYPE = 'task';\n\n// Exceptions to the default mapping\nconst SPAN_TYPE_EXCEPTIONS: Partial<Record<AISpanType, string>> = {\n [AISpanType.LLM_GENERATION]: 'llm',\n [AISpanType.LLM_CHUNK]: 'llm',\n [AISpanType.TOOL_CALL]: 'tool',\n [AISpanType.MCP_TOOL_CALL]: 'tool',\n [AISpanType.WORKFLOW_CONDITIONAL_EVAL]: 'function',\n [AISpanType.WORKFLOW_WAIT_EVENT]: 'function',\n};\n\n// Mapping function - returns valid Braintrust span types\nfunction mapSpanType(spanType: AISpanType): 'llm' | 'score' | 'function' | 'eval' | 'task' | 'tool' {\n return (SPAN_TYPE_EXCEPTIONS[spanType] as any) ?? DEFAULT_SPAN_TYPE;\n}\n\nexport class BraintrustExporter implements AITracingExporter {\n name = 'braintrust';\n private traceMap = new Map<string, SpanData>();\n private logger: ConsoleLogger;\n private config: BraintrustExporterConfig;\n\n constructor(config: BraintrustExporterConfig) {\n this.logger = new ConsoleLogger({ level: config.logLevel ?? 'warn' });\n\n if (!config.apiKey) {\n this.logger.error('BraintrustExporter: Missing required credentials, exporter will be disabled', {\n hasApiKey: !!config.apiKey,\n });\n this.config = null as any;\n return;\n }\n\n this.config = config;\n }\n\n async exportEvent(event: AITracingEvent): Promise<void> {\n if (!this.config) {\n return;\n }\n\n if (event.exportedSpan.isEvent) {\n await this.handleEventSpan(event.exportedSpan);\n return;\n }\n\n switch (event.type) {\n case 'span_started':\n await this.handleSpanStarted(event.exportedSpan);\n break;\n case 'span_updated':\n await this.handleSpanUpdateOrEnd(event.exportedSpan, false);\n break;\n case 'span_ended':\n await this.handleSpanUpdateOrEnd(event.exportedSpan, true);\n break;\n }\n }\n\n private async handleSpanStarted(span: AnyExportedAISpan): Promise<void> {\n if (span.isRootSpan) {\n await this.initLogger(span);\n }\n\n const method = 'handleSpanStarted';\n const spanData = this.getSpanData({ span, method });\n if (!spanData) {\n return;\n }\n\n const braintrustParent = this.getBraintrustParent({ spanData, span, method });\n if (!braintrustParent) {\n return;\n }\n\n const payload = this.buildSpanPayload(span);\n\n const braintrustSpan = braintrustParent.startSpan({\n name: span.name,\n type: mapSpanType(span.type),\n ...payload,\n });\n\n spanData.spans.set(span.id, braintrustSpan);\n }\n\n private async handleSpanUpdateOrEnd(span: AnyExportedAISpan, isEnd: boolean): Promise<void> {\n const method = isEnd ? 'handleSpanEnd' : 'handleSpanUpdate';\n\n const spanData = this.getSpanData({ span, method });\n if (!spanData) {\n return;\n }\n\n const braintrustSpan = spanData.spans.get(span.id);\n if (!braintrustSpan) {\n this.logger.warn('Braintrust exporter: No Braintrust span found for span update/end', {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n spanType: span.type,\n isRootSpan: span.isRootSpan,\n parentSpanId: span.parentSpanId,\n method,\n });\n return;\n }\n\n braintrustSpan.log(this.buildSpanPayload(span));\n\n if (isEnd) {\n // End the span with the correct endTime (convert milliseconds to seconds)\n if (span.endTime) {\n braintrustSpan.end({ endTime: span.endTime.getTime() / 1000 });\n } else {\n braintrustSpan.end();\n }\n\n if (span.isRootSpan) {\n this.traceMap.delete(span.traceId);\n }\n }\n }\n\n private async handleEventSpan(span: AnyExportedAISpan): Promise<void> {\n if (span.isRootSpan) {\n this.logger.debug('Braintrust exporter: Creating logger for event', {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n method: 'handleEventSpan',\n });\n await this.initLogger(span);\n }\n\n const method = 'handleEventSpan';\n const spanData = this.getSpanData({ span, method });\n if (!spanData) {\n return;\n }\n\n const braintrustParent = this.getBraintrustParent({ spanData, span, method });\n if (!braintrustParent) {\n return;\n }\n\n const payload = this.buildSpanPayload(span);\n\n // Create zero-duration span for event (convert milliseconds to seconds)\n const braintrustSpan = braintrustParent.startSpan({\n name: span.name,\n type: mapSpanType(span.type),\n startTime: span.startTime.getTime() / 1000,\n ...payload,\n });\n\n braintrustSpan.end({ endTime: span.startTime.getTime() / 1000 });\n spanData.spans.set(span.id, braintrustSpan);\n }\n\n private async initLogger(span: AnyExportedAISpan): Promise<void> {\n const logger = await initLogger({\n projectName: this.config.projectName ?? 'mastra-tracing',\n apiKey: this.config.apiKey,\n appUrl: this.config.endpoint,\n ...this.config.tuningParameters,\n });\n\n this.traceMap.set(span.traceId, { logger, spans: new Map() });\n }\n\n private getSpanData(options: { span: AnyExportedAISpan; method: string }): SpanData | undefined {\n const { span, method } = options;\n if (this.traceMap.has(span.traceId)) {\n return this.traceMap.get(span.traceId);\n }\n\n this.logger.warn('Braintrust exporter: No span data found for span', {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n spanType: span.type,\n isRootSpan: span.isRootSpan,\n parentSpanId: span.parentSpanId,\n method,\n });\n }\n\n private getBraintrustParent(options: {\n spanData: SpanData;\n span: AnyExportedAISpan;\n method: string;\n }): Logger<true> | Span | undefined {\n const { spanData, span, method } = options;\n\n const parentId = span.parentSpanId;\n if (!parentId) {\n return spanData.logger;\n }\n\n if (spanData.spans.has(parentId)) {\n return spanData.spans.get(parentId);\n }\n\n this.logger.warn('Braintrust exporter: No parent data found for span', {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n spanType: span.type,\n isRootSpan: span.isRootSpan,\n parentSpanId: span.parentSpanId,\n method,\n });\n }\n\n private buildSpanPayload(span: AnyExportedAISpan): Record<string, any> {\n const payload: Record<string, any> = {};\n\n // Core span data\n if (span.input !== undefined) {\n payload.input = span.input;\n }\n\n if (span.output !== undefined) {\n payload.output = span.output;\n }\n\n // Initialize metrics and metadata objects\n payload.metrics = {};\n payload.metadata = {\n spanType: span.type,\n ...span.metadata,\n };\n\n const attributes = (span.attributes ?? {}) as Record<string, any>;\n\n if (span.type === AISpanType.LLM_GENERATION) {\n const llmAttr = attributes as LLMGenerationAttributes;\n\n // Model goes to metadata\n if (llmAttr.model !== undefined) {\n payload.metadata.model = llmAttr.model;\n }\n\n // Provider goes to metadata (if provided by attributes)\n if (llmAttr.provider !== undefined) {\n payload.metadata.provider = llmAttr.provider;\n }\n\n // Usage/token info goes to metrics\n payload.metrics = normalizeUsageMetrics(llmAttr);\n\n // Model parameters go to metadata\n if (llmAttr.parameters !== undefined) {\n payload.metadata.modelParameters = llmAttr.parameters;\n }\n\n // Other LLM attributes go to metadata\n const otherAttributes = omitKeys(attributes, ['model', 'usage', 'parameters']);\n payload.metadata = {\n ...payload.metadata,\n ...otherAttributes,\n };\n } else {\n // For non-LLM spans, put all attributes in metadata\n payload.metadata = {\n ...payload.metadata,\n ...attributes,\n };\n }\n\n // Handle errors\n if (span.errorInfo) {\n payload.error = span.errorInfo.message;\n payload.metadata.errorDetails = span.errorInfo;\n }\n\n // Clean up empty metrics object\n if (Object.keys(payload.metrics).length === 0) {\n delete payload.metrics;\n }\n\n return payload;\n }\n\n async shutdown(): Promise<void> {\n if (!this.config) {\n return;\n }\n\n // End all active spans\n for (const [_traceId, spanData] of this.traceMap) {\n for (const [_spanId, span] of spanData.spans) {\n span.end();\n }\n // Loggers don't have an explicit shutdown method\n }\n this.traceMap.clear();\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/metrics.ts","../src/tracing.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ModelGenerationAttributes } from '@mastra/core/observability';\n/**\n * BraintrustUsageMetrics\n *\n * Canonical metric keys expected by Braintrust for LLM usage accounting.\n * These map various provider/SDK-specific usage fields to a common schema.\n * - prompt_tokens: input-side tokens (aka inputTokens/promptTokens)\n * - completion_tokens: output-side tokens (aka outputTokens/completionTokens)\n * - tokens: total tokens (provided or derived)\n * - completion_reasoning_tokens: reasoning tokens, when available\n * - prompt_cached_tokens: tokens served from cache (provider-specific)\n * - prompt_cache_creation_tokens: tokens used to create cache (provider-specific)\n * - time_to_first_token: timestamp (ms since epoch) when first token arrived (streaming only)\n */\nexport interface BraintrustUsageMetrics {\n prompt_tokens?: number;\n completion_tokens?: number;\n tokens?: number;\n completion_reasoning_tokens?: number;\n prompt_cached_tokens?: number;\n prompt_cache_creation_tokens?: number;\n time_to_first_token?: number;\n [key: string]: number | undefined;\n}\n\nexport function normalizeUsageMetrics(modelAttr: ModelGenerationAttributes): BraintrustUsageMetrics {\n const metrics: BraintrustUsageMetrics = {};\n\n if (modelAttr.usage?.inputTokens !== undefined) {\n metrics.prompt_tokens = modelAttr.usage?.inputTokens;\n } else if (modelAttr.usage?.promptTokens !== undefined) {\n metrics.prompt_tokens = modelAttr.usage?.promptTokens;\n }\n\n if (modelAttr.usage?.outputTokens !== undefined) {\n metrics.completion_tokens = modelAttr.usage?.outputTokens;\n } else if (modelAttr.usage?.completionTokens !== undefined) {\n metrics.completion_tokens = modelAttr.usage?.completionTokens;\n }\n\n if (modelAttr.usage?.totalTokens !== undefined) {\n metrics.tokens = modelAttr.usage?.totalTokens;\n }\n if (modelAttr.usage?.reasoningTokens !== undefined) {\n metrics.completion_reasoning_tokens = modelAttr.usage?.reasoningTokens;\n }\n if (modelAttr.usage?.promptCacheHitTokens !== undefined) {\n metrics.prompt_cached_tokens = modelAttr.usage?.promptCacheHitTokens;\n }\n if (modelAttr.usage?.promptCacheMissTokens !== undefined) {\n metrics.prompt_cache_creation_tokens = modelAttr.usage?.promptCacheMissTokens;\n }\n\n // Time to first token (TTFT) for streaming responses\n if (modelAttr.completionStartTime) {\n // Handle both Date objects and already-converted timestamps (number/string)\n const startTime = modelAttr.completionStartTime;\n if (startTime instanceof Date) {\n metrics.time_to_first_token = startTime.getTime();\n } else if (typeof startTime === 'number') {\n metrics.time_to_first_token = startTime;\n } else if (typeof startTime === 'string') {\n metrics.time_to_first_token = new Date(startTime).getTime();\n }\n }\n\n return metrics;\n}\n","/**\n * Braintrust Exporter for Mastra Observability\n *\n * This exporter sends observability data to Braintrust.\n * Root spans become top-level Braintrust spans (no trace wrapper).\n * Events are handled as zero-duration spans with matching start/end times.\n */\n\nimport type { TracingEvent, AnyExportedSpan, ModelGenerationAttributes } from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport { omitKeys } from '@mastra/core/utils';\nimport { BaseExporter } from '@mastra/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport { initLogger, currentSpan } from 'braintrust';\nimport type { Span, Logger } from 'braintrust';\nimport { normalizeUsageMetrics } from './metrics';\n\nconst MASTRA_TRACE_ID_METADATA_KEY = 'mastra-trace-id';\n\nexport interface BraintrustExporterConfig extends BaseExporterConfig {\n /**\n * Optional Braintrust logger instance.\n * When provided, enables integration with Braintrust contexts such as:\n * - Evals: Agent traces nest inside eval task spans\n * - logger.traced(): Agent traces nest inside traced spans\n * - Parent spans: Auto-detects and attaches to external Braintrust spans\n */\n braintrustLogger?: Logger<true>;\n\n /** Braintrust API key. Required if logger is not provided. */\n apiKey?: string;\n /** Optional custom endpoint */\n endpoint?: string;\n /** Braintrust project name (default: 'mastra-tracing') */\n projectName?: string;\n /** Support tuning parameters */\n tuningParameters?: Record<string, any>;\n}\n\ntype SpanData = {\n logger: Logger<true> | Span; // Braintrust logger (for root spans) or external span\n spans: Map<string, Span>; // Maps span.id to Braintrust span\n activeIds: Set<string>; // Tracks started (non-event) spans not yet ended, including root\n isExternal: boolean; // True if logger is an external span from logger.traced() or Eval()\n};\n\n// Default span type for all spans\nconst DEFAULT_SPAN_TYPE = 'task';\n\n// Exceptions to the default mapping\nconst SPAN_TYPE_EXCEPTIONS: Partial<Record<SpanType, string>> = {\n [SpanType.MODEL_GENERATION]: 'llm',\n [SpanType.MODEL_CHUNK]: 'llm',\n [SpanType.TOOL_CALL]: 'tool',\n [SpanType.MCP_TOOL_CALL]: 'tool',\n [SpanType.WORKFLOW_CONDITIONAL_EVAL]: 'function',\n [SpanType.WORKFLOW_WAIT_EVENT]: 'function',\n};\n\n// Mapping function - returns valid Braintrust span types\nfunction mapSpanType(spanType: SpanType): 'llm' | 'score' | 'function' | 'eval' | 'task' | 'tool' {\n return (SPAN_TYPE_EXCEPTIONS[spanType] as any) ?? DEFAULT_SPAN_TYPE;\n}\n\nexport class BraintrustExporter extends BaseExporter {\n name = 'braintrust';\n private traceMap = new Map<string, SpanData>();\n private config: BraintrustExporterConfig;\n\n // Flags and logger for context-aware mode\n private useProvidedLogger: boolean;\n private providedLogger?: Logger<true>;\n\n constructor(config: BraintrustExporterConfig) {\n super(config);\n\n if (config.braintrustLogger) {\n // Use provided logger - enables Braintrust context integration\n this.useProvidedLogger = true;\n this.providedLogger = config.braintrustLogger;\n this.config = config;\n } else {\n // Validate apiKey for creating loggers per trace\n if (!config.apiKey) {\n this.setDisabled(`Missing required credentials (apiKey: ${!!config.apiKey})`);\n this.config = null as any;\n this.useProvidedLogger = false;\n return;\n }\n this.useProvidedLogger = false;\n this.config = config;\n }\n }\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (event.exportedSpan.isEvent) {\n await this.handleEventSpan(event.exportedSpan);\n return;\n }\n\n switch (event.type) {\n case 'span_started':\n await this.handleSpanStarted(event.exportedSpan);\n break;\n case 'span_updated':\n await this.handleSpanUpdateOrEnd(event.exportedSpan, false);\n break;\n case 'span_ended':\n await this.handleSpanUpdateOrEnd(event.exportedSpan, true);\n break;\n }\n }\n\n private async handleSpanStarted(span: AnyExportedSpan): Promise<void> {\n if (span.isRootSpan) {\n if (this.useProvidedLogger) {\n // Use provided logger, detect external Braintrust spans\n await this.initLoggerOrUseContext(span);\n } else {\n // Create new logger per trace\n await this.initLoggerPerTrace(span);\n }\n }\n\n const method = 'handleSpanStarted';\n const spanData = this.getSpanData({ span, method });\n if (!spanData) {\n return;\n }\n\n // Refcount: track active non-event spans (including root)\n if (!span.isEvent) {\n spanData.activeIds.add(span.id);\n }\n\n const braintrustParent = this.getBraintrustParent({ spanData, span, method });\n if (!braintrustParent) {\n return;\n }\n\n const payload = this.buildSpanPayload(span);\n\n const braintrustSpan = braintrustParent.startSpan({\n spanId: span.id,\n name: span.name,\n type: mapSpanType(span.type),\n ...payload,\n });\n\n // Include the Mastra trace ID in the span metadata for correlation\n // Also include tags if present (only for root spans)\n braintrustSpan.log({\n metadata: {\n [MASTRA_TRACE_ID_METADATA_KEY]: span.traceId,\n },\n ...(span.isRootSpan && span.tags?.length ? { tags: span.tags } : {}),\n });\n\n spanData.spans.set(span.id, braintrustSpan);\n }\n\n private async handleSpanUpdateOrEnd(span: AnyExportedSpan, isEnd: boolean): Promise<void> {\n const method = isEnd ? 'handleSpanEnd' : 'handleSpanUpdate';\n\n const spanData = this.getSpanData({ span, method });\n if (!spanData) {\n return;\n }\n\n const braintrustSpan = spanData.spans.get(span.id);\n if (!braintrustSpan) {\n this.logger.warn('Braintrust exporter: No Braintrust span found for span update/end', {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n spanType: span.type,\n isRootSpan: span.isRootSpan,\n parentSpanId: span.parentSpanId,\n method,\n });\n return;\n }\n\n braintrustSpan.log(this.buildSpanPayload(span));\n\n if (isEnd) {\n // End the span with the correct endTime (convert milliseconds to seconds)\n if (span.endTime) {\n braintrustSpan.end({ endTime: span.endTime.getTime() / 1000 });\n } else {\n braintrustSpan.end();\n }\n\n // Refcount: mark this span as ended\n if (!span.isEvent) {\n spanData.activeIds.delete(span.id);\n }\n\n // If no more active spans remain for this trace, clean up the trace entry\n // Don't clean up if using external spans (they're managed by Braintrust)\n if (spanData.activeIds.size === 0 && !spanData.isExternal) {\n this.traceMap.delete(span.traceId);\n }\n }\n }\n\n private async handleEventSpan(span: AnyExportedSpan): Promise<void> {\n if (span.isRootSpan) {\n this.logger.debug('Braintrust exporter: Creating logger for event', {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n method: 'handleEventSpan',\n });\n\n if (this.useProvidedLogger) {\n // Use provided logger, detect external Braintrust spans\n await this.initLoggerOrUseContext(span);\n } else {\n // Create new logger per trace\n await this.initLoggerPerTrace(span);\n }\n }\n\n const method = 'handleEventSpan';\n const spanData = this.getSpanData({ span, method });\n if (!spanData) {\n return;\n }\n\n const braintrustParent = this.getBraintrustParent({ spanData, span, method });\n if (!braintrustParent) {\n return;\n }\n\n const payload = this.buildSpanPayload(span);\n\n // Create zero-duration span for event (convert milliseconds to seconds)\n const braintrustSpan = braintrustParent.startSpan({\n spanId: span.id,\n name: span.name,\n type: mapSpanType(span.type),\n startTime: span.startTime.getTime() / 1000,\n ...payload,\n });\n\n braintrustSpan.end({ endTime: span.startTime.getTime() / 1000 });\n }\n\n private initTraceMap(params: { traceId: string; isExternal: boolean; logger: Logger<true> | Span }): void {\n const { traceId, isExternal, logger } = params;\n\n // Check if trace already exists - reuse existing trace data\n if (this.traceMap.has(traceId)) {\n this.logger.debug('Braintrust exporter: Reusing existing trace from local map', { traceId });\n return;\n }\n\n this.traceMap.set(traceId, {\n logger,\n spans: new Map(),\n activeIds: new Set(),\n isExternal,\n });\n }\n\n /**\n * Creates a new logger per trace using config credentials\n */\n private async initLoggerPerTrace(span: AnyExportedSpan): Promise<void> {\n // Check if trace already exists - reuse existing trace data\n if (this.traceMap.has(span.traceId)) {\n this.logger.debug('Braintrust exporter: Reusing existing trace from local map', { traceId: span.traceId });\n return;\n }\n\n const logger = await initLogger({\n projectName: this.config.projectName ?? 'mastra-tracing',\n apiKey: this.config.apiKey,\n appUrl: this.config.endpoint,\n ...this.config.tuningParameters,\n });\n\n this.initTraceMap({ logger, isExternal: false, traceId: span.traceId });\n }\n\n /**\n * Uses provided logger and detects external Braintrust spans.\n * If a Braintrust span is detected (from logger.traced() or Eval()), attaches to it.\n * Otherwise, uses the provided logger instance.\n */\n private async initLoggerOrUseContext(span: AnyExportedSpan): Promise<void> {\n // Check if trace already exists - reuse existing trace data\n if (this.traceMap.has(span.traceId)) {\n this.logger.debug('Braintrust exporter: Reusing existing trace from local map', { traceId: span.traceId });\n return;\n }\n\n // Try to find a Braintrust span to attach to:\n // 1. Auto-detect from Braintrust's current span (logger.traced(), Eval(), etc.)\n // 2. Fall back to the configured logger\n const braintrustSpan = currentSpan();\n\n // Check if it's a valid span (not the NOOP_SPAN)\n if (braintrustSpan && braintrustSpan.id) {\n // External span detected - attach Mastra traces to it\n this.initTraceMap({ logger: braintrustSpan, isExternal: true, traceId: span.traceId });\n } else {\n // No external span - use provided logger\n this.initTraceMap({ logger: this.providedLogger!, isExternal: false, traceId: span.traceId });\n }\n }\n\n private getSpanData(options: { span: AnyExportedSpan; method: string }): SpanData | undefined {\n const { span, method } = options;\n if (this.traceMap.has(span.traceId)) {\n return this.traceMap.get(span.traceId);\n }\n\n this.logger.warn('Braintrust exporter: No span data found for span', {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n spanType: span.type,\n isRootSpan: span.isRootSpan,\n parentSpanId: span.parentSpanId,\n method,\n });\n }\n\n private getBraintrustParent(options: {\n spanData: SpanData;\n span: AnyExportedSpan;\n method: string;\n }): Logger<true> | Span | undefined {\n const { spanData, span, method } = options;\n\n const parentId = span.parentSpanId;\n if (!parentId) {\n return spanData.logger;\n }\n\n if (spanData.spans.has(parentId)) {\n return spanData.spans.get(parentId);\n }\n\n // If the parent exists but is the root span (not represented as a Braintrust\n // span because we use the logger as the root), attach to the logger so the\n // span is not orphaned. We need to check if parentSpanId exists but the\n // parent span is not in our spans map (indicating it's the root span).\n if (parentId && !spanData.spans.has(parentId)) {\n // This means the parent exists but isn't tracked as a Braintrust span,\n // which happens when the parent is the root span (we use logger as root)\n return spanData.logger;\n }\n\n this.logger.warn('Braintrust exporter: No parent data found for span', {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n spanType: span.type,\n isRootSpan: span.isRootSpan,\n parentSpanId: span.parentSpanId,\n method,\n });\n }\n\n /**\n * Transforms MODEL_GENERATION input to Braintrust Thread view format.\n */\n private transformInput(input: any, spanType: SpanType): any {\n if (spanType === SpanType.MODEL_GENERATION) {\n if (input && Array.isArray(input.messages)) {\n return input.messages;\n } else if (input && typeof input === 'object' && 'content' in input) {\n return [{ role: input.role, content: input.content }];\n }\n }\n\n return input;\n }\n\n /**\n * Transforms MODEL_GENERATION output to Braintrust Thread view format.\n */\n private transformOutput(output: any, spanType: SpanType): any {\n if (spanType === SpanType.MODEL_GENERATION) {\n const { text, ...rest } = output;\n return { role: 'assistant', content: text, ...rest };\n }\n\n return output;\n }\n\n private buildSpanPayload(span: AnyExportedSpan): Record<string, any> {\n const payload: Record<string, any> = {};\n\n if (span.input !== undefined) {\n payload.input = this.transformInput(span.input, span.type);\n }\n\n if (span.output !== undefined) {\n payload.output = this.transformOutput(span.output, span.type);\n }\n\n // Initialize metrics and metadata objects\n payload.metrics = {};\n payload.metadata = {\n spanType: span.type,\n ...span.metadata,\n };\n\n const attributes = (span.attributes ?? {}) as Record<string, any>;\n\n if (span.type === SpanType.MODEL_GENERATION) {\n const modelAttr = attributes as ModelGenerationAttributes;\n\n // Model goes to metadata\n if (modelAttr.model !== undefined) {\n payload.metadata.model = modelAttr.model;\n }\n\n // Provider goes to metadata (if provided by attributes)\n if (modelAttr.provider !== undefined) {\n payload.metadata.provider = modelAttr.provider;\n }\n\n // Usage/token info goes to metrics\n payload.metrics = normalizeUsageMetrics(modelAttr);\n\n // Model parameters go to metadata\n if (modelAttr.parameters !== undefined) {\n payload.metadata.modelParameters = modelAttr.parameters;\n }\n\n // Other LLM attributes go to metadata\n const otherAttributes = omitKeys(attributes, ['model', 'usage', 'parameters']);\n payload.metadata = {\n ...payload.metadata,\n ...otherAttributes,\n };\n } else {\n // For non-LLM spans, put all attributes in metadata\n payload.metadata = {\n ...payload.metadata,\n ...attributes,\n };\n }\n\n // Handle errors\n if (span.errorInfo) {\n payload.error = span.errorInfo.message;\n payload.metadata.errorDetails = span.errorInfo;\n }\n\n // Clean up empty metrics object\n if (Object.keys(payload.metrics).length === 0) {\n delete payload.metrics;\n }\n\n return payload;\n }\n\n async shutdown(): Promise<void> {\n if (!this.config) {\n return;\n }\n\n // End all active spans\n for (const [_traceId, spanData] of this.traceMap) {\n for (const [_spanId, span] of spanData.spans) {\n span.end();\n }\n // Loggers don't have an explicit shutdown method\n }\n this.traceMap.clear();\n await super.shutdown();\n }\n}\n"]}
package/dist/metrics.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { LLMGenerationAttributes } from '@mastra/core/ai-tracing';
1
+ import type { ModelGenerationAttributes } from '@mastra/core/observability';
2
2
  /**
3
3
  * BraintrustUsageMetrics
4
4
  *
@@ -10,6 +10,7 @@ import type { LLMGenerationAttributes } from '@mastra/core/ai-tracing';
10
10
  * - completion_reasoning_tokens: reasoning tokens, when available
11
11
  * - prompt_cached_tokens: tokens served from cache (provider-specific)
12
12
  * - prompt_cache_creation_tokens: tokens used to create cache (provider-specific)
13
+ * - time_to_first_token: timestamp (ms since epoch) when first token arrived (streaming only)
13
14
  */
14
15
  export interface BraintrustUsageMetrics {
15
16
  prompt_tokens?: number;
@@ -18,7 +19,8 @@ export interface BraintrustUsageMetrics {
18
19
  completion_reasoning_tokens?: number;
19
20
  prompt_cached_tokens?: number;
20
21
  prompt_cache_creation_tokens?: number;
22
+ time_to_first_token?: number;
21
23
  [key: string]: number | undefined;
22
24
  }
23
- export declare function normalizeUsageMetrics(llmAttr: LLMGenerationAttributes): BraintrustUsageMetrics;
25
+ export declare function normalizeUsageMetrics(modelAttr: ModelGenerationAttributes): BraintrustUsageMetrics;
24
26
  //# sourceMappingURL=metrics.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CAoB9F"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,yBAAyB,GAAG,sBAAsB,CA0ClG"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Braintrust Exporter for Mastra Observability
3
+ *
4
+ * This exporter sends observability data to Braintrust.
5
+ * Root spans become top-level Braintrust spans (no trace wrapper).
6
+ * Events are handled as zero-duration spans with matching start/end times.
7
+ */
8
+ import type { TracingEvent } from '@mastra/core/observability';
9
+ import { BaseExporter } from '@mastra/observability';
10
+ import type { BaseExporterConfig } from '@mastra/observability';
11
+ import type { Logger } from 'braintrust';
12
+ export interface BraintrustExporterConfig extends BaseExporterConfig {
13
+ /**
14
+ * Optional Braintrust logger instance.
15
+ * When provided, enables integration with Braintrust contexts such as:
16
+ * - Evals: Agent traces nest inside eval task spans
17
+ * - logger.traced(): Agent traces nest inside traced spans
18
+ * - Parent spans: Auto-detects and attaches to external Braintrust spans
19
+ */
20
+ braintrustLogger?: Logger<true>;
21
+ /** Braintrust API key. Required if logger is not provided. */
22
+ apiKey?: string;
23
+ /** Optional custom endpoint */
24
+ endpoint?: string;
25
+ /** Braintrust project name (default: 'mastra-tracing') */
26
+ projectName?: string;
27
+ /** Support tuning parameters */
28
+ tuningParameters?: Record<string, any>;
29
+ }
30
+ export declare class BraintrustExporter extends BaseExporter {
31
+ name: string;
32
+ private traceMap;
33
+ private config;
34
+ private useProvidedLogger;
35
+ private providedLogger?;
36
+ constructor(config: BraintrustExporterConfig);
37
+ protected _exportTracingEvent(event: TracingEvent): Promise<void>;
38
+ private handleSpanStarted;
39
+ private handleSpanUpdateOrEnd;
40
+ private handleEventSpan;
41
+ private initTraceMap;
42
+ /**
43
+ * Creates a new logger per trace using config credentials
44
+ */
45
+ private initLoggerPerTrace;
46
+ /**
47
+ * Uses provided logger and detects external Braintrust spans.
48
+ * If a Braintrust span is detected (from logger.traced() or Eval()), attaches to it.
49
+ * Otherwise, uses the provided logger instance.
50
+ */
51
+ private initLoggerOrUseContext;
52
+ private getSpanData;
53
+ private getBraintrustParent;
54
+ /**
55
+ * Transforms MODEL_GENERATION input to Braintrust Thread view format.
56
+ */
57
+ private transformInput;
58
+ /**
59
+ * Transforms MODEL_GENERATION output to Braintrust Thread view format.
60
+ */
61
+ private transformOutput;
62
+ private buildSpanPayload;
63
+ shutdown(): Promise<void>;
64
+ }
65
+ //# sourceMappingURL=tracing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAA8C,MAAM,4BAA4B,CAAC;AAG3G,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,KAAK,EAAQ,MAAM,EAAE,MAAM,YAAY,CAAC;AAK/C,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB;IAClE;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAEhC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gCAAgC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACxC;AA2BD,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,IAAI,SAAgB;IACpB,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,MAAM,CAA2B;IAGzC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,cAAc,CAAC,CAAe;gBAE1B,MAAM,EAAE,wBAAwB;cAqB5B,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;YAmBzD,iBAAiB;YAgDjB,qBAAqB;YA6CrB,eAAe;IA2C7B,OAAO,CAAC,YAAY;IAiBpB;;OAEG;YACW,kBAAkB;IAiBhC;;;;OAIG;YACW,sBAAsB;IAsBpC,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,mBAAmB;IAqC3B;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,gBAAgB;IAqElB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAehC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mastra/braintrust",
3
- "version": "0.0.0-scorers-ui-refactored-20250916094952",
4
- "description": "Braintrust observability provider for Mastra - includes AI tracing and future observability features",
3
+ "version": "0.0.0-scorers-logs-20251208093427",
4
+ "description": "Braintrust observability provider for Mastra - includes tracing and future observability features",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -24,21 +24,24 @@
24
24
  },
25
25
  "license": "Apache-2.0",
26
26
  "dependencies": {
27
- "braintrust": "^0.3.6"
27
+ "braintrust": "^0.4.9",
28
+ "@mastra/observability": "0.0.0-scorers-logs-20251208093427"
28
29
  },
29
30
  "devDependencies": {
30
31
  "@microsoft/api-extractor": "^7.52.8",
31
- "@types/node": "^20.19.0",
32
- "eslint": "^9.30.1",
32
+ "@types/node": "22.13.17",
33
+ "@vitest/coverage-v8": "4.0.12",
34
+ "@vitest/ui": "4.0.12",
35
+ "eslint": "^9.37.0",
33
36
  "tsup": "^8.5.0",
34
37
  "typescript": "^5.8.3",
35
- "vitest": "^3.2.4",
36
- "@internal/lint": "0.0.0-scorers-ui-refactored-20250916094952",
37
- "@internal/types-builder": "0.0.0-scorers-ui-refactored-20250916094952",
38
- "@mastra/core": "0.0.0-scorers-ui-refactored-20250916094952"
38
+ "vitest": "4.0.12",
39
+ "@internal/lint": "0.0.0-scorers-logs-20251208093427",
40
+ "@internal/types-builder": "0.0.0-scorers-logs-20251208093427",
41
+ "@mastra/core": "0.0.0-scorers-logs-20251208093427"
39
42
  },
40
43
  "peerDependencies": {
41
- "@mastra/core": "0.0.0-scorers-ui-refactored-20250916094952"
44
+ "@mastra/core": "0.0.0-scorers-logs-20251208093427"
42
45
  },
43
46
  "homepage": "https://mastra.ai",
44
47
  "repository": {
@@ -49,11 +52,17 @@
49
52
  "bugs": {
50
53
  "url": "https://github.com/mastra-ai/mastra/issues"
51
54
  },
55
+ "engines": {
56
+ "node": ">=22.13.0"
57
+ },
52
58
  "scripts": {
53
59
  "build": "tsup --silent --config tsup.config.ts",
54
60
  "build:watch": "pnpm build --watch",
55
61
  "test": "vitest run",
56
62
  "test:watch": "vitest watch",
57
- "lint": "eslint ."
63
+ "lint": "eslint .",
64
+ "example:basic": "tsx examples/basic.ts",
65
+ "example:traced": "tsx examples/with-logger-traced.ts",
66
+ "example:eval": "tsx examples/with-eval.ts"
58
67
  }
59
68
  }
@@ -1,37 +0,0 @@
1
- /**
2
- * Braintrust Exporter for Mastra AI Tracing
3
- *
4
- * This exporter sends tracing data to Braintrust for AI observability.
5
- * Root spans become top-level Braintrust spans (no trace wrapper).
6
- * Events are handled as zero-duration spans with matching start/end times.
7
- */
8
- import type { AITracingExporter, AITracingEvent } from '@mastra/core/ai-tracing';
9
- export interface BraintrustExporterConfig {
10
- /** Braintrust API key */
11
- apiKey?: string;
12
- /** Optional custom endpoint */
13
- endpoint?: string;
14
- /** Braintrust project name (default: 'mastra-tracing') */
15
- projectName?: string;
16
- /** Logger level for diagnostic messages (default: 'warn') */
17
- logLevel?: 'debug' | 'info' | 'warn' | 'error';
18
- /** Support tuning parameters */
19
- tuningParameters?: Record<string, any>;
20
- }
21
- export declare class BraintrustExporter implements AITracingExporter {
22
- name: string;
23
- private traceMap;
24
- private logger;
25
- private config;
26
- constructor(config: BraintrustExporterConfig);
27
- exportEvent(event: AITracingEvent): Promise<void>;
28
- private handleSpanStarted;
29
- private handleSpanUpdateOrEnd;
30
- private handleEventSpan;
31
- private initLogger;
32
- private getSpanData;
33
- private getBraintrustParent;
34
- private buildSpanPayload;
35
- shutdown(): Promise<void>;
36
- }
37
- //# sourceMappingURL=ai-tracing.d.ts.map