@mastra/sentry 1.2.25 → 1.2.26-alpha.1

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.cjs CHANGED
@@ -159,6 +159,14 @@ const ATTRIBUTE_KEYS = {
159
159
  GEN_AI_USAGE_CACHE_WRITE_TOKENS: "gen_ai.usage.cache_creation.input_tokens",
160
160
  GEN_AI_USAGE_REASONING_TOKENS: "gen_ai.usage.reasoning_tokens"
161
161
  };
162
+ /** Sentry span links for Mastra span links. Only full-length W3C IDs are kept. */
163
+ function toSentryLinks(links) {
164
+ return (links ?? []).filter((link) => /^[0-9a-f]{32}$/.test(link.traceId) && /^[0-9a-f]{16}$/.test(link.spanId)).map((link) => ({ context: {
165
+ traceId: link.traceId,
166
+ spanId: link.spanId,
167
+ traceFlags: 1
168
+ } }));
169
+ }
162
170
  var SentryExporter = class extends _mastra_observability.BaseExporter {
163
171
  name = "sentry";
164
172
  sentryConfig;
@@ -234,17 +242,20 @@ var SentryExporter = class extends _mastra_observability.BaseExporter {
234
242
  }
235
243
  async handleSpanStarted(span) {
236
244
  const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);
245
+ const links = toSentryLinks(span.links);
237
246
  const sentrySpan = _sentry_node.startInactiveSpan({
238
247
  op: this.getOperationType(span),
239
248
  name: (0, _mastra_otel_exporter.getSpanName)(span, this.genAIOptions(span)),
240
249
  startTime: span.startTime.getTime(),
241
250
  forceTransaction: span.isRootSpan,
242
- parentSpan: resolvedParentId ? this.spanMap.get(resolvedParentId)?.span : void 0
251
+ parentSpan: resolvedParentId ? this.spanMap.get(resolvedParentId)?.span : void 0,
252
+ ...links.length > 0 ? { links } : {}
243
253
  });
244
254
  sentrySpan.setAttributes(this.buildSpanAttributes(span));
245
255
  this.spanMap.set(span.id, {
246
256
  span: sentrySpan,
247
- spanType: span.type
257
+ spanType: span.type,
258
+ ...span.links?.length ? { startLinkKeys: new Set(span.links.map((link) => `${link.traceId}:${link.spanId}`)) } : {}
248
259
  });
249
260
  if ((span.type === _mastra_core_observability.SpanType.TOOL_CALL || span.type === _mastra_core_observability.SpanType.PROVIDER_TOOL_CALL) && resolvedParentId) this.trackToolCallForParent(span, resolvedParentId);
250
261
  }
@@ -302,6 +313,8 @@ var SentryExporter = class extends _mastra_observability.BaseExporter {
302
313
  }
303
314
  } });
304
315
  }
316
+ const lateLinks = toSentryLinks(span.links?.filter((link) => !spanData.startLinkKeys?.has(`${link.traceId}:${link.spanId}`)));
317
+ if (lateLinks.length > 0 && typeof sentrySpan.addLinks === "function") sentrySpan.addLinks(lateLinks);
305
318
  const endTime = span.endTime ? span.endTime.getTime() : void 0;
306
319
  sentrySpan.end(endTime);
307
320
  this.spanMap.delete(span.id);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["SpanType","BaseExporter","TracingEventType","Sentry"],"sources":["../src/tracing.ts"],"sourcesContent":["/**\n * Sentry Exporter for Mastra Observability\n *\n * Sends observability data to Sentry for AI tracing and monitoring.\n * Uses Sentry's modern span model (v8+) with OpenTelemetry semantic conventions.\n *\n * Spans are hierarchically organized: AGENT_RUN -> MODEL_GENERATION -> TOOL_CALL\n * MODEL_STEP and MODEL_CHUNK spans are skipped to simplify the trace hierarchy.\n */\n\nimport type {\n TracingEvent,\n AnyExportedSpan,\n ModelGenerationAttributes,\n ToolCallAttributes,\n AgentRunAttributes,\n WorkflowRunAttributes,\n WorkflowStepAttributes,\n UsageStats,\n} from '@mastra/core/observability';\nimport { SpanType, TracingEventType } from '@mastra/core/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport { BaseExporter } from '@mastra/observability';\nimport { getAttributes as getGenAIAttributes, getSpanName as getGenAISpanName } from '@mastra/otel-exporter';\nimport type { GenAISemanticsOptions } from '@mastra/otel-exporter';\nimport * as Sentry from '@sentry/node';\n\ntype SentrySpanOp = { opType: string; opName: string };\n\n/**\n * Builds the span-type map, dropping any entry whose span type does not exist\n * in the paired `@mastra/core`.\n *\n * The peer range admits a core older than the one that introduced a given\n * `SpanType` member, where `SpanType.X` is `undefined` at runtime. As a plain\n * object literal that lands in the map under a literal `\"undefined\"` key, which\n * then matches any span whose type is undefined and mislabels it.\n *\n * @internal Exported for tests.\n */\nexport function buildSpanTypeConfig(\n entries: Array<[SpanType | undefined, SentrySpanOp]>,\n): Partial<Record<SpanType, SentrySpanOp>> {\n return Object.fromEntries(\n entries.filter((entry): entry is [SpanType, SentrySpanOp] => entry[0] !== undefined),\n ) as Partial<Record<SpanType, SentrySpanOp>>;\n}\n\nconst SPAN_TYPE_CONFIG: Partial<Record<SpanType, SentrySpanOp>> = buildSpanTypeConfig([\n [SpanType.AGENT_RUN, { opType: 'gen_ai.invoke_agent', opName: 'invoke_agent' }],\n [SpanType.MODEL_GENERATION, { opType: 'gen_ai.chat', opName: 'chat' }],\n [SpanType.TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.MCP_TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.PROVIDER_TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.WORKFLOW_RUN, { opType: 'workflow.run', opName: 'workflow' }],\n [SpanType.WORKFLOW_STEP, { opType: 'workflow.step', opName: 'step' }],\n [SpanType.WORKFLOW_CONDITIONAL, { opType: 'workflow.conditional', opName: 'step' }],\n [SpanType.WORKFLOW_CONDITIONAL_EVAL, { opType: 'workflow.conditional', opName: 'step' }],\n [SpanType.WORKFLOW_PARALLEL, { opType: 'workflow.parallel', opName: 'step' }],\n [SpanType.WORKFLOW_LOOP, { opType: 'workflow.loop', opName: 'step' }],\n [SpanType.WORKFLOW_SLEEP, { opType: 'workflow.sleep', opName: 'step' }],\n [SpanType.WORKFLOW_WAIT_EVENT, { opType: 'workflow.wait', opName: 'step' }],\n [SpanType.PROCESSOR_RUN, { opType: 'ai.processor', opName: 'step' }],\n [SpanType.GENERIC, { opType: 'ai.span', opName: 'span' }],\n [SpanType.MODEL_STEP, { opType: 'ai.span', opName: 'step' }],\n [SpanType.MODEL_CHUNK, { opType: 'ai.span', opName: 'step' }],\n [SpanType.SCORER_RUN, { opType: 'workflow.run', opName: 'eval' }],\n [SpanType.SCORER_STEP, { opType: 'workflow.step', opName: 'step' }],\n [SpanType.MEMORY_OPERATION, { opType: 'ai.memory', opName: 'memory' }],\n // Skill and workspace spans come from two places: the tools the model calls,\n // and the processors Mastra derives from agent config. A processor-flavoured\n // op would mislabel the tool calls, so both map to their subsystem the way\n // MEMORY_OPERATION already does. Without an entry they fall back to the\n // catch-all 'ai.span'.\n //\n // Both arrived after this package's oldest supported core, so against an\n // older one they read as `undefined`. `buildSpanTypeConfig` drops those\n // entries rather than keying the map under an `undefined` member.\n [SpanType.WORKSPACE_ACTION, { opType: 'ai.workspace', opName: 'workspace' }],\n [SpanType.SKILL_ACTION, { opType: 'ai.skill', opName: 'skill' }],\n]);\n\nconst ATTRIBUTE_KEYS = {\n SPAN_TYPE: 'ai.span.type',\n ORIGIN: 'sentry.origin',\n TAGS: 'tags',\n INPUT: 'input',\n OUTPUT: 'output',\n GEN_AI_REQUEST_STREAM: 'gen_ai.request.stream',\n GEN_AI_RESPONSE_MODEL: 'gen_ai.response.model',\n GEN_AI_RESPONSE_STREAMING: 'gen_ai.response.streaming',\n GEN_AI_RESPONSE_TOOL_CALLS: 'gen_ai.response.tool_calls',\n GEN_AI_RESPONSE_TEXT: 'gen_ai.response.text',\n GEN_AI_CONVERSATION_ID: 'gen_ai.conversation.id',\n GEN_AI_COMPLETION_START_TIME: 'gen_ai.completion_start_time',\n GEN_AI_TOOL_CALL_ID: 'gen_ai.tool.call.id',\n TOOL_SUCCESS: 'tool.success',\n GEN_AI_PIPELINE_NAME: 'gen_ai.pipeline.name',\n GEN_AI_AGENT_PROMPT: 'gen_ai.agent.prompt',\n WORKFLOW_ID: 'workflow.id',\n WORKFLOW_STATUS: 'workflow.status',\n WORKFLOW_STEP_ID: 'workflow.step.id',\n WORKFLOW_STEP_STATUS: 'workflow.step.status',\n GEN_AI_USAGE_INPUT_TOKENS: 'gen_ai.usage.input_tokens',\n GEN_AI_USAGE_OUTPUT_TOKENS: 'gen_ai.usage.output_tokens',\n GEN_AI_USAGE_TOTAL_TOKENS: 'gen_ai.usage.total_tokens',\n GEN_AI_USAGE_CACHE_READ_TOKENS: 'gen_ai.usage.cache_read.input_tokens',\n GEN_AI_USAGE_CACHE_WRITE_TOKENS: 'gen_ai.usage.cache_creation.input_tokens',\n GEN_AI_USAGE_REASONING_TOKENS: 'gen_ai.usage.reasoning_tokens',\n} as const;\n\nexport interface SentryExporterConfig extends BaseExporterConfig {\n // Sentry SDK options (passed to Sentry.init())\n /** Data Source Name - tells the SDK where to send events */\n dsn?: string;\n /** Deployment environment (enables filtering issues and alerts by environment) */\n environment?: string;\n /** Percentage of transactions sent to Sentry (0.0 = 0%, 1.0 = 100%) */\n tracesSampleRate?: number;\n /** Version of your code deployed (helps identify regressions and track deployments) */\n release?: string;\n /** Additional Sentry SDK options (integrations, beforeSend, etc.) */\n options?: Partial<Sentry.NodeOptions>;\n}\n\n/**\n * Internal span tracking data.\n * generation tracks the single MODEL_GENERATION for AGENT_RUN response attributes.\n * toolCalls tracks child tool calls for MODEL_GENERATION spans.\n */\ntype SpanData = {\n span: Sentry.Span;\n spanType: SpanType;\n generation?: {\n model?: string;\n output?: any;\n usage?: UsageStats;\n };\n toolCalls?: Array<{\n name: string;\n id?: string;\n type?: string;\n }>;\n};\n\n/** Config type with Sentry-specific fields resolved */\ntype ResolvedSentryConfig = Required<\n Pick<SentryExporterConfig, 'dsn' | 'environment' | 'tracesSampleRate' | 'release'>\n>;\n\nexport class SentryExporter extends BaseExporter {\n name = 'sentry';\n private sentryConfig: ResolvedSentryConfig;\n private spanMap = new Map<string, SpanData>();\n private skippedSpans = new Map<string, string>();\n private initialized = false;\n\n constructor(config: SentryExporterConfig = {}) {\n super(config);\n\n this.sentryConfig = {\n dsn: config.dsn ?? process.env.SENTRY_DSN ?? '',\n environment: config.environment ?? process.env.SENTRY_ENVIRONMENT ?? 'production',\n tracesSampleRate: config.tracesSampleRate ?? 1.0,\n release: config.release ?? process.env.SENTRY_RELEASE ?? '',\n };\n\n if (!this.sentryConfig.dsn) {\n const dsnSource = config.dsn ? 'from config' : process.env.SENTRY_DSN ? 'from env' : 'missing';\n this.setDisabled(\n `Missing required DSN (dsn: ${dsnSource}). Set SENTRY_DSN environment variable or pass it in config.`,\n );\n return;\n }\n\n try {\n Sentry.init({\n dsn: this.sentryConfig.dsn,\n environment: this.sentryConfig.environment,\n tracesSampleRate: this.sentryConfig.tracesSampleRate,\n release: this.sentryConfig.release,\n ...config.options,\n });\n this.initialized = true;\n } catch (error) {\n this.setDisabled(`Failed to initialize Sentry: ${error}`);\n }\n }\n\n // ============================================================================\n // Main Event Handlers\n // ============================================================================\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (!this.initialized) return;\n\n const { type, exportedSpan } = event;\n\n if (exportedSpan.isEvent) {\n this.handleEventSpan(exportedSpan);\n return;\n }\n\n // Skip MODEL_CHUNK, MODEL_STEP and MODEL_INFERENCE spans to simplify trace\n // hierarchy: MODEL_GENERATION is exported as the single `gen_ai.chat` span.\n // We store them in skippedSpans to preserve parent-child relationships:\n // when a child span references a skipped span as parent, resolveParentSpanId()\n // walks up the chain to find the first non-skipped ancestor.\n if (\n exportedSpan.type === SpanType.MODEL_CHUNK ||\n exportedSpan.type === SpanType.MODEL_STEP ||\n exportedSpan.type === SpanType.MODEL_INFERENCE\n ) {\n if (type === TracingEventType.SPAN_STARTED) {\n this.skippedSpans.set(exportedSpan.id, exportedSpan.parentSpanId || '');\n } else if (type === TracingEventType.SPAN_ENDED) {\n this.skippedSpans.delete(exportedSpan.id);\n }\n return;\n }\n\n switch (type) {\n case TracingEventType.SPAN_STARTED:\n await this.handleSpanStarted(exportedSpan);\n break;\n case TracingEventType.SPAN_UPDATED:\n await this.handleSpanUpdated(exportedSpan);\n break;\n case TracingEventType.SPAN_ENDED:\n await this.handleSpanEnded(exportedSpan);\n break;\n }\n }\n\n private handleEventSpan(span: AnyExportedSpan): void {\n Sentry.addBreadcrumb({\n type: 'default',\n category: span.type,\n message: span.name,\n level: span.errorInfo ? 'error' : 'info',\n data: {\n spanId: span.id,\n traceId: span.traceId,\n ...(span.input && { input: this.serializeValue(span.input) }),\n ...(span.output && { output: this.serializeValue(span.output) }),\n ...(span.metadata && { metadata: span.metadata }),\n ...(span.attributes && { attributes: span.attributes }),\n },\n timestamp: span.startTime.getTime() / 1000,\n });\n }\n\n private async handleSpanStarted(span: AnyExportedSpan): Promise<void> {\n const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);\n\n const sentrySpan = Sentry.startInactiveSpan({\n op: this.getOperationType(span),\n name: getGenAISpanName(span, this.genAIOptions(span)),\n startTime: span.startTime.getTime(),\n forceTransaction: span.isRootSpan,\n parentSpan: resolvedParentId ? this.spanMap.get(resolvedParentId)?.span : undefined,\n });\n\n sentrySpan.setAttributes(this.buildSpanAttributes(span));\n\n this.spanMap.set(span.id, {\n span: sentrySpan,\n spanType: span.type,\n });\n\n // Track tool calls as children of MODEL_GENERATION spans for gen_ai.response.tool_calls attribute\n if ((span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) && resolvedParentId) {\n this.trackToolCallForParent(span, resolvedParentId);\n }\n }\n\n private async handleSpanUpdated(span: AnyExportedSpan): Promise<void> {\n const spanData = this.spanMap.get(span.id);\n if (!spanData) {\n this.logMissingSpan(span, 'span update');\n return;\n }\n // Attributes are set on SPAN_STARTED and finalized on SPAN_ENDED.\n // If dynamic updates become necessary, add spanData.span.setAttributes() here.\n }\n\n private async handleSpanEnded(span: AnyExportedSpan): Promise<void> {\n const spanData = this.spanMap.get(span.id);\n if (!spanData) {\n this.logMissingSpan(span, 'span end');\n return;\n }\n\n const { span: sentrySpan } = spanData;\n\n sentrySpan.setAttributes(this.buildSpanAttributes(span));\n\n if (span.type === SpanType.MODEL_GENERATION) {\n // Set gen_ai.response.tool_calls if this generation had tool calls\n this.applyToolCallsAttribute(spanData);\n\n const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);\n if (resolvedParentId) {\n const parentData = this.spanMap.get(resolvedParentId);\n if (parentData?.spanType === SpanType.AGENT_RUN) {\n const modelAttr = span.attributes as ModelGenerationAttributes;\n parentData.generation = {\n model: modelAttr.model,\n output: span.output,\n usage: modelAttr.usage,\n };\n }\n }\n }\n\n if (span.type === SpanType.AGENT_RUN) {\n // Apply token usage from the single child MODEL_GENERATION span\n // (there is only ever one MODEL_GENERATION span per AGENT_RUN)\n this.applyUsageFromGeneration(spanData);\n\n this.setGenerationResponseAttributes(spanData);\n }\n\n if (span.errorInfo) {\n sentrySpan.setStatus({\n code: 2,\n message: span.errorInfo.message,\n });\n\n // Build an Error instance so Sentry can use the real stack trace captured\n // by observability rather than synthesizing one from this exporter's call site.\n // Passing a string to Sentry.captureException produces a stack that points to\n // handleSpanEnded, hiding the real error origin.\n const error = new Error(span.errorInfo.message);\n if (span.errorInfo.name) {\n error.name = span.errorInfo.name;\n }\n if (span.errorInfo.stack) {\n error.stack = span.errorInfo.stack;\n }\n\n Sentry.captureException(error, {\n contexts: {\n trace: { trace_id: span.traceId, span_id: span.id },\n span_info: {\n name: span.name,\n type: span.type,\n error_id: span.errorInfo.id,\n error_category: span.errorInfo.category,\n },\n },\n });\n }\n\n const endTime = span.endTime ? span.endTime.getTime() : undefined;\n sentrySpan.end(endTime);\n this.spanMap.delete(span.id);\n }\n\n // ============================================================================\n // Span Creation Helpers\n // ============================================================================\n\n private resolveParentSpanId(parentSpanId: string | undefined): string | undefined {\n if (!parentSpanId) return undefined;\n\n let currentParentId: string | undefined = parentSpanId;\n while (currentParentId && this.skippedSpans.has(currentParentId)) {\n currentParentId = this.skippedSpans.get(currentParentId);\n if (!currentParentId) break;\n }\n\n return currentParentId;\n }\n\n /**\n * MODEL_GENERATION is Sentry's `gen_ai.chat` span (steps and inference are\n * skipped), so it always takes the model-call GenAI attributes.\n */\n private genAIOptions(span: AnyExportedSpan): GenAISemanticsOptions {\n return { modelCall: span.type === SpanType.MODEL_GENERATION };\n }\n\n private getOperationType(span: AnyExportedSpan): string {\n const config = SPAN_TYPE_CONFIG[span.type];\n return config ? config.opType : 'ai.span';\n }\n\n private buildSpanAttributes(span: AnyExportedSpan): Record<string, any> {\n const attributes = getGenAIAttributes(span, this.genAIOptions(span)) as Record<string, any>;\n\n attributes[ATTRIBUTE_KEYS.SPAN_TYPE] = span.type;\n attributes[ATTRIBUTE_KEYS.ORIGIN] = 'auto.ai.mastra';\n\n if (span.metadata) {\n Object.entries(span.metadata).forEach(([key, value]) => {\n if (value !== undefined && value !== null && key !== 'langfuse') {\n attributes[`metadata.${key}`] = this.serializeValue(value);\n }\n });\n }\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.TAGS, span.tags?.join(','));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.GEN_AI_CONVERSATION_ID, span.metadata?.threadId);\n\n this.addInputOutputAttributes(attributes, span);\n\n if (span.type === SpanType.MODEL_GENERATION) {\n this.addModelGenerationAttributes(attributes, span);\n }\n\n if (span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) {\n this.addToolCallAttributes(attributes, span);\n }\n\n if (span.type === SpanType.AGENT_RUN) {\n this.addAgentRunAttributes(attributes, span);\n }\n\n if (span.type === SpanType.WORKFLOW_RUN) {\n const workflowAttr = span.attributes as WorkflowRunAttributes;\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_ID, this.getEntityName(span));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STATUS, workflowAttr.status);\n }\n\n if (span.type === SpanType.WORKFLOW_STEP) {\n const stepAttr = span.attributes as WorkflowStepAttributes;\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STEP_ID, this.getEntityName(span));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STEP_STATUS, stepAttr.status);\n }\n\n return attributes;\n }\n\n // ============================================================================\n // Sentry-Specific Attribute Formatters\n // ============================================================================\n\n /**\n * Adds Sentry-specific input/output attributes that complement GenAI semantic conventions.\n * Adds 'input' and 'output' keys for Sentry UI compatibility.\n */\n private addInputOutputAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n if (span.input !== undefined) {\n attributes[ATTRIBUTE_KEYS.INPUT] = this.serializeValue(span.input);\n }\n\n if (span.output !== undefined) {\n attributes[ATTRIBUTE_KEYS.OUTPUT] = this.serializeValue(span.output);\n\n // Extract text for MODEL_GENERATION spans\n if (span.type === SpanType.MODEL_GENERATION) {\n const outputText = this.extractOutputText(span.output);\n if (outputText) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TEXT] = outputText;\n }\n }\n }\n }\n\n /**\n * Adds Sentry-specific MODEL_GENERATION attributes that complement GenAI semantic conventions.\n */\n private addModelGenerationAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const modelAttr = span.attributes as ModelGenerationAttributes;\n\n if (modelAttr.streaming !== undefined) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_REQUEST_STREAM] = modelAttr.streaming;\n attributes[ATTRIBUTE_KEYS.GEN_AI_RESPONSE_STREAMING] = modelAttr.streaming;\n }\n\n this.setAttributeIfDefined(\n attributes,\n ATTRIBUTE_KEYS.GEN_AI_COMPLETION_START_TIME,\n modelAttr.completionStartTime?.toISOString(),\n );\n\n if (modelAttr.usage) {\n const totalTokens = (modelAttr.usage.inputTokens || 0) + (modelAttr.usage.outputTokens || 0);\n if (totalTokens > 0) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_USAGE_TOTAL_TOKENS] = totalTokens;\n }\n }\n }\n\n /**\n * Adds Sentry-specific TOOL_CALL attributes that complement GenAI semantic conventions.\n */\n private addToolCallAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const toolAttr = span.attributes as ToolCallAttributes;\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.TOOL_SUCCESS, toolAttr.success);\n this.setAttributeIfDefined(\n attributes,\n ATTRIBUTE_KEYS.GEN_AI_TOOL_CALL_ID,\n toolAttr.toolCallId ?? span.metadata?.toolCallId,\n );\n }\n\n /**\n * Adds Sentry-specific AGENT_RUN attributes that complement GenAI semantic conventions.\n */\n private addAgentRunAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const agentAttr = span.attributes as AgentRunAttributes;\n\n const agentName = this.getEntityName(span);\n if (agentName) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_PIPELINE_NAME] = agentName;\n }\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.GEN_AI_AGENT_PROMPT, agentAttr.prompt);\n }\n\n // ============================================================================\n // Token Usage Management\n // ============================================================================\n\n /**\n * Applies token usage from the MODEL_GENERATION span to the AGENT_RUN span attributes.\n * Reads usage directly from the generation field.\n * Called when AGENT_RUN spans end to set gen_ai.usage.* attributes.\n */\n private applyUsageFromGeneration(spanData: SpanData): void {\n const usage = spanData.generation?.usage;\n if (!usage) return;\n\n const inputTokens = usage.inputTokens || 0;\n const outputTokens = usage.outputTokens || 0;\n\n if (inputTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_INPUT_TOKENS, inputTokens);\n }\n if (outputTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);\n }\n\n const totalTokens = inputTokens + outputTokens;\n if (totalTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);\n }\n\n const cacheReadTokens = usage.inputDetails?.cacheRead || 0;\n const cacheWriteTokens = usage.inputDetails?.cacheWrite || 0;\n const reasoningTokens = usage.outputDetails?.reasoning || 0;\n\n if (cacheReadTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_CACHE_READ_TOKENS, cacheReadTokens);\n }\n if (cacheWriteTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_CACHE_WRITE_TOKENS, cacheWriteTokens);\n }\n if (reasoningTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_REASONING_TOKENS, reasoningTokens);\n }\n }\n\n /**\n * Sets gen_ai.response.model and gen_ai.response.text from the MODEL_GENERATION.\n * Only applies to AGENT_RUN spans.\n */\n private setGenerationResponseAttributes(spanData: SpanData): void {\n if (!spanData.generation) return;\n\n if (spanData.generation.model) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_MODEL, spanData.generation.model);\n }\n\n if (spanData.generation.output) {\n const outputText = this.extractOutputText(spanData.generation.output);\n if (outputText) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TEXT, outputText);\n }\n }\n }\n\n /**\n * Tracks a TOOL_CALL span as a child of its parent MODEL_GENERATION span.\n * This builds the tool_calls array for gen_ai.response.tool_calls attribute.\n */\n private trackToolCallForParent(span: AnyExportedSpan, parentId: string): void {\n const parentSpanData = this.spanMap.get(parentId);\n if (!parentSpanData || parentSpanData.spanType !== SpanType.MODEL_GENERATION) {\n return;\n }\n\n const toolAttr = span.attributes as ToolCallAttributes;\n if (!parentSpanData.toolCalls) {\n parentSpanData.toolCalls = [];\n }\n\n parentSpanData.toolCalls.push({\n name: this.getEntityName(span),\n id: toolAttr.toolCallId ?? span.metadata?.toolCallId,\n type: toolAttr.toolType || 'function',\n });\n }\n\n /**\n * Applies the gen_ai.response.tool_calls attribute to MODEL_GENERATION spans.\n * Called when MODEL_GENERATION spans end if they have child tool calls.\n */\n private applyToolCallsAttribute(spanData: SpanData): void {\n if (!spanData.toolCalls || spanData.toolCalls.length === 0) {\n return;\n }\n\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TOOL_CALLS, JSON.stringify(spanData.toolCalls));\n }\n\n // ============================================================================\n // Utility Helpers\n // ============================================================================\n\n private logMissingSpan(span: AnyExportedSpan, operation: string): void {\n this.logger.warn(`Sentry exporter: No Sentry span found for ${operation}`, {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n });\n }\n\n private getEntityName(span: AnyExportedSpan): string {\n return span.entityName || span.entityId || 'unknown';\n }\n\n private extractOutputText(output: any): string | undefined {\n if (!output) return undefined;\n if (typeof output === 'string') return output;\n if (output.text && typeof output.text === 'string') return output.text;\n if (output.content && typeof output.content === 'string') return output.content;\n if (output.message?.content && typeof output.message.content === 'string') return output.message.content;\n return undefined;\n }\n\n private serializeValue(value: any): any {\n if (value === null || value === undefined) return value;\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return value;\n }\n\n private setAttributeIfDefined(attributes: Record<string, any>, key: string, value: any): void {\n if (value !== undefined && value !== null) {\n attributes[key] = value;\n }\n }\n\n // ============================================================================\n // Flush and Shutdown\n // ============================================================================\n\n /**\n * Force flush any buffered spans without shutting down the exporter.\n * This is useful in serverless environments where you need to ensure spans\n * are exported before the runtime instance is terminated.\n */\n async flush(): Promise<void> {\n if (!this.initialized) return;\n\n try {\n // Sentry.flush() sends any pending events to Sentry\n // The timeout is in milliseconds\n await Sentry.flush(2000);\n this.logger.debug('Sentry exporter: Flushed pending events');\n } catch (error) {\n this.logger.error('Sentry exporter: Error flushing events', { error });\n }\n }\n\n async shutdown(): Promise<void> {\n for (const [spanId, spanData] of this.spanMap.entries()) {\n try {\n spanData.span.end();\n } catch (error) {\n this.logger.error('Sentry exporter: Error ending span during shutdown', { spanId, error });\n }\n }\n\n this.spanMap.clear();\n this.skippedSpans.clear();\n\n if (this.initialized) {\n await Sentry.close(2000);\n }\n\n await super.shutdown();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["SpanType","BaseExporter","TracingEventType","Sentry"],"sources":["../src/tracing.ts"],"sourcesContent":["/**\n * Sentry Exporter for Mastra Observability\n *\n * Sends observability data to Sentry for AI tracing and monitoring.\n * Uses Sentry's modern span model (v8+) with OpenTelemetry semantic conventions.\n *\n * Spans are hierarchically organized: AGENT_RUN -> MODEL_GENERATION -> TOOL_CALL\n * MODEL_STEP and MODEL_CHUNK spans are skipped to simplify the trace hierarchy.\n */\n\nimport type {\n TracingEvent,\n AnyExportedSpan,\n ModelGenerationAttributes,\n ToolCallAttributes,\n AgentRunAttributes,\n WorkflowRunAttributes,\n WorkflowStepAttributes,\n UsageStats,\n} from '@mastra/core/observability';\nimport { SpanType, TracingEventType } from '@mastra/core/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport { BaseExporter } from '@mastra/observability';\nimport { getAttributes as getGenAIAttributes, getSpanName as getGenAISpanName } from '@mastra/otel-exporter';\nimport type { GenAISemanticsOptions } from '@mastra/otel-exporter';\nimport * as Sentry from '@sentry/node';\n\ntype SentrySpanOp = { opType: string; opName: string };\n\n/**\n * Builds the span-type map, dropping any entry whose span type does not exist\n * in the paired `@mastra/core`.\n *\n * The peer range admits a core older than the one that introduced a given\n * `SpanType` member, where `SpanType.X` is `undefined` at runtime. As a plain\n * object literal that lands in the map under a literal `\"undefined\"` key, which\n * then matches any span whose type is undefined and mislabels it.\n *\n * @internal Exported for tests.\n */\nexport function buildSpanTypeConfig(\n entries: Array<[SpanType | undefined, SentrySpanOp]>,\n): Partial<Record<SpanType, SentrySpanOp>> {\n return Object.fromEntries(\n entries.filter((entry): entry is [SpanType, SentrySpanOp] => entry[0] !== undefined),\n ) as Partial<Record<SpanType, SentrySpanOp>>;\n}\n\nconst SPAN_TYPE_CONFIG: Partial<Record<SpanType, SentrySpanOp>> = buildSpanTypeConfig([\n [SpanType.AGENT_RUN, { opType: 'gen_ai.invoke_agent', opName: 'invoke_agent' }],\n [SpanType.MODEL_GENERATION, { opType: 'gen_ai.chat', opName: 'chat' }],\n [SpanType.TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.MCP_TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.PROVIDER_TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.WORKFLOW_RUN, { opType: 'workflow.run', opName: 'workflow' }],\n [SpanType.WORKFLOW_STEP, { opType: 'workflow.step', opName: 'step' }],\n [SpanType.WORKFLOW_CONDITIONAL, { opType: 'workflow.conditional', opName: 'step' }],\n [SpanType.WORKFLOW_CONDITIONAL_EVAL, { opType: 'workflow.conditional', opName: 'step' }],\n [SpanType.WORKFLOW_PARALLEL, { opType: 'workflow.parallel', opName: 'step' }],\n [SpanType.WORKFLOW_LOOP, { opType: 'workflow.loop', opName: 'step' }],\n [SpanType.WORKFLOW_SLEEP, { opType: 'workflow.sleep', opName: 'step' }],\n [SpanType.WORKFLOW_WAIT_EVENT, { opType: 'workflow.wait', opName: 'step' }],\n [SpanType.PROCESSOR_RUN, { opType: 'ai.processor', opName: 'step' }],\n [SpanType.GENERIC, { opType: 'ai.span', opName: 'span' }],\n [SpanType.MODEL_STEP, { opType: 'ai.span', opName: 'step' }],\n [SpanType.MODEL_CHUNK, { opType: 'ai.span', opName: 'step' }],\n [SpanType.SCORER_RUN, { opType: 'workflow.run', opName: 'eval' }],\n [SpanType.SCORER_STEP, { opType: 'workflow.step', opName: 'step' }],\n [SpanType.MEMORY_OPERATION, { opType: 'ai.memory', opName: 'memory' }],\n // Skill and workspace spans come from two places: the tools the model calls,\n // and the processors Mastra derives from agent config. A processor-flavoured\n // op would mislabel the tool calls, so both map to their subsystem the way\n // MEMORY_OPERATION already does. Without an entry they fall back to the\n // catch-all 'ai.span'.\n //\n // Both arrived after this package's oldest supported core, so against an\n // older one they read as `undefined`. `buildSpanTypeConfig` drops those\n // entries rather than keying the map under an `undefined` member.\n [SpanType.WORKSPACE_ACTION, { opType: 'ai.workspace', opName: 'workspace' }],\n [SpanType.SKILL_ACTION, { opType: 'ai.skill', opName: 'skill' }],\n]);\n\nconst ATTRIBUTE_KEYS = {\n SPAN_TYPE: 'ai.span.type',\n ORIGIN: 'sentry.origin',\n TAGS: 'tags',\n INPUT: 'input',\n OUTPUT: 'output',\n GEN_AI_REQUEST_STREAM: 'gen_ai.request.stream',\n GEN_AI_RESPONSE_MODEL: 'gen_ai.response.model',\n GEN_AI_RESPONSE_STREAMING: 'gen_ai.response.streaming',\n GEN_AI_RESPONSE_TOOL_CALLS: 'gen_ai.response.tool_calls',\n GEN_AI_RESPONSE_TEXT: 'gen_ai.response.text',\n GEN_AI_CONVERSATION_ID: 'gen_ai.conversation.id',\n GEN_AI_COMPLETION_START_TIME: 'gen_ai.completion_start_time',\n GEN_AI_TOOL_CALL_ID: 'gen_ai.tool.call.id',\n TOOL_SUCCESS: 'tool.success',\n GEN_AI_PIPELINE_NAME: 'gen_ai.pipeline.name',\n GEN_AI_AGENT_PROMPT: 'gen_ai.agent.prompt',\n WORKFLOW_ID: 'workflow.id',\n WORKFLOW_STATUS: 'workflow.status',\n WORKFLOW_STEP_ID: 'workflow.step.id',\n WORKFLOW_STEP_STATUS: 'workflow.step.status',\n GEN_AI_USAGE_INPUT_TOKENS: 'gen_ai.usage.input_tokens',\n GEN_AI_USAGE_OUTPUT_TOKENS: 'gen_ai.usage.output_tokens',\n GEN_AI_USAGE_TOTAL_TOKENS: 'gen_ai.usage.total_tokens',\n GEN_AI_USAGE_CACHE_READ_TOKENS: 'gen_ai.usage.cache_read.input_tokens',\n GEN_AI_USAGE_CACHE_WRITE_TOKENS: 'gen_ai.usage.cache_creation.input_tokens',\n GEN_AI_USAGE_REASONING_TOKENS: 'gen_ai.usage.reasoning_tokens',\n} as const;\n\nexport interface SentryExporterConfig extends BaseExporterConfig {\n // Sentry SDK options (passed to Sentry.init())\n /** Data Source Name - tells the SDK where to send events */\n dsn?: string;\n /** Deployment environment (enables filtering issues and alerts by environment) */\n environment?: string;\n /** Percentage of transactions sent to Sentry (0.0 = 0%, 1.0 = 100%) */\n tracesSampleRate?: number;\n /** Version of your code deployed (helps identify regressions and track deployments) */\n release?: string;\n /** Additional Sentry SDK options (integrations, beforeSend, etc.) */\n options?: Partial<Sentry.NodeOptions>;\n}\n\n/** Sentry span links for Mastra span links. Only full-length W3C IDs are kept. */\nfunction toSentryLinks(links: { traceId: string; spanId: string }[] | undefined) {\n return (links ?? [])\n .filter(link => /^[0-9a-f]{32}$/.test(link.traceId) && /^[0-9a-f]{16}$/.test(link.spanId))\n .map(link => ({ context: { traceId: link.traceId, spanId: link.spanId, traceFlags: 1 } }));\n}\n\n/**\n * Internal span tracking data.\n * generation tracks the single MODEL_GENERATION for AGENT_RUN response attributes.\n * toolCalls tracks child tool calls for MODEL_GENERATION spans.\n */\ntype SpanData = {\n span: Sentry.Span;\n spanType: SpanType;\n generation?: {\n model?: string;\n output?: any;\n usage?: UsageStats;\n };\n toolCalls?: Array<{\n name: string;\n id?: string;\n type?: string;\n }>;\n /** Keys of the links the span was started with, so links set later are added once at end. */\n startLinkKeys?: Set<string>;\n};\n\n/** Config type with Sentry-specific fields resolved */\ntype ResolvedSentryConfig = Required<\n Pick<SentryExporterConfig, 'dsn' | 'environment' | 'tracesSampleRate' | 'release'>\n>;\n\nexport class SentryExporter extends BaseExporter {\n name = 'sentry';\n private sentryConfig: ResolvedSentryConfig;\n private spanMap = new Map<string, SpanData>();\n private skippedSpans = new Map<string, string>();\n private initialized = false;\n\n constructor(config: SentryExporterConfig = {}) {\n super(config);\n\n this.sentryConfig = {\n dsn: config.dsn ?? process.env.SENTRY_DSN ?? '',\n environment: config.environment ?? process.env.SENTRY_ENVIRONMENT ?? 'production',\n tracesSampleRate: config.tracesSampleRate ?? 1.0,\n release: config.release ?? process.env.SENTRY_RELEASE ?? '',\n };\n\n if (!this.sentryConfig.dsn) {\n const dsnSource = config.dsn ? 'from config' : process.env.SENTRY_DSN ? 'from env' : 'missing';\n this.setDisabled(\n `Missing required DSN (dsn: ${dsnSource}). Set SENTRY_DSN environment variable or pass it in config.`,\n );\n return;\n }\n\n try {\n Sentry.init({\n dsn: this.sentryConfig.dsn,\n environment: this.sentryConfig.environment,\n tracesSampleRate: this.sentryConfig.tracesSampleRate,\n release: this.sentryConfig.release,\n ...config.options,\n });\n this.initialized = true;\n } catch (error) {\n this.setDisabled(`Failed to initialize Sentry: ${error}`);\n }\n }\n\n // ============================================================================\n // Main Event Handlers\n // ============================================================================\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (!this.initialized) return;\n\n const { type, exportedSpan } = event;\n\n if (exportedSpan.isEvent) {\n this.handleEventSpan(exportedSpan);\n return;\n }\n\n // Skip MODEL_CHUNK, MODEL_STEP and MODEL_INFERENCE spans to simplify trace\n // hierarchy: MODEL_GENERATION is exported as the single `gen_ai.chat` span.\n // We store them in skippedSpans to preserve parent-child relationships:\n // when a child span references a skipped span as parent, resolveParentSpanId()\n // walks up the chain to find the first non-skipped ancestor.\n if (\n exportedSpan.type === SpanType.MODEL_CHUNK ||\n exportedSpan.type === SpanType.MODEL_STEP ||\n exportedSpan.type === SpanType.MODEL_INFERENCE\n ) {\n if (type === TracingEventType.SPAN_STARTED) {\n this.skippedSpans.set(exportedSpan.id, exportedSpan.parentSpanId || '');\n } else if (type === TracingEventType.SPAN_ENDED) {\n this.skippedSpans.delete(exportedSpan.id);\n }\n return;\n }\n\n switch (type) {\n case TracingEventType.SPAN_STARTED:\n await this.handleSpanStarted(exportedSpan);\n break;\n case TracingEventType.SPAN_UPDATED:\n await this.handleSpanUpdated(exportedSpan);\n break;\n case TracingEventType.SPAN_ENDED:\n await this.handleSpanEnded(exportedSpan);\n break;\n }\n }\n\n private handleEventSpan(span: AnyExportedSpan): void {\n Sentry.addBreadcrumb({\n type: 'default',\n category: span.type,\n message: span.name,\n level: span.errorInfo ? 'error' : 'info',\n data: {\n spanId: span.id,\n traceId: span.traceId,\n ...(span.input && { input: this.serializeValue(span.input) }),\n ...(span.output && { output: this.serializeValue(span.output) }),\n ...(span.metadata && { metadata: span.metadata }),\n ...(span.attributes && { attributes: span.attributes }),\n },\n timestamp: span.startTime.getTime() / 1000,\n });\n }\n\n private async handleSpanStarted(span: AnyExportedSpan): Promise<void> {\n const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);\n\n const links = toSentryLinks(span.links);\n const sentrySpan = Sentry.startInactiveSpan({\n op: this.getOperationType(span),\n name: getGenAISpanName(span, this.genAIOptions(span)),\n startTime: span.startTime.getTime(),\n forceTransaction: span.isRootSpan,\n parentSpan: resolvedParentId ? this.spanMap.get(resolvedParentId)?.span : undefined,\n ...(links.length > 0 ? { links } : {}),\n });\n\n sentrySpan.setAttributes(this.buildSpanAttributes(span));\n\n this.spanMap.set(span.id, {\n span: sentrySpan,\n spanType: span.type,\n ...(span.links?.length\n ? { startLinkKeys: new Set(span.links.map(link => `${link.traceId}:${link.spanId}`)) }\n : {}),\n });\n\n // Track tool calls as children of MODEL_GENERATION spans for gen_ai.response.tool_calls attribute\n if ((span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) && resolvedParentId) {\n this.trackToolCallForParent(span, resolvedParentId);\n }\n }\n\n private async handleSpanUpdated(span: AnyExportedSpan): Promise<void> {\n const spanData = this.spanMap.get(span.id);\n if (!spanData) {\n this.logMissingSpan(span, 'span update');\n return;\n }\n // Attributes are set on SPAN_STARTED and finalized on SPAN_ENDED.\n // If dynamic updates become necessary, add spanData.span.setAttributes() here.\n }\n\n private async handleSpanEnded(span: AnyExportedSpan): Promise<void> {\n const spanData = this.spanMap.get(span.id);\n if (!spanData) {\n this.logMissingSpan(span, 'span end');\n return;\n }\n\n const { span: sentrySpan } = spanData;\n\n sentrySpan.setAttributes(this.buildSpanAttributes(span));\n\n if (span.type === SpanType.MODEL_GENERATION) {\n // Set gen_ai.response.tool_calls if this generation had tool calls\n this.applyToolCallsAttribute(spanData);\n\n const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);\n if (resolvedParentId) {\n const parentData = this.spanMap.get(resolvedParentId);\n if (parentData?.spanType === SpanType.AGENT_RUN) {\n const modelAttr = span.attributes as ModelGenerationAttributes;\n parentData.generation = {\n model: modelAttr.model,\n output: span.output,\n usage: modelAttr.usage,\n };\n }\n }\n }\n\n if (span.type === SpanType.AGENT_RUN) {\n // Apply token usage from the single child MODEL_GENERATION span\n // (there is only ever one MODEL_GENERATION span per AGENT_RUN)\n this.applyUsageFromGeneration(spanData);\n\n this.setGenerationResponseAttributes(spanData);\n }\n\n if (span.errorInfo) {\n sentrySpan.setStatus({\n code: 2,\n message: span.errorInfo.message,\n });\n\n // Build an Error instance so Sentry can use the real stack trace captured\n // by observability rather than synthesizing one from this exporter's call site.\n // Passing a string to Sentry.captureException produces a stack that points to\n // handleSpanEnded, hiding the real error origin.\n const error = new Error(span.errorInfo.message);\n if (span.errorInfo.name) {\n error.name = span.errorInfo.name;\n }\n if (span.errorInfo.stack) {\n error.stack = span.errorInfo.stack;\n }\n\n Sentry.captureException(error, {\n contexts: {\n trace: { trace_id: span.traceId, span_id: span.id },\n span_info: {\n name: span.name,\n type: span.type,\n error_id: span.errorInfo.id,\n error_category: span.errorInfo.category,\n },\n },\n });\n }\n\n // Links set after the span started, such as an MCP tool call's link to the\n // server span that handled it\n const lateLinks = toSentryLinks(\n span.links?.filter(link => !spanData.startLinkKeys?.has(`${link.traceId}:${link.spanId}`)),\n );\n if (lateLinks.length > 0 && typeof sentrySpan.addLinks === 'function') {\n sentrySpan.addLinks(lateLinks);\n }\n\n const endTime = span.endTime ? span.endTime.getTime() : undefined;\n sentrySpan.end(endTime);\n this.spanMap.delete(span.id);\n }\n\n // ============================================================================\n // Span Creation Helpers\n // ============================================================================\n\n private resolveParentSpanId(parentSpanId: string | undefined): string | undefined {\n if (!parentSpanId) return undefined;\n\n let currentParentId: string | undefined = parentSpanId;\n while (currentParentId && this.skippedSpans.has(currentParentId)) {\n currentParentId = this.skippedSpans.get(currentParentId);\n if (!currentParentId) break;\n }\n\n return currentParentId;\n }\n\n /**\n * MODEL_GENERATION is Sentry's `gen_ai.chat` span (steps and inference are\n * skipped), so it always takes the model-call GenAI attributes.\n */\n private genAIOptions(span: AnyExportedSpan): GenAISemanticsOptions {\n return { modelCall: span.type === SpanType.MODEL_GENERATION };\n }\n\n private getOperationType(span: AnyExportedSpan): string {\n const config = SPAN_TYPE_CONFIG[span.type];\n return config ? config.opType : 'ai.span';\n }\n\n private buildSpanAttributes(span: AnyExportedSpan): Record<string, any> {\n const attributes = getGenAIAttributes(span, this.genAIOptions(span)) as Record<string, any>;\n\n attributes[ATTRIBUTE_KEYS.SPAN_TYPE] = span.type;\n attributes[ATTRIBUTE_KEYS.ORIGIN] = 'auto.ai.mastra';\n\n if (span.metadata) {\n Object.entries(span.metadata).forEach(([key, value]) => {\n if (value !== undefined && value !== null && key !== 'langfuse') {\n attributes[`metadata.${key}`] = this.serializeValue(value);\n }\n });\n }\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.TAGS, span.tags?.join(','));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.GEN_AI_CONVERSATION_ID, span.metadata?.threadId);\n\n this.addInputOutputAttributes(attributes, span);\n\n if (span.type === SpanType.MODEL_GENERATION) {\n this.addModelGenerationAttributes(attributes, span);\n }\n\n if (span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) {\n this.addToolCallAttributes(attributes, span);\n }\n\n if (span.type === SpanType.AGENT_RUN) {\n this.addAgentRunAttributes(attributes, span);\n }\n\n if (span.type === SpanType.WORKFLOW_RUN) {\n const workflowAttr = span.attributes as WorkflowRunAttributes;\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_ID, this.getEntityName(span));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STATUS, workflowAttr.status);\n }\n\n if (span.type === SpanType.WORKFLOW_STEP) {\n const stepAttr = span.attributes as WorkflowStepAttributes;\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STEP_ID, this.getEntityName(span));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STEP_STATUS, stepAttr.status);\n }\n\n return attributes;\n }\n\n // ============================================================================\n // Sentry-Specific Attribute Formatters\n // ============================================================================\n\n /**\n * Adds Sentry-specific input/output attributes that complement GenAI semantic conventions.\n * Adds 'input' and 'output' keys for Sentry UI compatibility.\n */\n private addInputOutputAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n if (span.input !== undefined) {\n attributes[ATTRIBUTE_KEYS.INPUT] = this.serializeValue(span.input);\n }\n\n if (span.output !== undefined) {\n attributes[ATTRIBUTE_KEYS.OUTPUT] = this.serializeValue(span.output);\n\n // Extract text for MODEL_GENERATION spans\n if (span.type === SpanType.MODEL_GENERATION) {\n const outputText = this.extractOutputText(span.output);\n if (outputText) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TEXT] = outputText;\n }\n }\n }\n }\n\n /**\n * Adds Sentry-specific MODEL_GENERATION attributes that complement GenAI semantic conventions.\n */\n private addModelGenerationAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const modelAttr = span.attributes as ModelGenerationAttributes;\n\n if (modelAttr.streaming !== undefined) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_REQUEST_STREAM] = modelAttr.streaming;\n attributes[ATTRIBUTE_KEYS.GEN_AI_RESPONSE_STREAMING] = modelAttr.streaming;\n }\n\n this.setAttributeIfDefined(\n attributes,\n ATTRIBUTE_KEYS.GEN_AI_COMPLETION_START_TIME,\n modelAttr.completionStartTime?.toISOString(),\n );\n\n if (modelAttr.usage) {\n const totalTokens = (modelAttr.usage.inputTokens || 0) + (modelAttr.usage.outputTokens || 0);\n if (totalTokens > 0) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_USAGE_TOTAL_TOKENS] = totalTokens;\n }\n }\n }\n\n /**\n * Adds Sentry-specific TOOL_CALL attributes that complement GenAI semantic conventions.\n */\n private addToolCallAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const toolAttr = span.attributes as ToolCallAttributes;\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.TOOL_SUCCESS, toolAttr.success);\n this.setAttributeIfDefined(\n attributes,\n ATTRIBUTE_KEYS.GEN_AI_TOOL_CALL_ID,\n toolAttr.toolCallId ?? span.metadata?.toolCallId,\n );\n }\n\n /**\n * Adds Sentry-specific AGENT_RUN attributes that complement GenAI semantic conventions.\n */\n private addAgentRunAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const agentAttr = span.attributes as AgentRunAttributes;\n\n const agentName = this.getEntityName(span);\n if (agentName) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_PIPELINE_NAME] = agentName;\n }\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.GEN_AI_AGENT_PROMPT, agentAttr.prompt);\n }\n\n // ============================================================================\n // Token Usage Management\n // ============================================================================\n\n /**\n * Applies token usage from the MODEL_GENERATION span to the AGENT_RUN span attributes.\n * Reads usage directly from the generation field.\n * Called when AGENT_RUN spans end to set gen_ai.usage.* attributes.\n */\n private applyUsageFromGeneration(spanData: SpanData): void {\n const usage = spanData.generation?.usage;\n if (!usage) return;\n\n const inputTokens = usage.inputTokens || 0;\n const outputTokens = usage.outputTokens || 0;\n\n if (inputTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_INPUT_TOKENS, inputTokens);\n }\n if (outputTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);\n }\n\n const totalTokens = inputTokens + outputTokens;\n if (totalTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);\n }\n\n const cacheReadTokens = usage.inputDetails?.cacheRead || 0;\n const cacheWriteTokens = usage.inputDetails?.cacheWrite || 0;\n const reasoningTokens = usage.outputDetails?.reasoning || 0;\n\n if (cacheReadTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_CACHE_READ_TOKENS, cacheReadTokens);\n }\n if (cacheWriteTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_CACHE_WRITE_TOKENS, cacheWriteTokens);\n }\n if (reasoningTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_REASONING_TOKENS, reasoningTokens);\n }\n }\n\n /**\n * Sets gen_ai.response.model and gen_ai.response.text from the MODEL_GENERATION.\n * Only applies to AGENT_RUN spans.\n */\n private setGenerationResponseAttributes(spanData: SpanData): void {\n if (!spanData.generation) return;\n\n if (spanData.generation.model) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_MODEL, spanData.generation.model);\n }\n\n if (spanData.generation.output) {\n const outputText = this.extractOutputText(spanData.generation.output);\n if (outputText) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TEXT, outputText);\n }\n }\n }\n\n /**\n * Tracks a TOOL_CALL span as a child of its parent MODEL_GENERATION span.\n * This builds the tool_calls array for gen_ai.response.tool_calls attribute.\n */\n private trackToolCallForParent(span: AnyExportedSpan, parentId: string): void {\n const parentSpanData = this.spanMap.get(parentId);\n if (!parentSpanData || parentSpanData.spanType !== SpanType.MODEL_GENERATION) {\n return;\n }\n\n const toolAttr = span.attributes as ToolCallAttributes;\n if (!parentSpanData.toolCalls) {\n parentSpanData.toolCalls = [];\n }\n\n parentSpanData.toolCalls.push({\n name: this.getEntityName(span),\n id: toolAttr.toolCallId ?? span.metadata?.toolCallId,\n type: toolAttr.toolType || 'function',\n });\n }\n\n /**\n * Applies the gen_ai.response.tool_calls attribute to MODEL_GENERATION spans.\n * Called when MODEL_GENERATION spans end if they have child tool calls.\n */\n private applyToolCallsAttribute(spanData: SpanData): void {\n if (!spanData.toolCalls || spanData.toolCalls.length === 0) {\n return;\n }\n\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TOOL_CALLS, JSON.stringify(spanData.toolCalls));\n }\n\n // ============================================================================\n // Utility Helpers\n // ============================================================================\n\n private logMissingSpan(span: AnyExportedSpan, operation: string): void {\n this.logger.warn(`Sentry exporter: No Sentry span found for ${operation}`, {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n });\n }\n\n private getEntityName(span: AnyExportedSpan): string {\n return span.entityName || span.entityId || 'unknown';\n }\n\n private extractOutputText(output: any): string | undefined {\n if (!output) return undefined;\n if (typeof output === 'string') return output;\n if (output.text && typeof output.text === 'string') return output.text;\n if (output.content && typeof output.content === 'string') return output.content;\n if (output.message?.content && typeof output.message.content === 'string') return output.message.content;\n return undefined;\n }\n\n private serializeValue(value: any): any {\n if (value === null || value === undefined) return value;\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return value;\n }\n\n private setAttributeIfDefined(attributes: Record<string, any>, key: string, value: any): void {\n if (value !== undefined && value !== null) {\n attributes[key] = value;\n }\n }\n\n // ============================================================================\n // Flush and Shutdown\n // ============================================================================\n\n /**\n * Force flush any buffered spans without shutting down the exporter.\n * This is useful in serverless environments where you need to ensure spans\n * are exported before the runtime instance is terminated.\n */\n async flush(): Promise<void> {\n if (!this.initialized) return;\n\n try {\n // Sentry.flush() sends any pending events to Sentry\n // The timeout is in milliseconds\n await Sentry.flush(2000);\n this.logger.debug('Sentry exporter: Flushed pending events');\n } catch (error) {\n this.logger.error('Sentry exporter: Error flushing events', { error });\n }\n }\n\n async shutdown(): Promise<void> {\n for (const [spanId, spanData] of this.spanMap.entries()) {\n try {\n spanData.span.end();\n } catch (error) {\n this.logger.error('Sentry exporter: Error ending span during shutdown', { spanId, error });\n }\n }\n\n this.spanMap.clear();\n this.skippedSpans.clear();\n\n if (this.initialized) {\n await Sentry.close(2000);\n }\n\n await super.shutdown();\n }\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -135,6 +135,14 @@ const ATTRIBUTE_KEYS = {
135
135
  GEN_AI_USAGE_CACHE_WRITE_TOKENS: "gen_ai.usage.cache_creation.input_tokens",
136
136
  GEN_AI_USAGE_REASONING_TOKENS: "gen_ai.usage.reasoning_tokens"
137
137
  };
138
+ /** Sentry span links for Mastra span links. Only full-length W3C IDs are kept. */
139
+ function toSentryLinks(links) {
140
+ return (links ?? []).filter((link) => /^[0-9a-f]{32}$/.test(link.traceId) && /^[0-9a-f]{16}$/.test(link.spanId)).map((link) => ({ context: {
141
+ traceId: link.traceId,
142
+ spanId: link.spanId,
143
+ traceFlags: 1
144
+ } }));
145
+ }
138
146
  var SentryExporter = class extends BaseExporter {
139
147
  name = "sentry";
140
148
  sentryConfig;
@@ -210,17 +218,20 @@ var SentryExporter = class extends BaseExporter {
210
218
  }
211
219
  async handleSpanStarted(span) {
212
220
  const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);
221
+ const links = toSentryLinks(span.links);
213
222
  const sentrySpan = Sentry.startInactiveSpan({
214
223
  op: this.getOperationType(span),
215
224
  name: getSpanName(span, this.genAIOptions(span)),
216
225
  startTime: span.startTime.getTime(),
217
226
  forceTransaction: span.isRootSpan,
218
- parentSpan: resolvedParentId ? this.spanMap.get(resolvedParentId)?.span : void 0
227
+ parentSpan: resolvedParentId ? this.spanMap.get(resolvedParentId)?.span : void 0,
228
+ ...links.length > 0 ? { links } : {}
219
229
  });
220
230
  sentrySpan.setAttributes(this.buildSpanAttributes(span));
221
231
  this.spanMap.set(span.id, {
222
232
  span: sentrySpan,
223
- spanType: span.type
233
+ spanType: span.type,
234
+ ...span.links?.length ? { startLinkKeys: new Set(span.links.map((link) => `${link.traceId}:${link.spanId}`)) } : {}
224
235
  });
225
236
  if ((span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) && resolvedParentId) this.trackToolCallForParent(span, resolvedParentId);
226
237
  }
@@ -278,6 +289,8 @@ var SentryExporter = class extends BaseExporter {
278
289
  }
279
290
  } });
280
291
  }
292
+ const lateLinks = toSentryLinks(span.links?.filter((link) => !spanData.startLinkKeys?.has(`${link.traceId}:${link.spanId}`)));
293
+ if (lateLinks.length > 0 && typeof sentrySpan.addLinks === "function") sentrySpan.addLinks(lateLinks);
281
294
  const endTime = span.endTime ? span.endTime.getTime() : void 0;
282
295
  sentrySpan.end(endTime);
283
296
  this.spanMap.delete(span.id);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["getGenAISpanName","getGenAIAttributes"],"sources":["../src/tracing.ts"],"sourcesContent":["/**\n * Sentry Exporter for Mastra Observability\n *\n * Sends observability data to Sentry for AI tracing and monitoring.\n * Uses Sentry's modern span model (v8+) with OpenTelemetry semantic conventions.\n *\n * Spans are hierarchically organized: AGENT_RUN -> MODEL_GENERATION -> TOOL_CALL\n * MODEL_STEP and MODEL_CHUNK spans are skipped to simplify the trace hierarchy.\n */\n\nimport type {\n TracingEvent,\n AnyExportedSpan,\n ModelGenerationAttributes,\n ToolCallAttributes,\n AgentRunAttributes,\n WorkflowRunAttributes,\n WorkflowStepAttributes,\n UsageStats,\n} from '@mastra/core/observability';\nimport { SpanType, TracingEventType } from '@mastra/core/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport { BaseExporter } from '@mastra/observability';\nimport { getAttributes as getGenAIAttributes, getSpanName as getGenAISpanName } from '@mastra/otel-exporter';\nimport type { GenAISemanticsOptions } from '@mastra/otel-exporter';\nimport * as Sentry from '@sentry/node';\n\ntype SentrySpanOp = { opType: string; opName: string };\n\n/**\n * Builds the span-type map, dropping any entry whose span type does not exist\n * in the paired `@mastra/core`.\n *\n * The peer range admits a core older than the one that introduced a given\n * `SpanType` member, where `SpanType.X` is `undefined` at runtime. As a plain\n * object literal that lands in the map under a literal `\"undefined\"` key, which\n * then matches any span whose type is undefined and mislabels it.\n *\n * @internal Exported for tests.\n */\nexport function buildSpanTypeConfig(\n entries: Array<[SpanType | undefined, SentrySpanOp]>,\n): Partial<Record<SpanType, SentrySpanOp>> {\n return Object.fromEntries(\n entries.filter((entry): entry is [SpanType, SentrySpanOp] => entry[0] !== undefined),\n ) as Partial<Record<SpanType, SentrySpanOp>>;\n}\n\nconst SPAN_TYPE_CONFIG: Partial<Record<SpanType, SentrySpanOp>> = buildSpanTypeConfig([\n [SpanType.AGENT_RUN, { opType: 'gen_ai.invoke_agent', opName: 'invoke_agent' }],\n [SpanType.MODEL_GENERATION, { opType: 'gen_ai.chat', opName: 'chat' }],\n [SpanType.TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.MCP_TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.PROVIDER_TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.WORKFLOW_RUN, { opType: 'workflow.run', opName: 'workflow' }],\n [SpanType.WORKFLOW_STEP, { opType: 'workflow.step', opName: 'step' }],\n [SpanType.WORKFLOW_CONDITIONAL, { opType: 'workflow.conditional', opName: 'step' }],\n [SpanType.WORKFLOW_CONDITIONAL_EVAL, { opType: 'workflow.conditional', opName: 'step' }],\n [SpanType.WORKFLOW_PARALLEL, { opType: 'workflow.parallel', opName: 'step' }],\n [SpanType.WORKFLOW_LOOP, { opType: 'workflow.loop', opName: 'step' }],\n [SpanType.WORKFLOW_SLEEP, { opType: 'workflow.sleep', opName: 'step' }],\n [SpanType.WORKFLOW_WAIT_EVENT, { opType: 'workflow.wait', opName: 'step' }],\n [SpanType.PROCESSOR_RUN, { opType: 'ai.processor', opName: 'step' }],\n [SpanType.GENERIC, { opType: 'ai.span', opName: 'span' }],\n [SpanType.MODEL_STEP, { opType: 'ai.span', opName: 'step' }],\n [SpanType.MODEL_CHUNK, { opType: 'ai.span', opName: 'step' }],\n [SpanType.SCORER_RUN, { opType: 'workflow.run', opName: 'eval' }],\n [SpanType.SCORER_STEP, { opType: 'workflow.step', opName: 'step' }],\n [SpanType.MEMORY_OPERATION, { opType: 'ai.memory', opName: 'memory' }],\n // Skill and workspace spans come from two places: the tools the model calls,\n // and the processors Mastra derives from agent config. A processor-flavoured\n // op would mislabel the tool calls, so both map to their subsystem the way\n // MEMORY_OPERATION already does. Without an entry they fall back to the\n // catch-all 'ai.span'.\n //\n // Both arrived after this package's oldest supported core, so against an\n // older one they read as `undefined`. `buildSpanTypeConfig` drops those\n // entries rather than keying the map under an `undefined` member.\n [SpanType.WORKSPACE_ACTION, { opType: 'ai.workspace', opName: 'workspace' }],\n [SpanType.SKILL_ACTION, { opType: 'ai.skill', opName: 'skill' }],\n]);\n\nconst ATTRIBUTE_KEYS = {\n SPAN_TYPE: 'ai.span.type',\n ORIGIN: 'sentry.origin',\n TAGS: 'tags',\n INPUT: 'input',\n OUTPUT: 'output',\n GEN_AI_REQUEST_STREAM: 'gen_ai.request.stream',\n GEN_AI_RESPONSE_MODEL: 'gen_ai.response.model',\n GEN_AI_RESPONSE_STREAMING: 'gen_ai.response.streaming',\n GEN_AI_RESPONSE_TOOL_CALLS: 'gen_ai.response.tool_calls',\n GEN_AI_RESPONSE_TEXT: 'gen_ai.response.text',\n GEN_AI_CONVERSATION_ID: 'gen_ai.conversation.id',\n GEN_AI_COMPLETION_START_TIME: 'gen_ai.completion_start_time',\n GEN_AI_TOOL_CALL_ID: 'gen_ai.tool.call.id',\n TOOL_SUCCESS: 'tool.success',\n GEN_AI_PIPELINE_NAME: 'gen_ai.pipeline.name',\n GEN_AI_AGENT_PROMPT: 'gen_ai.agent.prompt',\n WORKFLOW_ID: 'workflow.id',\n WORKFLOW_STATUS: 'workflow.status',\n WORKFLOW_STEP_ID: 'workflow.step.id',\n WORKFLOW_STEP_STATUS: 'workflow.step.status',\n GEN_AI_USAGE_INPUT_TOKENS: 'gen_ai.usage.input_tokens',\n GEN_AI_USAGE_OUTPUT_TOKENS: 'gen_ai.usage.output_tokens',\n GEN_AI_USAGE_TOTAL_TOKENS: 'gen_ai.usage.total_tokens',\n GEN_AI_USAGE_CACHE_READ_TOKENS: 'gen_ai.usage.cache_read.input_tokens',\n GEN_AI_USAGE_CACHE_WRITE_TOKENS: 'gen_ai.usage.cache_creation.input_tokens',\n GEN_AI_USAGE_REASONING_TOKENS: 'gen_ai.usage.reasoning_tokens',\n} as const;\n\nexport interface SentryExporterConfig extends BaseExporterConfig {\n // Sentry SDK options (passed to Sentry.init())\n /** Data Source Name - tells the SDK where to send events */\n dsn?: string;\n /** Deployment environment (enables filtering issues and alerts by environment) */\n environment?: string;\n /** Percentage of transactions sent to Sentry (0.0 = 0%, 1.0 = 100%) */\n tracesSampleRate?: number;\n /** Version of your code deployed (helps identify regressions and track deployments) */\n release?: string;\n /** Additional Sentry SDK options (integrations, beforeSend, etc.) */\n options?: Partial<Sentry.NodeOptions>;\n}\n\n/**\n * Internal span tracking data.\n * generation tracks the single MODEL_GENERATION for AGENT_RUN response attributes.\n * toolCalls tracks child tool calls for MODEL_GENERATION spans.\n */\ntype SpanData = {\n span: Sentry.Span;\n spanType: SpanType;\n generation?: {\n model?: string;\n output?: any;\n usage?: UsageStats;\n };\n toolCalls?: Array<{\n name: string;\n id?: string;\n type?: string;\n }>;\n};\n\n/** Config type with Sentry-specific fields resolved */\ntype ResolvedSentryConfig = Required<\n Pick<SentryExporterConfig, 'dsn' | 'environment' | 'tracesSampleRate' | 'release'>\n>;\n\nexport class SentryExporter extends BaseExporter {\n name = 'sentry';\n private sentryConfig: ResolvedSentryConfig;\n private spanMap = new Map<string, SpanData>();\n private skippedSpans = new Map<string, string>();\n private initialized = false;\n\n constructor(config: SentryExporterConfig = {}) {\n super(config);\n\n this.sentryConfig = {\n dsn: config.dsn ?? process.env.SENTRY_DSN ?? '',\n environment: config.environment ?? process.env.SENTRY_ENVIRONMENT ?? 'production',\n tracesSampleRate: config.tracesSampleRate ?? 1.0,\n release: config.release ?? process.env.SENTRY_RELEASE ?? '',\n };\n\n if (!this.sentryConfig.dsn) {\n const dsnSource = config.dsn ? 'from config' : process.env.SENTRY_DSN ? 'from env' : 'missing';\n this.setDisabled(\n `Missing required DSN (dsn: ${dsnSource}). Set SENTRY_DSN environment variable or pass it in config.`,\n );\n return;\n }\n\n try {\n Sentry.init({\n dsn: this.sentryConfig.dsn,\n environment: this.sentryConfig.environment,\n tracesSampleRate: this.sentryConfig.tracesSampleRate,\n release: this.sentryConfig.release,\n ...config.options,\n });\n this.initialized = true;\n } catch (error) {\n this.setDisabled(`Failed to initialize Sentry: ${error}`);\n }\n }\n\n // ============================================================================\n // Main Event Handlers\n // ============================================================================\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (!this.initialized) return;\n\n const { type, exportedSpan } = event;\n\n if (exportedSpan.isEvent) {\n this.handleEventSpan(exportedSpan);\n return;\n }\n\n // Skip MODEL_CHUNK, MODEL_STEP and MODEL_INFERENCE spans to simplify trace\n // hierarchy: MODEL_GENERATION is exported as the single `gen_ai.chat` span.\n // We store them in skippedSpans to preserve parent-child relationships:\n // when a child span references a skipped span as parent, resolveParentSpanId()\n // walks up the chain to find the first non-skipped ancestor.\n if (\n exportedSpan.type === SpanType.MODEL_CHUNK ||\n exportedSpan.type === SpanType.MODEL_STEP ||\n exportedSpan.type === SpanType.MODEL_INFERENCE\n ) {\n if (type === TracingEventType.SPAN_STARTED) {\n this.skippedSpans.set(exportedSpan.id, exportedSpan.parentSpanId || '');\n } else if (type === TracingEventType.SPAN_ENDED) {\n this.skippedSpans.delete(exportedSpan.id);\n }\n return;\n }\n\n switch (type) {\n case TracingEventType.SPAN_STARTED:\n await this.handleSpanStarted(exportedSpan);\n break;\n case TracingEventType.SPAN_UPDATED:\n await this.handleSpanUpdated(exportedSpan);\n break;\n case TracingEventType.SPAN_ENDED:\n await this.handleSpanEnded(exportedSpan);\n break;\n }\n }\n\n private handleEventSpan(span: AnyExportedSpan): void {\n Sentry.addBreadcrumb({\n type: 'default',\n category: span.type,\n message: span.name,\n level: span.errorInfo ? 'error' : 'info',\n data: {\n spanId: span.id,\n traceId: span.traceId,\n ...(span.input && { input: this.serializeValue(span.input) }),\n ...(span.output && { output: this.serializeValue(span.output) }),\n ...(span.metadata && { metadata: span.metadata }),\n ...(span.attributes && { attributes: span.attributes }),\n },\n timestamp: span.startTime.getTime() / 1000,\n });\n }\n\n private async handleSpanStarted(span: AnyExportedSpan): Promise<void> {\n const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);\n\n const sentrySpan = Sentry.startInactiveSpan({\n op: this.getOperationType(span),\n name: getGenAISpanName(span, this.genAIOptions(span)),\n startTime: span.startTime.getTime(),\n forceTransaction: span.isRootSpan,\n parentSpan: resolvedParentId ? this.spanMap.get(resolvedParentId)?.span : undefined,\n });\n\n sentrySpan.setAttributes(this.buildSpanAttributes(span));\n\n this.spanMap.set(span.id, {\n span: sentrySpan,\n spanType: span.type,\n });\n\n // Track tool calls as children of MODEL_GENERATION spans for gen_ai.response.tool_calls attribute\n if ((span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) && resolvedParentId) {\n this.trackToolCallForParent(span, resolvedParentId);\n }\n }\n\n private async handleSpanUpdated(span: AnyExportedSpan): Promise<void> {\n const spanData = this.spanMap.get(span.id);\n if (!spanData) {\n this.logMissingSpan(span, 'span update');\n return;\n }\n // Attributes are set on SPAN_STARTED and finalized on SPAN_ENDED.\n // If dynamic updates become necessary, add spanData.span.setAttributes() here.\n }\n\n private async handleSpanEnded(span: AnyExportedSpan): Promise<void> {\n const spanData = this.spanMap.get(span.id);\n if (!spanData) {\n this.logMissingSpan(span, 'span end');\n return;\n }\n\n const { span: sentrySpan } = spanData;\n\n sentrySpan.setAttributes(this.buildSpanAttributes(span));\n\n if (span.type === SpanType.MODEL_GENERATION) {\n // Set gen_ai.response.tool_calls if this generation had tool calls\n this.applyToolCallsAttribute(spanData);\n\n const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);\n if (resolvedParentId) {\n const parentData = this.spanMap.get(resolvedParentId);\n if (parentData?.spanType === SpanType.AGENT_RUN) {\n const modelAttr = span.attributes as ModelGenerationAttributes;\n parentData.generation = {\n model: modelAttr.model,\n output: span.output,\n usage: modelAttr.usage,\n };\n }\n }\n }\n\n if (span.type === SpanType.AGENT_RUN) {\n // Apply token usage from the single child MODEL_GENERATION span\n // (there is only ever one MODEL_GENERATION span per AGENT_RUN)\n this.applyUsageFromGeneration(spanData);\n\n this.setGenerationResponseAttributes(spanData);\n }\n\n if (span.errorInfo) {\n sentrySpan.setStatus({\n code: 2,\n message: span.errorInfo.message,\n });\n\n // Build an Error instance so Sentry can use the real stack trace captured\n // by observability rather than synthesizing one from this exporter's call site.\n // Passing a string to Sentry.captureException produces a stack that points to\n // handleSpanEnded, hiding the real error origin.\n const error = new Error(span.errorInfo.message);\n if (span.errorInfo.name) {\n error.name = span.errorInfo.name;\n }\n if (span.errorInfo.stack) {\n error.stack = span.errorInfo.stack;\n }\n\n Sentry.captureException(error, {\n contexts: {\n trace: { trace_id: span.traceId, span_id: span.id },\n span_info: {\n name: span.name,\n type: span.type,\n error_id: span.errorInfo.id,\n error_category: span.errorInfo.category,\n },\n },\n });\n }\n\n const endTime = span.endTime ? span.endTime.getTime() : undefined;\n sentrySpan.end(endTime);\n this.spanMap.delete(span.id);\n }\n\n // ============================================================================\n // Span Creation Helpers\n // ============================================================================\n\n private resolveParentSpanId(parentSpanId: string | undefined): string | undefined {\n if (!parentSpanId) return undefined;\n\n let currentParentId: string | undefined = parentSpanId;\n while (currentParentId && this.skippedSpans.has(currentParentId)) {\n currentParentId = this.skippedSpans.get(currentParentId);\n if (!currentParentId) break;\n }\n\n return currentParentId;\n }\n\n /**\n * MODEL_GENERATION is Sentry's `gen_ai.chat` span (steps and inference are\n * skipped), so it always takes the model-call GenAI attributes.\n */\n private genAIOptions(span: AnyExportedSpan): GenAISemanticsOptions {\n return { modelCall: span.type === SpanType.MODEL_GENERATION };\n }\n\n private getOperationType(span: AnyExportedSpan): string {\n const config = SPAN_TYPE_CONFIG[span.type];\n return config ? config.opType : 'ai.span';\n }\n\n private buildSpanAttributes(span: AnyExportedSpan): Record<string, any> {\n const attributes = getGenAIAttributes(span, this.genAIOptions(span)) as Record<string, any>;\n\n attributes[ATTRIBUTE_KEYS.SPAN_TYPE] = span.type;\n attributes[ATTRIBUTE_KEYS.ORIGIN] = 'auto.ai.mastra';\n\n if (span.metadata) {\n Object.entries(span.metadata).forEach(([key, value]) => {\n if (value !== undefined && value !== null && key !== 'langfuse') {\n attributes[`metadata.${key}`] = this.serializeValue(value);\n }\n });\n }\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.TAGS, span.tags?.join(','));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.GEN_AI_CONVERSATION_ID, span.metadata?.threadId);\n\n this.addInputOutputAttributes(attributes, span);\n\n if (span.type === SpanType.MODEL_GENERATION) {\n this.addModelGenerationAttributes(attributes, span);\n }\n\n if (span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) {\n this.addToolCallAttributes(attributes, span);\n }\n\n if (span.type === SpanType.AGENT_RUN) {\n this.addAgentRunAttributes(attributes, span);\n }\n\n if (span.type === SpanType.WORKFLOW_RUN) {\n const workflowAttr = span.attributes as WorkflowRunAttributes;\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_ID, this.getEntityName(span));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STATUS, workflowAttr.status);\n }\n\n if (span.type === SpanType.WORKFLOW_STEP) {\n const stepAttr = span.attributes as WorkflowStepAttributes;\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STEP_ID, this.getEntityName(span));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STEP_STATUS, stepAttr.status);\n }\n\n return attributes;\n }\n\n // ============================================================================\n // Sentry-Specific Attribute Formatters\n // ============================================================================\n\n /**\n * Adds Sentry-specific input/output attributes that complement GenAI semantic conventions.\n * Adds 'input' and 'output' keys for Sentry UI compatibility.\n */\n private addInputOutputAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n if (span.input !== undefined) {\n attributes[ATTRIBUTE_KEYS.INPUT] = this.serializeValue(span.input);\n }\n\n if (span.output !== undefined) {\n attributes[ATTRIBUTE_KEYS.OUTPUT] = this.serializeValue(span.output);\n\n // Extract text for MODEL_GENERATION spans\n if (span.type === SpanType.MODEL_GENERATION) {\n const outputText = this.extractOutputText(span.output);\n if (outputText) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TEXT] = outputText;\n }\n }\n }\n }\n\n /**\n * Adds Sentry-specific MODEL_GENERATION attributes that complement GenAI semantic conventions.\n */\n private addModelGenerationAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const modelAttr = span.attributes as ModelGenerationAttributes;\n\n if (modelAttr.streaming !== undefined) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_REQUEST_STREAM] = modelAttr.streaming;\n attributes[ATTRIBUTE_KEYS.GEN_AI_RESPONSE_STREAMING] = modelAttr.streaming;\n }\n\n this.setAttributeIfDefined(\n attributes,\n ATTRIBUTE_KEYS.GEN_AI_COMPLETION_START_TIME,\n modelAttr.completionStartTime?.toISOString(),\n );\n\n if (modelAttr.usage) {\n const totalTokens = (modelAttr.usage.inputTokens || 0) + (modelAttr.usage.outputTokens || 0);\n if (totalTokens > 0) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_USAGE_TOTAL_TOKENS] = totalTokens;\n }\n }\n }\n\n /**\n * Adds Sentry-specific TOOL_CALL attributes that complement GenAI semantic conventions.\n */\n private addToolCallAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const toolAttr = span.attributes as ToolCallAttributes;\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.TOOL_SUCCESS, toolAttr.success);\n this.setAttributeIfDefined(\n attributes,\n ATTRIBUTE_KEYS.GEN_AI_TOOL_CALL_ID,\n toolAttr.toolCallId ?? span.metadata?.toolCallId,\n );\n }\n\n /**\n * Adds Sentry-specific AGENT_RUN attributes that complement GenAI semantic conventions.\n */\n private addAgentRunAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const agentAttr = span.attributes as AgentRunAttributes;\n\n const agentName = this.getEntityName(span);\n if (agentName) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_PIPELINE_NAME] = agentName;\n }\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.GEN_AI_AGENT_PROMPT, agentAttr.prompt);\n }\n\n // ============================================================================\n // Token Usage Management\n // ============================================================================\n\n /**\n * Applies token usage from the MODEL_GENERATION span to the AGENT_RUN span attributes.\n * Reads usage directly from the generation field.\n * Called when AGENT_RUN spans end to set gen_ai.usage.* attributes.\n */\n private applyUsageFromGeneration(spanData: SpanData): void {\n const usage = spanData.generation?.usage;\n if (!usage) return;\n\n const inputTokens = usage.inputTokens || 0;\n const outputTokens = usage.outputTokens || 0;\n\n if (inputTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_INPUT_TOKENS, inputTokens);\n }\n if (outputTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);\n }\n\n const totalTokens = inputTokens + outputTokens;\n if (totalTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);\n }\n\n const cacheReadTokens = usage.inputDetails?.cacheRead || 0;\n const cacheWriteTokens = usage.inputDetails?.cacheWrite || 0;\n const reasoningTokens = usage.outputDetails?.reasoning || 0;\n\n if (cacheReadTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_CACHE_READ_TOKENS, cacheReadTokens);\n }\n if (cacheWriteTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_CACHE_WRITE_TOKENS, cacheWriteTokens);\n }\n if (reasoningTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_REASONING_TOKENS, reasoningTokens);\n }\n }\n\n /**\n * Sets gen_ai.response.model and gen_ai.response.text from the MODEL_GENERATION.\n * Only applies to AGENT_RUN spans.\n */\n private setGenerationResponseAttributes(spanData: SpanData): void {\n if (!spanData.generation) return;\n\n if (spanData.generation.model) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_MODEL, spanData.generation.model);\n }\n\n if (spanData.generation.output) {\n const outputText = this.extractOutputText(spanData.generation.output);\n if (outputText) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TEXT, outputText);\n }\n }\n }\n\n /**\n * Tracks a TOOL_CALL span as a child of its parent MODEL_GENERATION span.\n * This builds the tool_calls array for gen_ai.response.tool_calls attribute.\n */\n private trackToolCallForParent(span: AnyExportedSpan, parentId: string): void {\n const parentSpanData = this.spanMap.get(parentId);\n if (!parentSpanData || parentSpanData.spanType !== SpanType.MODEL_GENERATION) {\n return;\n }\n\n const toolAttr = span.attributes as ToolCallAttributes;\n if (!parentSpanData.toolCalls) {\n parentSpanData.toolCalls = [];\n }\n\n parentSpanData.toolCalls.push({\n name: this.getEntityName(span),\n id: toolAttr.toolCallId ?? span.metadata?.toolCallId,\n type: toolAttr.toolType || 'function',\n });\n }\n\n /**\n * Applies the gen_ai.response.tool_calls attribute to MODEL_GENERATION spans.\n * Called when MODEL_GENERATION spans end if they have child tool calls.\n */\n private applyToolCallsAttribute(spanData: SpanData): void {\n if (!spanData.toolCalls || spanData.toolCalls.length === 0) {\n return;\n }\n\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TOOL_CALLS, JSON.stringify(spanData.toolCalls));\n }\n\n // ============================================================================\n // Utility Helpers\n // ============================================================================\n\n private logMissingSpan(span: AnyExportedSpan, operation: string): void {\n this.logger.warn(`Sentry exporter: No Sentry span found for ${operation}`, {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n });\n }\n\n private getEntityName(span: AnyExportedSpan): string {\n return span.entityName || span.entityId || 'unknown';\n }\n\n private extractOutputText(output: any): string | undefined {\n if (!output) return undefined;\n if (typeof output === 'string') return output;\n if (output.text && typeof output.text === 'string') return output.text;\n if (output.content && typeof output.content === 'string') return output.content;\n if (output.message?.content && typeof output.message.content === 'string') return output.message.content;\n return undefined;\n }\n\n private serializeValue(value: any): any {\n if (value === null || value === undefined) return value;\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return value;\n }\n\n private setAttributeIfDefined(attributes: Record<string, any>, key: string, value: any): void {\n if (value !== undefined && value !== null) {\n attributes[key] = value;\n }\n }\n\n // ============================================================================\n // Flush and Shutdown\n // ============================================================================\n\n /**\n * Force flush any buffered spans without shutting down the exporter.\n * This is useful in serverless environments where you need to ensure spans\n * are exported before the runtime instance is terminated.\n */\n async flush(): Promise<void> {\n if (!this.initialized) return;\n\n try {\n // Sentry.flush() sends any pending events to Sentry\n // The timeout is in milliseconds\n await Sentry.flush(2000);\n this.logger.debug('Sentry exporter: Flushed pending events');\n } catch (error) {\n this.logger.error('Sentry exporter: Error flushing events', { error });\n }\n }\n\n async shutdown(): Promise<void> {\n for (const [spanId, spanData] of this.spanMap.entries()) {\n try {\n spanData.span.end();\n } catch (error) {\n this.logger.error('Sentry exporter: Error ending span during shutdown', { spanId, error });\n }\n }\n\n this.spanMap.clear();\n this.skippedSpans.clear();\n\n if (this.initialized) {\n await Sentry.close(2000);\n }\n\n await super.shutdown();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["getGenAISpanName","getGenAIAttributes"],"sources":["../src/tracing.ts"],"sourcesContent":["/**\n * Sentry Exporter for Mastra Observability\n *\n * Sends observability data to Sentry for AI tracing and monitoring.\n * Uses Sentry's modern span model (v8+) with OpenTelemetry semantic conventions.\n *\n * Spans are hierarchically organized: AGENT_RUN -> MODEL_GENERATION -> TOOL_CALL\n * MODEL_STEP and MODEL_CHUNK spans are skipped to simplify the trace hierarchy.\n */\n\nimport type {\n TracingEvent,\n AnyExportedSpan,\n ModelGenerationAttributes,\n ToolCallAttributes,\n AgentRunAttributes,\n WorkflowRunAttributes,\n WorkflowStepAttributes,\n UsageStats,\n} from '@mastra/core/observability';\nimport { SpanType, TracingEventType } from '@mastra/core/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport { BaseExporter } from '@mastra/observability';\nimport { getAttributes as getGenAIAttributes, getSpanName as getGenAISpanName } from '@mastra/otel-exporter';\nimport type { GenAISemanticsOptions } from '@mastra/otel-exporter';\nimport * as Sentry from '@sentry/node';\n\ntype SentrySpanOp = { opType: string; opName: string };\n\n/**\n * Builds the span-type map, dropping any entry whose span type does not exist\n * in the paired `@mastra/core`.\n *\n * The peer range admits a core older than the one that introduced a given\n * `SpanType` member, where `SpanType.X` is `undefined` at runtime. As a plain\n * object literal that lands in the map under a literal `\"undefined\"` key, which\n * then matches any span whose type is undefined and mislabels it.\n *\n * @internal Exported for tests.\n */\nexport function buildSpanTypeConfig(\n entries: Array<[SpanType | undefined, SentrySpanOp]>,\n): Partial<Record<SpanType, SentrySpanOp>> {\n return Object.fromEntries(\n entries.filter((entry): entry is [SpanType, SentrySpanOp] => entry[0] !== undefined),\n ) as Partial<Record<SpanType, SentrySpanOp>>;\n}\n\nconst SPAN_TYPE_CONFIG: Partial<Record<SpanType, SentrySpanOp>> = buildSpanTypeConfig([\n [SpanType.AGENT_RUN, { opType: 'gen_ai.invoke_agent', opName: 'invoke_agent' }],\n [SpanType.MODEL_GENERATION, { opType: 'gen_ai.chat', opName: 'chat' }],\n [SpanType.TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.MCP_TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.PROVIDER_TOOL_CALL, { opType: 'gen_ai.execute_tool', opName: 'execute_tool' }],\n [SpanType.WORKFLOW_RUN, { opType: 'workflow.run', opName: 'workflow' }],\n [SpanType.WORKFLOW_STEP, { opType: 'workflow.step', opName: 'step' }],\n [SpanType.WORKFLOW_CONDITIONAL, { opType: 'workflow.conditional', opName: 'step' }],\n [SpanType.WORKFLOW_CONDITIONAL_EVAL, { opType: 'workflow.conditional', opName: 'step' }],\n [SpanType.WORKFLOW_PARALLEL, { opType: 'workflow.parallel', opName: 'step' }],\n [SpanType.WORKFLOW_LOOP, { opType: 'workflow.loop', opName: 'step' }],\n [SpanType.WORKFLOW_SLEEP, { opType: 'workflow.sleep', opName: 'step' }],\n [SpanType.WORKFLOW_WAIT_EVENT, { opType: 'workflow.wait', opName: 'step' }],\n [SpanType.PROCESSOR_RUN, { opType: 'ai.processor', opName: 'step' }],\n [SpanType.GENERIC, { opType: 'ai.span', opName: 'span' }],\n [SpanType.MODEL_STEP, { opType: 'ai.span', opName: 'step' }],\n [SpanType.MODEL_CHUNK, { opType: 'ai.span', opName: 'step' }],\n [SpanType.SCORER_RUN, { opType: 'workflow.run', opName: 'eval' }],\n [SpanType.SCORER_STEP, { opType: 'workflow.step', opName: 'step' }],\n [SpanType.MEMORY_OPERATION, { opType: 'ai.memory', opName: 'memory' }],\n // Skill and workspace spans come from two places: the tools the model calls,\n // and the processors Mastra derives from agent config. A processor-flavoured\n // op would mislabel the tool calls, so both map to their subsystem the way\n // MEMORY_OPERATION already does. Without an entry they fall back to the\n // catch-all 'ai.span'.\n //\n // Both arrived after this package's oldest supported core, so against an\n // older one they read as `undefined`. `buildSpanTypeConfig` drops those\n // entries rather than keying the map under an `undefined` member.\n [SpanType.WORKSPACE_ACTION, { opType: 'ai.workspace', opName: 'workspace' }],\n [SpanType.SKILL_ACTION, { opType: 'ai.skill', opName: 'skill' }],\n]);\n\nconst ATTRIBUTE_KEYS = {\n SPAN_TYPE: 'ai.span.type',\n ORIGIN: 'sentry.origin',\n TAGS: 'tags',\n INPUT: 'input',\n OUTPUT: 'output',\n GEN_AI_REQUEST_STREAM: 'gen_ai.request.stream',\n GEN_AI_RESPONSE_MODEL: 'gen_ai.response.model',\n GEN_AI_RESPONSE_STREAMING: 'gen_ai.response.streaming',\n GEN_AI_RESPONSE_TOOL_CALLS: 'gen_ai.response.tool_calls',\n GEN_AI_RESPONSE_TEXT: 'gen_ai.response.text',\n GEN_AI_CONVERSATION_ID: 'gen_ai.conversation.id',\n GEN_AI_COMPLETION_START_TIME: 'gen_ai.completion_start_time',\n GEN_AI_TOOL_CALL_ID: 'gen_ai.tool.call.id',\n TOOL_SUCCESS: 'tool.success',\n GEN_AI_PIPELINE_NAME: 'gen_ai.pipeline.name',\n GEN_AI_AGENT_PROMPT: 'gen_ai.agent.prompt',\n WORKFLOW_ID: 'workflow.id',\n WORKFLOW_STATUS: 'workflow.status',\n WORKFLOW_STEP_ID: 'workflow.step.id',\n WORKFLOW_STEP_STATUS: 'workflow.step.status',\n GEN_AI_USAGE_INPUT_TOKENS: 'gen_ai.usage.input_tokens',\n GEN_AI_USAGE_OUTPUT_TOKENS: 'gen_ai.usage.output_tokens',\n GEN_AI_USAGE_TOTAL_TOKENS: 'gen_ai.usage.total_tokens',\n GEN_AI_USAGE_CACHE_READ_TOKENS: 'gen_ai.usage.cache_read.input_tokens',\n GEN_AI_USAGE_CACHE_WRITE_TOKENS: 'gen_ai.usage.cache_creation.input_tokens',\n GEN_AI_USAGE_REASONING_TOKENS: 'gen_ai.usage.reasoning_tokens',\n} as const;\n\nexport interface SentryExporterConfig extends BaseExporterConfig {\n // Sentry SDK options (passed to Sentry.init())\n /** Data Source Name - tells the SDK where to send events */\n dsn?: string;\n /** Deployment environment (enables filtering issues and alerts by environment) */\n environment?: string;\n /** Percentage of transactions sent to Sentry (0.0 = 0%, 1.0 = 100%) */\n tracesSampleRate?: number;\n /** Version of your code deployed (helps identify regressions and track deployments) */\n release?: string;\n /** Additional Sentry SDK options (integrations, beforeSend, etc.) */\n options?: Partial<Sentry.NodeOptions>;\n}\n\n/** Sentry span links for Mastra span links. Only full-length W3C IDs are kept. */\nfunction toSentryLinks(links: { traceId: string; spanId: string }[] | undefined) {\n return (links ?? [])\n .filter(link => /^[0-9a-f]{32}$/.test(link.traceId) && /^[0-9a-f]{16}$/.test(link.spanId))\n .map(link => ({ context: { traceId: link.traceId, spanId: link.spanId, traceFlags: 1 } }));\n}\n\n/**\n * Internal span tracking data.\n * generation tracks the single MODEL_GENERATION for AGENT_RUN response attributes.\n * toolCalls tracks child tool calls for MODEL_GENERATION spans.\n */\ntype SpanData = {\n span: Sentry.Span;\n spanType: SpanType;\n generation?: {\n model?: string;\n output?: any;\n usage?: UsageStats;\n };\n toolCalls?: Array<{\n name: string;\n id?: string;\n type?: string;\n }>;\n /** Keys of the links the span was started with, so links set later are added once at end. */\n startLinkKeys?: Set<string>;\n};\n\n/** Config type with Sentry-specific fields resolved */\ntype ResolvedSentryConfig = Required<\n Pick<SentryExporterConfig, 'dsn' | 'environment' | 'tracesSampleRate' | 'release'>\n>;\n\nexport class SentryExporter extends BaseExporter {\n name = 'sentry';\n private sentryConfig: ResolvedSentryConfig;\n private spanMap = new Map<string, SpanData>();\n private skippedSpans = new Map<string, string>();\n private initialized = false;\n\n constructor(config: SentryExporterConfig = {}) {\n super(config);\n\n this.sentryConfig = {\n dsn: config.dsn ?? process.env.SENTRY_DSN ?? '',\n environment: config.environment ?? process.env.SENTRY_ENVIRONMENT ?? 'production',\n tracesSampleRate: config.tracesSampleRate ?? 1.0,\n release: config.release ?? process.env.SENTRY_RELEASE ?? '',\n };\n\n if (!this.sentryConfig.dsn) {\n const dsnSource = config.dsn ? 'from config' : process.env.SENTRY_DSN ? 'from env' : 'missing';\n this.setDisabled(\n `Missing required DSN (dsn: ${dsnSource}). Set SENTRY_DSN environment variable or pass it in config.`,\n );\n return;\n }\n\n try {\n Sentry.init({\n dsn: this.sentryConfig.dsn,\n environment: this.sentryConfig.environment,\n tracesSampleRate: this.sentryConfig.tracesSampleRate,\n release: this.sentryConfig.release,\n ...config.options,\n });\n this.initialized = true;\n } catch (error) {\n this.setDisabled(`Failed to initialize Sentry: ${error}`);\n }\n }\n\n // ============================================================================\n // Main Event Handlers\n // ============================================================================\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (!this.initialized) return;\n\n const { type, exportedSpan } = event;\n\n if (exportedSpan.isEvent) {\n this.handleEventSpan(exportedSpan);\n return;\n }\n\n // Skip MODEL_CHUNK, MODEL_STEP and MODEL_INFERENCE spans to simplify trace\n // hierarchy: MODEL_GENERATION is exported as the single `gen_ai.chat` span.\n // We store them in skippedSpans to preserve parent-child relationships:\n // when a child span references a skipped span as parent, resolveParentSpanId()\n // walks up the chain to find the first non-skipped ancestor.\n if (\n exportedSpan.type === SpanType.MODEL_CHUNK ||\n exportedSpan.type === SpanType.MODEL_STEP ||\n exportedSpan.type === SpanType.MODEL_INFERENCE\n ) {\n if (type === TracingEventType.SPAN_STARTED) {\n this.skippedSpans.set(exportedSpan.id, exportedSpan.parentSpanId || '');\n } else if (type === TracingEventType.SPAN_ENDED) {\n this.skippedSpans.delete(exportedSpan.id);\n }\n return;\n }\n\n switch (type) {\n case TracingEventType.SPAN_STARTED:\n await this.handleSpanStarted(exportedSpan);\n break;\n case TracingEventType.SPAN_UPDATED:\n await this.handleSpanUpdated(exportedSpan);\n break;\n case TracingEventType.SPAN_ENDED:\n await this.handleSpanEnded(exportedSpan);\n break;\n }\n }\n\n private handleEventSpan(span: AnyExportedSpan): void {\n Sentry.addBreadcrumb({\n type: 'default',\n category: span.type,\n message: span.name,\n level: span.errorInfo ? 'error' : 'info',\n data: {\n spanId: span.id,\n traceId: span.traceId,\n ...(span.input && { input: this.serializeValue(span.input) }),\n ...(span.output && { output: this.serializeValue(span.output) }),\n ...(span.metadata && { metadata: span.metadata }),\n ...(span.attributes && { attributes: span.attributes }),\n },\n timestamp: span.startTime.getTime() / 1000,\n });\n }\n\n private async handleSpanStarted(span: AnyExportedSpan): Promise<void> {\n const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);\n\n const links = toSentryLinks(span.links);\n const sentrySpan = Sentry.startInactiveSpan({\n op: this.getOperationType(span),\n name: getGenAISpanName(span, this.genAIOptions(span)),\n startTime: span.startTime.getTime(),\n forceTransaction: span.isRootSpan,\n parentSpan: resolvedParentId ? this.spanMap.get(resolvedParentId)?.span : undefined,\n ...(links.length > 0 ? { links } : {}),\n });\n\n sentrySpan.setAttributes(this.buildSpanAttributes(span));\n\n this.spanMap.set(span.id, {\n span: sentrySpan,\n spanType: span.type,\n ...(span.links?.length\n ? { startLinkKeys: new Set(span.links.map(link => `${link.traceId}:${link.spanId}`)) }\n : {}),\n });\n\n // Track tool calls as children of MODEL_GENERATION spans for gen_ai.response.tool_calls attribute\n if ((span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) && resolvedParentId) {\n this.trackToolCallForParent(span, resolvedParentId);\n }\n }\n\n private async handleSpanUpdated(span: AnyExportedSpan): Promise<void> {\n const spanData = this.spanMap.get(span.id);\n if (!spanData) {\n this.logMissingSpan(span, 'span update');\n return;\n }\n // Attributes are set on SPAN_STARTED and finalized on SPAN_ENDED.\n // If dynamic updates become necessary, add spanData.span.setAttributes() here.\n }\n\n private async handleSpanEnded(span: AnyExportedSpan): Promise<void> {\n const spanData = this.spanMap.get(span.id);\n if (!spanData) {\n this.logMissingSpan(span, 'span end');\n return;\n }\n\n const { span: sentrySpan } = spanData;\n\n sentrySpan.setAttributes(this.buildSpanAttributes(span));\n\n if (span.type === SpanType.MODEL_GENERATION) {\n // Set gen_ai.response.tool_calls if this generation had tool calls\n this.applyToolCallsAttribute(spanData);\n\n const resolvedParentId = this.resolveParentSpanId(span.parentSpanId);\n if (resolvedParentId) {\n const parentData = this.spanMap.get(resolvedParentId);\n if (parentData?.spanType === SpanType.AGENT_RUN) {\n const modelAttr = span.attributes as ModelGenerationAttributes;\n parentData.generation = {\n model: modelAttr.model,\n output: span.output,\n usage: modelAttr.usage,\n };\n }\n }\n }\n\n if (span.type === SpanType.AGENT_RUN) {\n // Apply token usage from the single child MODEL_GENERATION span\n // (there is only ever one MODEL_GENERATION span per AGENT_RUN)\n this.applyUsageFromGeneration(spanData);\n\n this.setGenerationResponseAttributes(spanData);\n }\n\n if (span.errorInfo) {\n sentrySpan.setStatus({\n code: 2,\n message: span.errorInfo.message,\n });\n\n // Build an Error instance so Sentry can use the real stack trace captured\n // by observability rather than synthesizing one from this exporter's call site.\n // Passing a string to Sentry.captureException produces a stack that points to\n // handleSpanEnded, hiding the real error origin.\n const error = new Error(span.errorInfo.message);\n if (span.errorInfo.name) {\n error.name = span.errorInfo.name;\n }\n if (span.errorInfo.stack) {\n error.stack = span.errorInfo.stack;\n }\n\n Sentry.captureException(error, {\n contexts: {\n trace: { trace_id: span.traceId, span_id: span.id },\n span_info: {\n name: span.name,\n type: span.type,\n error_id: span.errorInfo.id,\n error_category: span.errorInfo.category,\n },\n },\n });\n }\n\n // Links set after the span started, such as an MCP tool call's link to the\n // server span that handled it\n const lateLinks = toSentryLinks(\n span.links?.filter(link => !spanData.startLinkKeys?.has(`${link.traceId}:${link.spanId}`)),\n );\n if (lateLinks.length > 0 && typeof sentrySpan.addLinks === 'function') {\n sentrySpan.addLinks(lateLinks);\n }\n\n const endTime = span.endTime ? span.endTime.getTime() : undefined;\n sentrySpan.end(endTime);\n this.spanMap.delete(span.id);\n }\n\n // ============================================================================\n // Span Creation Helpers\n // ============================================================================\n\n private resolveParentSpanId(parentSpanId: string | undefined): string | undefined {\n if (!parentSpanId) return undefined;\n\n let currentParentId: string | undefined = parentSpanId;\n while (currentParentId && this.skippedSpans.has(currentParentId)) {\n currentParentId = this.skippedSpans.get(currentParentId);\n if (!currentParentId) break;\n }\n\n return currentParentId;\n }\n\n /**\n * MODEL_GENERATION is Sentry's `gen_ai.chat` span (steps and inference are\n * skipped), so it always takes the model-call GenAI attributes.\n */\n private genAIOptions(span: AnyExportedSpan): GenAISemanticsOptions {\n return { modelCall: span.type === SpanType.MODEL_GENERATION };\n }\n\n private getOperationType(span: AnyExportedSpan): string {\n const config = SPAN_TYPE_CONFIG[span.type];\n return config ? config.opType : 'ai.span';\n }\n\n private buildSpanAttributes(span: AnyExportedSpan): Record<string, any> {\n const attributes = getGenAIAttributes(span, this.genAIOptions(span)) as Record<string, any>;\n\n attributes[ATTRIBUTE_KEYS.SPAN_TYPE] = span.type;\n attributes[ATTRIBUTE_KEYS.ORIGIN] = 'auto.ai.mastra';\n\n if (span.metadata) {\n Object.entries(span.metadata).forEach(([key, value]) => {\n if (value !== undefined && value !== null && key !== 'langfuse') {\n attributes[`metadata.${key}`] = this.serializeValue(value);\n }\n });\n }\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.TAGS, span.tags?.join(','));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.GEN_AI_CONVERSATION_ID, span.metadata?.threadId);\n\n this.addInputOutputAttributes(attributes, span);\n\n if (span.type === SpanType.MODEL_GENERATION) {\n this.addModelGenerationAttributes(attributes, span);\n }\n\n if (span.type === SpanType.TOOL_CALL || span.type === SpanType.PROVIDER_TOOL_CALL) {\n this.addToolCallAttributes(attributes, span);\n }\n\n if (span.type === SpanType.AGENT_RUN) {\n this.addAgentRunAttributes(attributes, span);\n }\n\n if (span.type === SpanType.WORKFLOW_RUN) {\n const workflowAttr = span.attributes as WorkflowRunAttributes;\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_ID, this.getEntityName(span));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STATUS, workflowAttr.status);\n }\n\n if (span.type === SpanType.WORKFLOW_STEP) {\n const stepAttr = span.attributes as WorkflowStepAttributes;\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STEP_ID, this.getEntityName(span));\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.WORKFLOW_STEP_STATUS, stepAttr.status);\n }\n\n return attributes;\n }\n\n // ============================================================================\n // Sentry-Specific Attribute Formatters\n // ============================================================================\n\n /**\n * Adds Sentry-specific input/output attributes that complement GenAI semantic conventions.\n * Adds 'input' and 'output' keys for Sentry UI compatibility.\n */\n private addInputOutputAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n if (span.input !== undefined) {\n attributes[ATTRIBUTE_KEYS.INPUT] = this.serializeValue(span.input);\n }\n\n if (span.output !== undefined) {\n attributes[ATTRIBUTE_KEYS.OUTPUT] = this.serializeValue(span.output);\n\n // Extract text for MODEL_GENERATION spans\n if (span.type === SpanType.MODEL_GENERATION) {\n const outputText = this.extractOutputText(span.output);\n if (outputText) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TEXT] = outputText;\n }\n }\n }\n }\n\n /**\n * Adds Sentry-specific MODEL_GENERATION attributes that complement GenAI semantic conventions.\n */\n private addModelGenerationAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const modelAttr = span.attributes as ModelGenerationAttributes;\n\n if (modelAttr.streaming !== undefined) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_REQUEST_STREAM] = modelAttr.streaming;\n attributes[ATTRIBUTE_KEYS.GEN_AI_RESPONSE_STREAMING] = modelAttr.streaming;\n }\n\n this.setAttributeIfDefined(\n attributes,\n ATTRIBUTE_KEYS.GEN_AI_COMPLETION_START_TIME,\n modelAttr.completionStartTime?.toISOString(),\n );\n\n if (modelAttr.usage) {\n const totalTokens = (modelAttr.usage.inputTokens || 0) + (modelAttr.usage.outputTokens || 0);\n if (totalTokens > 0) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_USAGE_TOTAL_TOKENS] = totalTokens;\n }\n }\n }\n\n /**\n * Adds Sentry-specific TOOL_CALL attributes that complement GenAI semantic conventions.\n */\n private addToolCallAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const toolAttr = span.attributes as ToolCallAttributes;\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.TOOL_SUCCESS, toolAttr.success);\n this.setAttributeIfDefined(\n attributes,\n ATTRIBUTE_KEYS.GEN_AI_TOOL_CALL_ID,\n toolAttr.toolCallId ?? span.metadata?.toolCallId,\n );\n }\n\n /**\n * Adds Sentry-specific AGENT_RUN attributes that complement GenAI semantic conventions.\n */\n private addAgentRunAttributes(attributes: Record<string, any>, span: AnyExportedSpan): void {\n const agentAttr = span.attributes as AgentRunAttributes;\n\n const agentName = this.getEntityName(span);\n if (agentName) {\n attributes[ATTRIBUTE_KEYS.GEN_AI_PIPELINE_NAME] = agentName;\n }\n\n this.setAttributeIfDefined(attributes, ATTRIBUTE_KEYS.GEN_AI_AGENT_PROMPT, agentAttr.prompt);\n }\n\n // ============================================================================\n // Token Usage Management\n // ============================================================================\n\n /**\n * Applies token usage from the MODEL_GENERATION span to the AGENT_RUN span attributes.\n * Reads usage directly from the generation field.\n * Called when AGENT_RUN spans end to set gen_ai.usage.* attributes.\n */\n private applyUsageFromGeneration(spanData: SpanData): void {\n const usage = spanData.generation?.usage;\n if (!usage) return;\n\n const inputTokens = usage.inputTokens || 0;\n const outputTokens = usage.outputTokens || 0;\n\n if (inputTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_INPUT_TOKENS, inputTokens);\n }\n if (outputTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);\n }\n\n const totalTokens = inputTokens + outputTokens;\n if (totalTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);\n }\n\n const cacheReadTokens = usage.inputDetails?.cacheRead || 0;\n const cacheWriteTokens = usage.inputDetails?.cacheWrite || 0;\n const reasoningTokens = usage.outputDetails?.reasoning || 0;\n\n if (cacheReadTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_CACHE_READ_TOKENS, cacheReadTokens);\n }\n if (cacheWriteTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_CACHE_WRITE_TOKENS, cacheWriteTokens);\n }\n if (reasoningTokens > 0) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_USAGE_REASONING_TOKENS, reasoningTokens);\n }\n }\n\n /**\n * Sets gen_ai.response.model and gen_ai.response.text from the MODEL_GENERATION.\n * Only applies to AGENT_RUN spans.\n */\n private setGenerationResponseAttributes(spanData: SpanData): void {\n if (!spanData.generation) return;\n\n if (spanData.generation.model) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_MODEL, spanData.generation.model);\n }\n\n if (spanData.generation.output) {\n const outputText = this.extractOutputText(spanData.generation.output);\n if (outputText) {\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TEXT, outputText);\n }\n }\n }\n\n /**\n * Tracks a TOOL_CALL span as a child of its parent MODEL_GENERATION span.\n * This builds the tool_calls array for gen_ai.response.tool_calls attribute.\n */\n private trackToolCallForParent(span: AnyExportedSpan, parentId: string): void {\n const parentSpanData = this.spanMap.get(parentId);\n if (!parentSpanData || parentSpanData.spanType !== SpanType.MODEL_GENERATION) {\n return;\n }\n\n const toolAttr = span.attributes as ToolCallAttributes;\n if (!parentSpanData.toolCalls) {\n parentSpanData.toolCalls = [];\n }\n\n parentSpanData.toolCalls.push({\n name: this.getEntityName(span),\n id: toolAttr.toolCallId ?? span.metadata?.toolCallId,\n type: toolAttr.toolType || 'function',\n });\n }\n\n /**\n * Applies the gen_ai.response.tool_calls attribute to MODEL_GENERATION spans.\n * Called when MODEL_GENERATION spans end if they have child tool calls.\n */\n private applyToolCallsAttribute(spanData: SpanData): void {\n if (!spanData.toolCalls || spanData.toolCalls.length === 0) {\n return;\n }\n\n spanData.span.setAttribute(ATTRIBUTE_KEYS.GEN_AI_RESPONSE_TOOL_CALLS, JSON.stringify(spanData.toolCalls));\n }\n\n // ============================================================================\n // Utility Helpers\n // ============================================================================\n\n private logMissingSpan(span: AnyExportedSpan, operation: string): void {\n this.logger.warn(`Sentry exporter: No Sentry span found for ${operation}`, {\n traceId: span.traceId,\n spanId: span.id,\n spanName: span.name,\n });\n }\n\n private getEntityName(span: AnyExportedSpan): string {\n return span.entityName || span.entityId || 'unknown';\n }\n\n private extractOutputText(output: any): string | undefined {\n if (!output) return undefined;\n if (typeof output === 'string') return output;\n if (output.text && typeof output.text === 'string') return output.text;\n if (output.content && typeof output.content === 'string') return output.content;\n if (output.message?.content && typeof output.message.content === 'string') return output.message.content;\n return undefined;\n }\n\n private serializeValue(value: any): any {\n if (value === null || value === undefined) return value;\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return value;\n }\n\n private setAttributeIfDefined(attributes: Record<string, any>, key: string, value: any): void {\n if (value !== undefined && value !== null) {\n attributes[key] = value;\n }\n }\n\n // ============================================================================\n // Flush and Shutdown\n // ============================================================================\n\n /**\n * Force flush any buffered spans without shutting down the exporter.\n * This is useful in serverless environments where you need to ensure spans\n * are exported before the runtime instance is terminated.\n */\n async flush(): Promise<void> {\n if (!this.initialized) return;\n\n try {\n // Sentry.flush() sends any pending events to Sentry\n // The timeout is in milliseconds\n await Sentry.flush(2000);\n this.logger.debug('Sentry exporter: Flushed pending events');\n } catch (error) {\n this.logger.error('Sentry exporter: Error flushing events', { error });\n }\n }\n\n async shutdown(): Promise<void> {\n for (const [spanId, spanData] of this.spanMap.entries()) {\n try {\n spanData.span.end();\n } catch (error) {\n this.logger.error('Sentry exporter: Error ending span during shutdown', { spanId, error });\n }\n }\n\n this.spanMap.clear();\n this.skippedSpans.clear();\n\n if (this.initialized) {\n await Sentry.close(2000);\n }\n\n await super.shutdown();\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,YAAY,EAQb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAoB,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAEvC,KAAK,YAAY,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,GAAG,SAAS,EAAE,YAAY,CAAC,CAAC,GACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAIzC;AAiED,MAAM,WAAW,oBAAqB,SAAQ,kBAAkB;IAE9D,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;CACvC;AA2BD,qBAAa,cAAe,SAAQ,YAAY;IAC9C,IAAI,SAAY;IAChB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,WAAW,CAAS;IAE5B,YAAY,MAAM,GAAE,oBAAyB,EA8B5C;IAMD,UAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCtE;IAED,OAAO,CAAC,eAAe;YAkBT,iBAAiB;YAwBjB,iBAAiB;YAUjB,eAAe;IA6E7B,OAAO,CAAC,mBAAmB;IAY3B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,mBAAmB;IAkD3B;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAkBhC;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAsBpC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAe7B;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAkChC;;;OAGG;IACH,OAAO,CAAC,+BAA+B;IAevC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAkB9B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,qBAAqB;IAU7B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAW3B;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAiB9B;CACF"}
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,YAAY,EAQb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAoB,MAAM,4BAA4B,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAEvC,KAAK,YAAY,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,GAAG,SAAS,EAAE,YAAY,CAAC,CAAC,GACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAIzC;AAiED,MAAM,WAAW,oBAAqB,SAAQ,kBAAkB;IAE9D,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;CACvC;AAoCD,qBAAa,cAAe,SAAQ,YAAY;IAC9C,IAAI,SAAY;IAChB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,WAAW,CAAS;IAE5B,YAAY,MAAM,GAAE,oBAAyB,EA8B5C;IAMD,UAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCtE;IAED,OAAO,CAAC,eAAe;YAkBT,iBAAiB;YA6BjB,iBAAiB;YAUjB,eAAe;IAsF7B,OAAO,CAAC,mBAAmB;IAY3B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,mBAAmB;IAkD3B;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAkBhC;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAsBpC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAe7B;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAkChC;;;OAGG;IACH,OAAO,CAAC,+BAA+B;IAevC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAkB9B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,qBAAqB;IAU7B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAW3B;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAiB9B;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/sentry",
3
- "version": "1.2.25",
3
+ "version": "1.2.26-alpha.1",
4
4
  "description": "Sentry AI observability exporter for Mastra",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -24,8 +24,8 @@
24
24
  "license": "Apache-2.0",
25
25
  "dependencies": {
26
26
  "@sentry/node": "^10.68.0",
27
- "@mastra/observability": "1.19.0",
28
- "@mastra/otel-exporter": "1.4.6"
27
+ "@mastra/observability": "1.20.0-alpha.0",
28
+ "@mastra/otel-exporter": "1.4.7-alpha.1"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "22.20.1",
@@ -37,7 +37,7 @@
37
37
  "vitest": "4.1.11",
38
38
  "@internal/lint": "0.0.142",
39
39
  "@internal/types-builder": "0.0.117",
40
- "@mastra/core": "1.76.0"
40
+ "@mastra/core": "1.77.0-alpha.3"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "@mastra/core": ">=1.16.0-0 <2.0.0-0"