@mastra/datadog 1.0.0-beta.2 → 1.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @mastra/datadog
2
2
 
3
+ ## 1.0.0-beta.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Make Datadog exporter zero-config compatible ([#11816](https://github.com/mastra-ai/mastra/pull/11816))
8
+
9
+ The Datadog exporter can now be instantiated without any configuration by reading credentials from environment variables:
10
+ - `DD_LLMOBS_ML_APP` - ML application name
11
+ - `DD_API_KEY` - Datadog API key
12
+ - `DD_SITE` - Datadog site (defaults to `datadoghq.com`)
13
+ - `DD_ENV` - Environment name
14
+
15
+ ```typescript
16
+ // Zero-config usage - reads from environment variables
17
+ const exporter = new DatadogExporter();
18
+ ```
19
+
20
+ - Fixed missing peer dependency warnings for `@openfeature/core` and `@openfeature/server-sdk` ([#11966](https://github.com/mastra-ai/mastra/pull/11966))
21
+
22
+ Added `@openfeature/core` and `@openfeature/server-sdk` as optional peer dependencies to resolve warnings that occur during installation. These are transitive dependencies from `dd-trace` and are now properly declared.
23
+
24
+ **Troubleshooting documentation added:**
25
+ - Native module ABI mismatch errors (Node.js version compatibility with `dd-trace`)
26
+ - Bundler externals configuration for `dd-trace` and native modules
27
+
28
+ - Updated dependencies [[`ebae12a`](https://github.com/mastra-ai/mastra/commit/ebae12a2dd0212e75478981053b148a2c246962d), [`c61a0a5`](https://github.com/mastra-ai/mastra/commit/c61a0a5de4904c88fd8b3718bc26d1be1c2ec6e7), [`69136e7`](https://github.com/mastra-ai/mastra/commit/69136e748e32f57297728a4e0f9a75988462f1a7), [`449aed2`](https://github.com/mastra-ai/mastra/commit/449aed2ba9d507b75bf93d427646ea94f734dfd1), [`eb648a2`](https://github.com/mastra-ai/mastra/commit/eb648a2cc1728f7678768dd70cd77619b448dab9), [`0131105`](https://github.com/mastra-ai/mastra/commit/0131105532e83bdcbb73352fc7d0879eebf140dc), [`9d5059e`](https://github.com/mastra-ai/mastra/commit/9d5059eae810829935fb08e81a9bb7ecd5b144a7), [`ef756c6`](https://github.com/mastra-ai/mastra/commit/ef756c65f82d16531c43f49a27290a416611e526), [`b00ccd3`](https://github.com/mastra-ai/mastra/commit/b00ccd325ebd5d9e37e34dd0a105caae67eb568f), [`3bdfa75`](https://github.com/mastra-ai/mastra/commit/3bdfa7507a91db66f176ba8221aa28dd546e464a), [`e770de9`](https://github.com/mastra-ai/mastra/commit/e770de941a287a49b1964d44db5a5763d19890a6), [`52e2716`](https://github.com/mastra-ai/mastra/commit/52e2716b42df6eff443de72360ae83e86ec23993), [`27b4040`](https://github.com/mastra-ai/mastra/commit/27b4040bfa1a95d92546f420a02a626b1419a1d6), [`610a70b`](https://github.com/mastra-ai/mastra/commit/610a70bdad282079f0c630e0d7bb284578f20151), [`8dc7f55`](https://github.com/mastra-ai/mastra/commit/8dc7f55900395771da851dc7d78d53ae84fe34ec), [`8379099`](https://github.com/mastra-ai/mastra/commit/8379099fc467af6bef54dd7f80c9bd75bf8bbddf), [`b06be72`](https://github.com/mastra-ai/mastra/commit/b06be7223d5ef23edc98c01a67ef713c6cc039f9), [`8c0ec25`](https://github.com/mastra-ai/mastra/commit/8c0ec25646c8a7df253ed1e5ff4863a0d3f1316c), [`ff4d9a6`](https://github.com/mastra-ai/mastra/commit/ff4d9a6704fc87b31a380a76ed22736fdedbba5a), [`69821ef`](https://github.com/mastra-ai/mastra/commit/69821ef806482e2c44e2197ac0b050c3fe3a5285), [`1ed5716`](https://github.com/mastra-ai/mastra/commit/1ed5716830867b3774c4a1b43cc0d82935f32b96), [`4186bdd`](https://github.com/mastra-ai/mastra/commit/4186bdd00731305726fa06adba0b076a1d50b49f), [`7aaf973`](https://github.com/mastra-ai/mastra/commit/7aaf973f83fbbe9521f1f9e7a4fd99b8de464617)]:
29
+ - @mastra/core@1.0.0-beta.22
30
+ - @mastra/observability@1.0.0-beta.11
31
+
3
32
  ## 1.0.0-beta.2
4
33
 
5
34
  ### Minor Changes
package/README.md CHANGED
@@ -10,6 +10,7 @@ pnpm add @mastra/datadog
10
10
 
11
11
  ## Requirements
12
12
 
13
+ - **Node.js >=22.13.0** (Node.js 22.x recommended; `dd-trace` native modules ship prebuilt binaries for this ABI)
13
14
  - Datadog account with LLM Observability enabled
14
15
  - Datadog API key (available in your Datadog account settings)
15
16
 
@@ -98,6 +99,38 @@ All unmapped span types (including `MODEL_CHUNK`, `GENERIC`, etc., and future sp
98
99
  - **Error tracking**: Error spans include error tags with message, ID, and category
99
100
  - **Parent/child hierarchy**: Spans are emitted parent-first to preserve trace trees in Datadog
100
101
 
102
+ ## Troubleshooting
103
+
104
+ ### Native module ABI errors
105
+
106
+ If you see errors like `No native build was found for runtime=node abi=137`:
107
+
108
+ These are non-blocking warnings. The `dd-trace` native modules (`@datadog/native-metrics`, etc.) are **optional** and provide performance monitoring features. Core tracing works without them.
109
+
110
+ **Options:**
111
+
112
+ 1. **Use Node.js 22.x** - Prebuilt binaries for `dd-trace` native modules target Node.js 22 (ABI 127/131). Newer Node.js versions have different ABIs.
113
+ 2. **Ignore the errors** - These are warnings, not fatal errors. LLM observability tracing functions normally without native modules.
114
+
115
+ ### Bundler configuration
116
+
117
+ When using bundlers, mark `dd-trace` and native modules as external:
118
+
119
+ ```typescript
120
+ // src/mastra/index.ts
121
+ export const mastra = new Mastra({
122
+ bundler: {
123
+ externals: [
124
+ 'dd-trace',
125
+ '@datadog/native-metrics',
126
+ '@datadog/native-appsec',
127
+ '@datadog/native-iast-taint-tracking',
128
+ '@datadog/pprof',
129
+ ],
130
+ },
131
+ });
132
+ ```
133
+
101
134
  ## License
102
135
 
103
136
  Apache-2.0
package/dist/index.cjs CHANGED
@@ -132,29 +132,32 @@ var DatadogExporter = class extends observability.BaseExporter {
132
132
  traceState = /* @__PURE__ */ new Map();
133
133
  constructor(config = {}) {
134
134
  super(config);
135
- const mlApp = config.mlApp || process.env.DD_LLMOBS_ML_APP;
136
- const apiKey = config.apiKey || process.env.DD_API_KEY;
137
- const site = config.site || process.env.DD_SITE || "datadoghq.com";
135
+ const mlApp = config.mlApp ?? process.env.DD_LLMOBS_ML_APP;
136
+ const apiKey = config.apiKey ?? process.env.DD_API_KEY;
137
+ const site = config.site ?? process.env.DD_SITE ?? "datadoghq.com";
138
+ const env = config.env ?? process.env.DD_ENV;
138
139
  const envAgentless = process.env.DD_LLMOBS_AGENTLESS_ENABLED?.toLowerCase();
139
140
  const agentless = config.agentless ?? (envAgentless === "false" || envAgentless === "0" ? false : true);
140
141
  if (!mlApp) {
141
- this.setDisabled("Missing required mlApp (set config.mlApp or DD_LLMOBS_ML_APP)");
142
+ this.setDisabled(`Missing required mlApp. Set DD_LLMOBS_ML_APP environment variable or pass mlApp in config.`);
142
143
  this.config = config;
143
144
  return;
144
145
  }
145
146
  if (agentless && !apiKey) {
146
- this.setDisabled("Missing required apiKey (set config.apiKey or DD_API_KEY)");
147
+ this.setDisabled(
148
+ `Missing required apiKey for agentless mode. Set DD_API_KEY environment variable or pass apiKey in config.`
149
+ );
147
150
  this.config = config;
148
151
  return;
149
152
  }
150
- this.config = { ...config, mlApp, site, apiKey, agentless };
153
+ this.config = { ...config, mlApp, site, apiKey, agentless, env };
151
154
  ensureTracer({
152
155
  mlApp,
153
156
  site,
154
157
  apiKey,
155
158
  agentless,
156
159
  service: config.service,
157
- env: config.env,
160
+ env,
158
161
  integrationsEnabled: config.integrationsEnabled
159
162
  });
160
163
  this.logger.info("Datadog exporter initialized", { mlApp, site, agentless });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/metrics.ts","../src/utils.ts","../src/tracing.ts"],"names":["SpanType","tracer","BaseExporter","omitKeys"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { UsageStats } from '@mastra/core/observability';\nimport type tracer from 'dd-trace';\n\ntype DatadogAnnotationMetrics = tracer.llmobs.AnnotationOptions['metrics'];\n\nexport function formatUsageMetrics(usage?: UsageStats): DatadogAnnotationMetrics | undefined {\n if (!usage) return undefined;\n\n const result: DatadogAnnotationMetrics = {};\n\n const inputTokens = usage.inputTokens;\n if (inputTokens !== undefined) result.inputTokens = inputTokens;\n\n const outputTokens = usage.outputTokens;\n if (outputTokens !== undefined) result.outputTokens = outputTokens;\n\n if (inputTokens !== undefined && outputTokens !== undefined) {\n result.totalTokens = inputTokens + outputTokens;\n }\n\n if (usage?.outputDetails?.reasoning !== undefined) {\n result.reasoningTokens = usage.outputDetails.reasoning;\n }\n\n const cachedTokens = usage?.inputDetails?.cacheRead;\n if (cachedTokens !== undefined) {\n result.cachedInputTokens = cachedTokens;\n }\n\n const cachedOutputTokens = usage?.inputDetails?.cacheWrite;\n if (cachedOutputTokens !== undefined) {\n result.cachedOutputTokens = cachedOutputTokens;\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n","/**\n * Utility functions for Datadog LLM Observability Exporter\n */\n\nimport { SpanType } from '@mastra/core/observability';\nimport tracer from 'dd-trace';\n\n/**\n * Datadog LLM Observability span kinds.\n */\nexport type DatadogSpanKind = 'llm' | 'agent' | 'workflow' | 'tool' | 'task' | 'retrieval' | 'embedding';\n\n/**\n * Maps Mastra SpanTypes to Datadog LLMObs span kinds.\n * Only non-task mappings are defined; unmapped types fall back to 'task'.\n */\nexport const SPAN_TYPE_TO_KIND: Partial<Record<SpanType, DatadogSpanKind>> = {\n [SpanType.AGENT_RUN]: 'agent',\n [SpanType.MODEL_GENERATION]: 'workflow',\n [SpanType.MODEL_STEP]: 'llm',\n [SpanType.TOOL_CALL]: 'tool',\n [SpanType.MCP_TOOL_CALL]: 'tool',\n [SpanType.WORKFLOW_RUN]: 'workflow',\n};\n\n/**\n * Singleton flag to prevent multiple tracer initializations.\n * dd-trace should only be initialized once per process.\n */\nconst tracerInitFlag = { done: false };\n\n/**\n * Ensures dd-trace is initialized exactly once.\n * Respects any existing tracer initialization by the application.\n */\nexport function ensureTracer(config: {\n mlApp: string;\n site: string;\n apiKey?: string;\n agentless: boolean;\n service?: string;\n env?: string;\n integrationsEnabled?: boolean;\n}): void {\n if (tracerInitFlag.done) return;\n\n // Set environment variables for dd-trace to pick up\n // (LLMObsEnableOptions only accepts mlApp and agentlessEnabled)\n // Always set when config is provided to ensure explicit config takes precedence\n // over any stale env vars that may already be set in the process\n if (config.site) {\n process.env.DD_SITE = config.site;\n }\n if (config.apiKey) {\n process.env.DD_API_KEY = config.apiKey;\n }\n\n // Check if tracer was already started by the application\n const alreadyStarted = (tracer as any)._tracer?.started;\n\n if (!alreadyStarted) {\n tracer.init({\n service: config.service || config.mlApp,\n env: config.env || process.env.DD_ENV,\n // Disable automatic integrations by default to avoid surprise instrumentation\n plugins: config.integrationsEnabled ?? false,\n });\n }\n\n // Enable LLM Observability with the resolved configuration\n tracer.llmobs.enable({\n mlApp: config.mlApp,\n agentlessEnabled: config.agentless,\n });\n\n tracerInitFlag.done = true;\n}\n\n/**\n * Returns the Datadog kind for a Mastra span type.\n */\nexport function kindFor(spanType: SpanType): DatadogSpanKind {\n return SPAN_TYPE_TO_KIND[spanType] || 'task';\n}\n\n/**\n * Converts a value to a Date object.\n */\nexport function toDate(value: Date | string | number): Date {\n return value instanceof Date ? value : new Date(value);\n}\n\n/**\n * Safely stringifies data, handling circular references.\n */\nexport function safeStringify(data: unknown): string {\n try {\n return JSON.stringify(data);\n } catch {\n if (typeof data === 'object' && data !== null) {\n return `[Non-serializable ${data.constructor?.name || 'Object'}]`;\n }\n return String(data);\n }\n}\n\n/**\n * Checks if data is already in message array format ({role, content}[]).\n */\nfunction isMessageArray(data: any): data is Array<{ role: string; content: any }> {\n return Array.isArray(data) && data.every(m => m?.role && m?.content !== undefined);\n}\n\n/**\n * Formats input data for Datadog annotations.\n * LLM spans use message array format; others use raw or stringified data.\n */\nexport function formatInput(input: any, spanType: SpanType): any {\n // LLM spans expect {role, content}[] format\n if (spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP) {\n // Already in message format\n if (isMessageArray(input)) {\n return input.map(m => ({\n role: m.role,\n content: typeof m.content === 'string' ? m.content : safeStringify(m.content),\n }));\n }\n // String input becomes user message\n if (typeof input === 'string') {\n return [{ role: 'user', content: input }];\n }\n // Object input gets stringified as user message\n return [{ role: 'user', content: safeStringify(input) }];\n }\n\n // Non-LLM spans: pass through strings/arrays, stringify objects\n if (typeof input === 'string' || Array.isArray(input)) return input;\n return safeStringify(input);\n}\n\n/**\n * Formats output data for Datadog annotations.\n * LLM spans use message array format; others use raw or stringified data.\n */\nexport function formatOutput(output: any, spanType: SpanType): any {\n // LLM spans expect {role, content}[] format\n if (spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP) {\n // Already in message format\n if (isMessageArray(output)) {\n return output.map(m => ({\n role: m.role,\n content: typeof m.content === 'string' ? m.content : safeStringify(m.content),\n }));\n }\n // String output becomes assistant message\n if (typeof output === 'string') {\n return [{ role: 'assistant', content: output }];\n }\n // Object with text property (common AI SDK format)\n if (output?.text) {\n return [{ role: 'assistant', content: output.text }];\n }\n // Other objects get stringified as assistant message\n return [{ role: 'assistant', content: safeStringify(output) }];\n }\n\n // Non-LLM spans: pass through strings, stringify objects\n if (typeof output === 'string') return output;\n return safeStringify(output);\n}\n","/**\n * Datadog LLM Observability Exporter for Mastra\n *\n * Exports Mastra observability data to Datadog's LLM Observability product.\n * Uses a completion-only pattern where spans are emitted on span_ended events.\n *\n * Key features:\n * - Maps Mastra span types to Datadog span kinds\n * - Normalizes AI SDK v4/v5 token usage formats\n * - Formats LLM inputs/outputs as message arrays\n * - Flattens metadata into searchable tags\n * - Supports both agent and agentless modes\n */\n\nimport type {\n TracingEvent,\n AnyExportedSpan,\n ModelGenerationAttributes,\n ModelStepAttributes,\n} from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport { omitKeys } from '@mastra/core/utils';\nimport { BaseExporter } from '@mastra/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport tracer from 'dd-trace';\nimport { formatUsageMetrics } from './metrics';\nimport { ensureTracer, kindFor, toDate, formatInput, formatOutput } from './utils';\nimport type { DatadogSpanKind } from './utils';\n\n/**\n * LLMObs span options with required name and kind properties.\n */\ninterface LLMObsSpanOptions {\n kind: DatadogSpanKind;\n name: string;\n sessionId?: string;\n userId?: string;\n mlApp?: string;\n modelName?: string;\n modelProvider?: string;\n startTime?: Date;\n endTime?: Date;\n}\n\n/**\n * Minimal per-trace context for user/session tagging.\n */\ninterface TraceContext {\n userId?: string;\n sessionId?: string;\n}\n\ntype TraceState = {\n buffer: Map<string, AnyExportedSpan>;\n contexts: Map<string, { ddSpan: any; exported?: { traceId: string; spanId: string } }>;\n rootEnded: boolean;\n treeEmitted: boolean; // Whether the initial span tree has been emitted\n createdAt: number;\n cleanupTimer?: ReturnType<typeof setTimeout>;\n maxLifetimeTimer?: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Tree node representing a span and its children for recursive emission.\n */\ninterface SpanNode {\n span: AnyExportedSpan;\n children: SpanNode[];\n}\n\n/**\n * Maximum lifetime for a trace state entry (30 minutes).\n * This is a fallback cleanup mechanism for traces that never receive a root span\n * or have all spans marked as non-root, preventing unbounded memory growth.\n */\nconst MAX_TRACE_LIFETIME_MS = 30 * 60 * 1000;\n\n/**\n * Regular cleanup interval for trace state entries (1 minute).\n */\nconst REGULAR_CLEANUP_INTERVAL_MS = 1 * 60 * 1000;\n\n/**\n * Configuration options for the Datadog LLM Observability exporter.\n */\nexport interface DatadogExporterConfig extends BaseExporterConfig {\n /**\n * Datadog API key. Required (agentless mode is the default).\n * Falls back to DD_API_KEY environment variable.\n */\n apiKey?: string;\n\n /**\n * ML application name for grouping traces.\n * Required - falls back to DD_LLMOBS_ML_APP environment variable.\n */\n mlApp?: string;\n\n /**\n * Datadog site (e.g., 'datadoghq.com', 'datadoghq.eu').\n * Falls back to DD_SITE environment variable, defaults to 'datadoghq.com'.\n */\n site?: string;\n\n /**\n * Service name for the application.\n * Falls back to mlApp if not specified.\n */\n service?: string;\n\n /**\n * Environment name (e.g., 'production', 'staging').\n * Falls back to DD_ENV environment variable.\n */\n env?: string;\n\n /**\n * Use agentless mode (direct HTTPS intake without local Datadog Agent).\n * Defaults to true for consistency with other Mastra exporters.\n * Set to false to use a local Datadog Agent instead.\n * Falls back to DD_LLMOBS_AGENTLESS_ENABLED environment variable.\n */\n agentless?: boolean;\n\n /**\n * Enable dd-trace automatic integrations.\n * Defaults to false to avoid unexpected instrumentation.\n */\n integrationsEnabled?: boolean;\n}\n\n/**\n * Datadog LLM Observability Exporter for Mastra.\n *\n * Exports observability data to Datadog's LLM Observability product using\n * a completion-only pattern where spans are emitted on span_ended events.\n */\nexport class DatadogExporter extends BaseExporter {\n name = 'datadog';\n\n private config: Required<Pick<DatadogExporterConfig, 'mlApp' | 'site'>> & DatadogExporterConfig;\n private traceContext = new Map<string, TraceContext>();\n private traceState = new Map<string, TraceState>();\n\n constructor(config: DatadogExporterConfig = {}) {\n super(config);\n\n // Resolve configuration from config object and environment variables\n const mlApp = config.mlApp || process.env.DD_LLMOBS_ML_APP;\n const apiKey = config.apiKey || process.env.DD_API_KEY;\n const site = config.site || process.env.DD_SITE || 'datadoghq.com';\n\n // Default to agentless mode (true) for consistency with other Mastra exporters\n // Only disable if explicitly set to false via config or env var\n const envAgentless = process.env.DD_LLMOBS_AGENTLESS_ENABLED?.toLowerCase();\n const agentless = config.agentless ?? (envAgentless === 'false' || envAgentless === '0' ? false : true);\n\n // Validate required configuration\n if (!mlApp) {\n this.setDisabled('Missing required mlApp (set config.mlApp or DD_LLMOBS_ML_APP)');\n this.config = config as any;\n return;\n }\n\n if (agentless && !apiKey) {\n this.setDisabled('Missing required apiKey (set config.apiKey or DD_API_KEY)');\n this.config = config as any;\n return;\n }\n\n this.config = { ...config, mlApp, site, apiKey, agentless };\n\n // Initialize tracer and enable LLM Observability\n ensureTracer({\n mlApp,\n site,\n apiKey,\n agentless,\n service: config.service,\n env: config.env,\n integrationsEnabled: config.integrationsEnabled,\n });\n\n this.logger.info('Datadog exporter initialized', { mlApp, site, agentless });\n }\n\n /**\n * Main entry point for tracing events from Mastra.\n */\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (this.isDisabled || !(tracer as any).llmobs) return;\n\n try {\n const span = event.exportedSpan;\n\n // Handle event spans (zero-duration spans) - buffer like regular spans for parent-first emission\n if (span.isEvent) {\n if (event.type === 'span_started') {\n this.captureTraceContext(span);\n this.enqueueSpan(span); // Route through buffer for proper parent context\n }\n return; // Skip span_updated and span_ended for events\n }\n\n // Handle regular spans based on event type\n switch (event.type) {\n case 'span_started':\n this.captureTraceContext(span);\n return;\n\n case 'span_updated':\n // No-op: completion-only pattern ignores mid-span updates\n return;\n\n case 'span_ended':\n this.enqueueSpan(span);\n return;\n }\n } catch (error) {\n this.logger.error('Datadog exporter error', {\n error,\n eventType: event.type,\n spanId: event.exportedSpan?.id,\n spanName: event.exportedSpan?.name,\n });\n }\n }\n\n /**\n * Captures user/session context from root spans for tagging all spans in the trace.\n */\n private captureTraceContext(span: AnyExportedSpan): void {\n if (span.isRootSpan && !this.traceContext.has(span.traceId)) {\n this.traceContext.set(span.traceId, {\n userId: span.metadata?.userId,\n sessionId: span.metadata?.sessionId,\n });\n }\n }\n\n /**\n * Queue span until its parent context is available, then emit spans parent-first.\n */\n private enqueueSpan(span: AnyExportedSpan): void {\n const state = this.getOrCreateTraceState(span.traceId);\n if (span.isRootSpan) {\n state.rootEnded = true;\n }\n\n state.buffer.set(span.id, span);\n this.tryEmitReadySpans(span.traceId);\n }\n\n /**\n * Builds annotations object for llmobs.annotate().\n * Uses dd-trace's expected property names: inputData, outputData, metadata, tags, metrics.\n */\n private buildAnnotations(span: AnyExportedSpan): Record<string, any> {\n const annotations: Record<string, any> = {};\n\n // Format and add input (dd-trace expects 'inputData')\n if (span.input !== undefined) {\n annotations.inputData = formatInput(span.input, span.type);\n }\n\n // Format and add output (dd-trace expects 'outputData')\n if (span.output !== undefined) {\n annotations.outputData = formatOutput(span.output, span.type);\n }\n\n // Add token usage metrics (only on MODEL_GENERATION or MODEL_STEP spans)\n if (span.type === SpanType.MODEL_GENERATION || span.type === SpanType.MODEL_STEP) {\n const usage = (span.attributes as ModelGenerationAttributes | ModelStepAttributes)?.usage;\n const metrics = formatUsageMetrics(usage);\n if (metrics) {\n annotations.metrics = metrics;\n }\n }\n\n // Forward span.attributes to metadata (minus known fields handled separately)\n // This ensures tool/workflow spans preserve custom attributes like other exporters\n const knownFields = ['usage', 'model', 'provider', 'parameters'];\n const otherAttributes = omitKeys((span.attributes ?? {}) as Record<string, any>, knownFields);\n\n // Merge span.metadata + remaining attributes into metadata\n const combinedMetadata = {\n ...span.metadata,\n ...otherAttributes,\n };\n if (Object.keys(combinedMetadata).length > 0) {\n annotations.metadata = combinedMetadata;\n }\n\n // Build tags from span.tags (user-provided string[] converted to object) and error info\n // Datadog annotation tags accept Record<string, any>, so we use proper types\n // The native span error status is also set via ddSpan.setTag('error', true) in emitSpan()\n const tags: Record<string, any> = {};\n\n // Convert span.tags (string[]) to object format - each tag becomes a key with value true\n if (span.tags?.length) {\n for (const tag of span.tags) {\n tags[tag] = true;\n }\n }\n\n // Add error info as consolidated tags\n if (span.errorInfo) {\n tags.error = true;\n tags.errorInfo = {\n message: span.errorInfo.message,\n ...(span.errorInfo.id ? { id: span.errorInfo.id } : {}),\n ...(span.errorInfo.domain ? { domain: span.errorInfo.domain } : {}),\n ...(span.errorInfo.category ? { category: span.errorInfo.category } : {}),\n };\n }\n\n if (Object.keys(tags).length > 0) {\n annotations.tags = tags;\n }\n\n return annotations;\n }\n\n /**\n * Gracefully shuts down the exporter.\n */\n async shutdown(): Promise<void> {\n // Cancel all pending cleanup timers and clear state FIRST\n for (const [traceId, state] of this.traceState) {\n if (state.cleanupTimer) {\n clearTimeout(state.cleanupTimer);\n }\n if (state.maxLifetimeTimer) {\n clearTimeout(state.maxLifetimeTimer);\n }\n if (state.buffer.size > 0) {\n this.logger.warn('Shutdown with pending spans', {\n traceId,\n pendingCount: state.buffer.size,\n spanIds: Array.from(state.buffer.keys()),\n });\n }\n }\n this.traceState.clear();\n\n // Flush any pending data\n if (tracer.llmobs?.flush) {\n try {\n await tracer.llmobs.flush();\n } catch (e) {\n this.logger.error('Error flushing llmobs', { error: e });\n }\n } else if ((tracer as any).flush) {\n try {\n await (tracer as any).flush();\n } catch (e) {\n this.logger.error('Error flushing tracer', { error: e });\n }\n }\n\n // Disable LLM Observability\n if (tracer.llmobs?.disable) {\n try {\n tracer.llmobs.disable();\n } catch (e) {\n this.logger.error('Error disabling llmobs', { error: e });\n }\n }\n\n // Clear local state\n this.traceContext.clear();\n\n await super.shutdown();\n }\n\n /**\n * Retrieve or initialize trace state for buffering and parent tracking.\n */\n private getOrCreateTraceState(traceId: string): TraceState {\n const existing = this.traceState.get(traceId);\n if (existing) {\n if (existing.cleanupTimer) {\n clearTimeout(existing.cleanupTimer);\n existing.cleanupTimer = undefined;\n }\n return existing;\n }\n\n const created: TraceState = {\n buffer: new Map<string, AnyExportedSpan>(),\n contexts: new Map<string, { ddSpan: any; exported?: { traceId: string; spanId: string } }>(),\n rootEnded: false,\n treeEmitted: false,\n createdAt: Date.now(),\n cleanupTimer: undefined,\n maxLifetimeTimer: undefined,\n };\n\n // Schedule fallback cleanup after max lifetime to prevent memory leaks\n // when traces never receive a root span or all spans are non-root\n const maxLifetimeTimer = setTimeout(() => {\n const state = this.traceState.get(traceId);\n if (state) {\n if (state.buffer.size > 0 || state.contexts.size > 0) {\n this.logger.warn('Discarding trace due to max lifetime exceeded', {\n traceId,\n bufferedSpans: state.buffer.size,\n emittedSpans: state.contexts.size,\n lifetimeMs: Date.now() - state.createdAt,\n });\n }\n if (state.cleanupTimer) {\n clearTimeout(state.cleanupTimer);\n }\n this.traceState.delete(traceId);\n this.traceContext.delete(traceId);\n }\n }, MAX_TRACE_LIFETIME_MS);\n // Prevent the timer from keeping the process alive\n (maxLifetimeTimer as any).unref?.();\n created.maxLifetimeTimer = maxLifetimeTimer;\n\n this.traceState.set(traceId, created);\n return created;\n }\n\n /**\n * Attempt to emit spans from the buffer.\n *\n * Two modes of operation:\n * 1. Initial tree emission: When root span ends and tree hasn't been emitted yet,\n * build a tree from all buffered spans and emit recursively using nested\n * llmobs.trace() calls. This ensures proper parent-child relationships in Datadog.\n * 2. Late-arriving spans: After the tree has been emitted, emit individual spans\n * with their parent context for proper linking.\n */\n private tryEmitReadySpans(traceId: string): void {\n const state = this.traceState.get(traceId);\n if (!state) return;\n\n // If tree hasn't been emitted yet, wait for root and emit as tree\n if (!state.treeEmitted) {\n // Wait until the root span has ended before emitting any spans\n if (!state.rootEnded) return;\n\n // Build tree and emit recursively\n const tree = this.buildSpanTree(state.buffer);\n if (tree) {\n this.emitSpanTree(tree, state);\n }\n\n // Clear the buffer and mark tree as emitted\n state.buffer.clear();\n state.treeEmitted = true;\n } else {\n // Tree already emitted - handle late-arriving spans individually\n // Use the old parent-first emission pattern for these\n let emitted = false;\n do {\n emitted = false;\n for (const [spanId, span] of state.buffer) {\n const parentCtx = span.parentSpanId ? state.contexts.get(span.parentSpanId) : undefined;\n if (span.parentSpanId && !parentCtx) {\n continue;\n }\n\n this.emitSingleSpan(span, state, parentCtx?.ddSpan);\n state.buffer.delete(spanId);\n emitted = true;\n }\n } while (emitted);\n }\n\n // Schedule cleanup if root has ended and buffer is empty\n if (state.rootEnded && state.buffer.size === 0 && !state.cleanupTimer) {\n const timer = setTimeout(() => {\n const currentState = this.traceState.get(traceId);\n if (currentState) {\n if (currentState.buffer.size > 0) {\n this.logger.warn('Discarding orphaned spans during cleanup', {\n traceId,\n orphanedCount: currentState.buffer.size,\n spanIds: Array.from(currentState.buffer.keys()),\n });\n }\n // Clear the max lifetime timer since normal cleanup is handling this\n if (currentState.maxLifetimeTimer) {\n clearTimeout(currentState.maxLifetimeTimer);\n }\n }\n this.traceState.delete(traceId);\n this.traceContext.delete(traceId);\n }, REGULAR_CLEANUP_INTERVAL_MS);\n // Prevent the timer from keeping the process alive\n (timer as any).unref?.();\n state.cleanupTimer = timer;\n }\n }\n\n /**\n * Builds a tree structure from buffered spans based on parentSpanId relationships.\n * Returns the root node of the tree, or undefined if no root span is found.\n */\n private buildSpanTree(buffer: Map<string, AnyExportedSpan>): SpanNode | undefined {\n // Create nodes for all spans\n const nodes = new Map<string, SpanNode>();\n let rootNode: SpanNode | undefined;\n\n for (const span of buffer.values()) {\n nodes.set(span.id, { span, children: [] });\n }\n\n // Build parent-child relationships\n for (const node of nodes.values()) {\n if (node.span.isRootSpan) {\n rootNode = node;\n } else if (node.span.parentSpanId) {\n const parentNode = nodes.get(node.span.parentSpanId);\n if (parentNode) {\n parentNode.children.push(node);\n } else {\n // Orphaned span - parent not in buffer, treat as root-level\n // This shouldn't happen normally but handles edge cases\n this.logger.warn('Orphaned span detected during tree build', {\n spanId: node.span.id,\n parentSpanId: node.span.parentSpanId,\n traceId: node.span.traceId,\n });\n }\n }\n }\n\n // Sort children by start time for consistent ordering\n for (const node of nodes.values()) {\n node.children.sort((a, b) => {\n const aTime =\n a.span.startTime instanceof Date ? a.span.startTime.getTime() : new Date(a.span.startTime).getTime();\n const bTime =\n b.span.startTime instanceof Date ? b.span.startTime.getTime() : new Date(b.span.startTime).getTime();\n return aTime - bTime;\n });\n }\n\n return rootNode;\n }\n\n /**\n * Builds LLMObs span options from a Mastra span.\n * Handles trace context, timestamps, and conditional model information for LLM spans.\n */\n private buildSpanOptions(span: AnyExportedSpan): LLMObsSpanOptions {\n const traceCtx = this.traceContext.get(span.traceId) || {\n userId: span.metadata?.userId,\n sessionId: span.metadata?.sessionId,\n };\n\n const kind = kindFor(span.type);\n const attrs = span.attributes as ModelGenerationAttributes | undefined;\n\n const startTime = toDate(span.startTime);\n // Event spans are point-in-time markers; use startTime for endTime if not set (zero duration)\n // Regular spans fall back to current time if endTime is not set\n const endTime = span.endTime ? toDate(span.endTime) : span.isEvent ? startTime : new Date();\n\n return {\n kind,\n name: span.name,\n sessionId: traceCtx.sessionId,\n userId: traceCtx.userId,\n startTime,\n endTime,\n ...(kind === 'llm' && attrs?.model ? { modelName: attrs.model } : {}),\n ...(kind === 'llm' && attrs?.provider ? { modelProvider: attrs.provider } : {}),\n };\n }\n\n /**\n * Recursively emits a span tree using nested llmobs.trace() calls.\n * This ensures parent-child relationships are properly established in Datadog\n * because child spans are created while their parent span is active in scope.\n */\n private emitSpanTree(node: SpanNode, state: TraceState): void {\n const span = node.span;\n const options = this.buildSpanOptions(span);\n\n // Use nested llmobs.trace() calls - children are emitted INSIDE the parent's callback\n // This ensures the Datadog SDK automatically establishes parent-child relationships\n tracer.llmobs.trace(options as any, (ddSpan: any) => {\n // Annotate this span\n const annotations = this.buildAnnotations(span);\n if (Object.keys(annotations).length > 0) {\n tracer.llmobs.annotate(ddSpan, annotations);\n }\n\n // Set native Datadog error status for proper UI highlighting\n if (span.errorInfo) {\n ddSpan.setTag('error', true);\n }\n\n // Store context for potential evaluation submissions\n const exported = tracer.llmobs.exportSpan ? tracer.llmobs.exportSpan(ddSpan) : undefined;\n state.contexts.set(span.id, { ddSpan, exported });\n\n // Recursively emit children INSIDE this span's callback\n // This is the key to establishing proper parent-child relationships\n for (const child of node.children) {\n this.emitSpanTree(child, state);\n }\n });\n }\n\n /**\n * Emit a single span with the proper Datadog parent context.\n * Used for late-arriving spans after the main tree has been emitted.\n */\n private emitSingleSpan(span: AnyExportedSpan, state: TraceState, parent?: any) {\n const options = this.buildSpanOptions(span);\n\n const runTrace = () =>\n tracer.llmobs.trace(options as any, (ddSpan: any) => {\n const annotations = this.buildAnnotations(span);\n if (Object.keys(annotations).length > 0) {\n tracer.llmobs.annotate(ddSpan, annotations);\n }\n\n // Set native Datadog error status for proper UI highlighting\n if (span.errorInfo) {\n ddSpan.setTag('error', true);\n }\n\n const exported = tracer.llmobs.exportSpan ? tracer.llmobs.exportSpan(ddSpan) : undefined;\n state.contexts.set(span.id, { ddSpan, exported });\n });\n\n if (parent) {\n tracer.scope().activate(parent, runTrace);\n } else {\n runTrace();\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/metrics.ts","../src/utils.ts","../src/tracing.ts"],"names":["SpanType","tracer","BaseExporter","omitKeys"],"mappings":";;;;;;;;;;;;;;AAKO,SAAS,mBAAmB,KAAA,EAA0D;AAC3F,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AAEnB,EAAA,MAAM,SAAmC,EAAC;AAE1C,EAAA,MAAM,cAAc,KAAA,CAAM,WAAA;AAC1B,EAAA,IAAI,WAAA,KAAgB,MAAA,EAAW,MAAA,CAAO,WAAA,GAAc,WAAA;AAEpD,EAAA,MAAM,eAAe,KAAA,CAAM,YAAA;AAC3B,EAAA,IAAI,YAAA,KAAiB,MAAA,EAAW,MAAA,CAAO,YAAA,GAAe,YAAA;AAEtD,EAAA,IAAI,WAAA,KAAgB,MAAA,IAAa,YAAA,KAAiB,MAAA,EAAW;AAC3D,IAAA,MAAA,CAAO,cAAc,WAAA,GAAc,YAAA;AAAA,EACrC;AAEA,EAAA,IAAI,KAAA,EAAO,aAAA,EAAe,SAAA,KAAc,MAAA,EAAW;AACjD,IAAA,MAAA,CAAO,eAAA,GAAkB,MAAM,aAAA,CAAc,SAAA;AAAA,EAC/C;AAEA,EAAA,MAAM,YAAA,GAAe,OAAO,YAAA,EAAc,SAAA;AAC1C,EAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,IAAA,MAAA,CAAO,iBAAA,GAAoB,YAAA;AAAA,EAC7B;AAEA,EAAA,MAAM,kBAAA,GAAqB,OAAO,YAAA,EAAc,UAAA;AAChD,EAAA,IAAI,uBAAuB,MAAA,EAAW;AACpC,IAAA,MAAA,CAAO,kBAAA,GAAqB,kBAAA;AAAA,EAC9B;AAEA,EAAA,OAAO,OAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,GAAS,IAAI,MAAA,GAAS,MAAA;AACnD;ACnBO,IAAM,iBAAA,GAAgE;AAAA,EAC3E,CAACA,wBAAA,CAAS,SAAS,GAAG,OAAA;AAAA,EACtB,CAACA,wBAAA,CAAS,gBAAgB,GAAG,UAAA;AAAA,EAC7B,CAACA,wBAAA,CAAS,UAAU,GAAG,KAAA;AAAA,EACvB,CAACA,wBAAA,CAAS,SAAS,GAAG,MAAA;AAAA,EACtB,CAACA,wBAAA,CAAS,aAAa,GAAG,MAAA;AAAA,EAC1B,CAACA,wBAAA,CAAS,YAAY,GAAG;AAC3B,CAAA;AAMA,IAAM,cAAA,GAAiB,EAAE,IAAA,EAAM,KAAA,EAAM;AAM9B,SAAS,aAAa,MAAA,EAQpB;AACP,EAAA,IAAI,eAAe,IAAA,EAAM;AAMzB,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,OAAA,CAAQ,GAAA,CAAI,UAAU,MAAA,CAAO,IAAA;AAAA,EAC/B;AACA,EAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,IAAA,OAAA,CAAQ,GAAA,CAAI,aAAa,MAAA,CAAO,MAAA;AAAA,EAClC;AAGA,EAAA,MAAM,cAAA,GAAkBC,yBAAe,OAAA,EAAS,OAAA;AAEhD,EAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,IAAAA,wBAAA,CAAO,IAAA,CAAK;AAAA,MACV,OAAA,EAAS,MAAA,CAAO,OAAA,IAAW,MAAA,CAAO,KAAA;AAAA,MAClC,GAAA,EAAK,MAAA,CAAO,GAAA,IAAO,OAAA,CAAQ,GAAA,CAAI,MAAA;AAAA;AAAA,MAE/B,OAAA,EAAS,OAAO,mBAAA,IAAuB;AAAA,KACxC,CAAA;AAAA,EACH;AAGA,EAAAA,wBAAA,CAAO,OAAO,MAAA,CAAO;AAAA,IACnB,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,kBAAkB,MAAA,CAAO;AAAA,GAC1B,CAAA;AAED,EAAA,cAAA,CAAe,IAAA,GAAO,IAAA;AACxB;AAKO,SAAS,QAAQ,QAAA,EAAqC;AAC3D,EAAA,OAAO,iBAAA,CAAkB,QAAQ,CAAA,IAAK,MAAA;AACxC;AAKO,SAAS,OAAO,KAAA,EAAqC;AAC1D,EAAA,OAAO,KAAA,YAAiB,IAAA,GAAO,KAAA,GAAQ,IAAI,KAAK,KAAK,CAAA;AACvD;AAKO,SAAS,cAAc,IAAA,EAAuB;AACnD,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,EAC5B,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,EAAM;AAC7C,MAAA,OAAO,CAAA,kBAAA,EAAqB,IAAA,CAAK,WAAA,EAAa,IAAA,IAAQ,QAAQ,CAAA,CAAA,CAAA;AAAA,IAChE;AACA,IAAA,OAAO,OAAO,IAAI,CAAA;AAAA,EACpB;AACF;AAKA,SAAS,eAAe,IAAA,EAA0D;AAChF,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,KAAA,CAAM,CAAA,CAAA,KAAK,CAAA,EAAG,IAAA,IAAQ,CAAA,EAAG,OAAA,KAAY,MAAS,CAAA;AACnF;AAMO,SAAS,WAAA,CAAY,OAAY,QAAA,EAAyB;AAE/D,EAAA,IAAI,QAAA,KAAaD,wBAAA,CAAS,gBAAA,IAAoB,QAAA,KAAaA,yBAAS,UAAA,EAAY;AAE9E,IAAA,IAAI,cAAA,CAAe,KAAK,CAAA,EAAG;AACzB,MAAA,OAAO,KAAA,CAAM,IAAI,CAAA,CAAA,MAAM;AAAA,QACrB,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,OAAA,EAAS,OAAO,CAAA,CAAE,OAAA,KAAY,WAAW,CAAA,CAAE,OAAA,GAAU,aAAA,CAAc,CAAA,CAAE,OAAO;AAAA,OAC9E,CAAE,CAAA;AAAA,IACJ;AAEA,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAAA,IAC1C;AAEA,IAAA,OAAO,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAS,aAAA,CAAc,KAAK,GAAG,CAAA;AAAA,EACzD;AAGA,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,MAAM,OAAA,CAAQ,KAAK,GAAG,OAAO,KAAA;AAC9D,EAAA,OAAO,cAAc,KAAK,CAAA;AAC5B;AAMO,SAAS,YAAA,CAAa,QAAa,QAAA,EAAyB;AAEjE,EAAA,IAAI,QAAA,KAAaA,wBAAA,CAAS,gBAAA,IAAoB,QAAA,KAAaA,yBAAS,UAAA,EAAY;AAE9E,IAAA,IAAI,cAAA,CAAe,MAAM,CAAA,EAAG;AAC1B,MAAA,OAAO,MAAA,CAAO,IAAI,CAAA,CAAA,MAAM;AAAA,QACtB,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,OAAA,EAAS,OAAO,CAAA,CAAE,OAAA,KAAY,WAAW,CAAA,CAAE,OAAA,GAAU,aAAA,CAAc,CAAA,CAAE,OAAO;AAAA,OAC9E,CAAE,CAAA;AAAA,IACJ;AAEA,IAAA,IAAI,OAAO,WAAW,QAAA,EAAU;AAC9B,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAS,QAAQ,CAAA;AAAA,IAChD;AAEA,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,aAAa,OAAA,EAAS,MAAA,CAAO,MAAM,CAAA;AAAA,IACrD;AAEA,IAAA,OAAO,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,SAAS,aAAA,CAAc,MAAM,GAAG,CAAA;AAAA,EAC/D;AAGA,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,EAAU,OAAO,MAAA;AACvC,EAAA,OAAO,cAAc,MAAM,CAAA;AAC7B;;;AC9FA,IAAM,qBAAA,GAAwB,KAAK,EAAA,GAAK,GAAA;AAKxC,IAAM,2BAAA,GAA8B,IAAI,EAAA,GAAK,GAAA;AAyDtC,IAAM,eAAA,GAAN,cAA8BE,0BAAA,CAAa;AAAA,EAChD,IAAA,GAAO,SAAA;AAAA,EAEC,MAAA;AAAA,EACA,YAAA,uBAAmB,GAAA,EAA0B;AAAA,EAC7C,UAAA,uBAAiB,GAAA,EAAwB;AAAA,EAEjD,WAAA,CAAY,MAAA,GAAgC,EAAC,EAAG;AAC9C,IAAA,KAAA,CAAM,MAAM,CAAA;AAGZ,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,IAAS,OAAA,CAAQ,GAAA,CAAI,gBAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,IAAU,OAAA,CAAQ,GAAA,CAAI,UAAA;AAC5C,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,IAAQ,OAAA,CAAQ,IAAI,OAAA,IAAW,eAAA;AACnD,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,IAAO,OAAA,CAAQ,GAAA,CAAI,MAAA;AAItC,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,2BAAA,EAA6B,WAAA,EAAY;AAC1E,IAAA,MAAM,YAAY,MAAA,CAAO,SAAA,KAAc,iBAAiB,OAAA,IAAW,YAAA,KAAiB,MAAM,KAAA,GAAQ,IAAA,CAAA;AAGlG,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,IAAA,CAAK,YAAY,CAAA,0FAAA,CAA4F,CAAA;AAC7G,MAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,SAAA,IAAa,CAAC,MAAA,EAAQ;AACxB,MAAA,IAAA,CAAK,WAAA;AAAA,QACH,CAAA,yGAAA;AAAA,OACF;AACA,MAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,OAAO,IAAA,EAAM,MAAA,EAAQ,WAAW,GAAA,EAAI;AAG/D,IAAA,YAAA,CAAa;AAAA,MACX,KAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,GAAA;AAAA,MACA,qBAAqB,MAAA,CAAO;AAAA,KAC7B,CAAA;AAED,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,8BAAA,EAAgC,EAAE,KAAA,EAAO,IAAA,EAAM,WAAW,CAAA;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,oBAAoB,KAAA,EAAoC;AACtE,IAAA,IAAI,IAAA,CAAK,UAAA,IAAc,CAAED,wBAAAA,CAAe,MAAA,EAAQ;AAEhD,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,KAAA,CAAM,YAAA;AAGnB,MAAA,IAAI,KAAK,OAAA,EAAS;AAChB,QAAA,IAAI,KAAA,CAAM,SAAS,cAAA,EAAgB;AACjC,UAAA,IAAA,CAAK,oBAAoB,IAAI,CAAA;AAC7B,UAAA,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,QACvB;AACA,QAAA;AAAA,MACF;AAGA,MAAA,QAAQ,MAAM,IAAA;AAAM,QAClB,KAAK,cAAA;AACH,UAAA,IAAA,CAAK,oBAAoB,IAAI,CAAA;AAC7B,UAAA;AAAA,QAEF,KAAK,cAAA;AAEH,UAAA;AAAA,QAEF,KAAK,YAAA;AACH,UAAA,IAAA,CAAK,YAAY,IAAI,CAAA;AACrB,UAAA;AAAA;AACJ,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,wBAAA,EAA0B;AAAA,QAC1C,KAAA;AAAA,QACA,WAAW,KAAA,CAAM,IAAA;AAAA,QACjB,MAAA,EAAQ,MAAM,YAAA,EAAc,EAAA;AAAA,QAC5B,QAAA,EAAU,MAAM,YAAA,EAAc;AAAA,OAC/B,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,IAAA,EAA6B;AACvD,IAAA,IAAI,IAAA,CAAK,cAAc,CAAC,IAAA,CAAK,aAAa,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA,EAAG;AAC3D,MAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,OAAA,EAAS;AAAA,QAClC,MAAA,EAAQ,KAAK,QAAA,EAAU,MAAA;AAAA,QACvB,SAAA,EAAW,KAAK,QAAA,EAAU;AAAA,OAC3B,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,IAAA,EAA6B;AAC/C,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,qBAAA,CAAsB,IAAA,CAAK,OAAO,CAAA;AACrD,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,KAAA,CAAM,SAAA,GAAY,IAAA;AAAA,IACpB;AAEA,IAAA,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,EAAA,EAAI,IAAI,CAAA;AAC9B,IAAA,IAAA,CAAK,iBAAA,CAAkB,KAAK,OAAO,CAAA;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,IAAA,EAA4C;AACnE,IAAA,MAAM,cAAmC,EAAC;AAG1C,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAW;AAC5B,MAAA,WAAA,CAAY,SAAA,GAAY,WAAA,CAAY,IAAA,CAAK,KAAA,EAAO,KAAK,IAAI,CAAA;AAAA,IAC3D;AAGA,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAC7B,MAAA,WAAA,CAAY,UAAA,GAAa,YAAA,CAAa,IAAA,CAAK,MAAA,EAAQ,KAAK,IAAI,CAAA;AAAA,IAC9D;AAGA,IAAA,IAAI,KAAK,IAAA,KAASD,wBAAAA,CAAS,oBAAoB,IAAA,CAAK,IAAA,KAASA,yBAAS,UAAA,EAAY;AAChF,MAAA,MAAM,KAAA,GAAS,KAAK,UAAA,EAAgE,KAAA;AACpF,MAAA,MAAM,OAAA,GAAU,mBAAmB,KAAK,CAAA;AACxC,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,WAAA,CAAY,OAAA,GAAU,OAAA;AAAA,MACxB;AAAA,IACF;AAIA,IAAA,MAAM,WAAA,GAAc,CAAC,OAAA,EAAS,OAAA,EAAS,YAAY,YAAY,CAAA;AAC/D,IAAA,MAAM,kBAAkBG,cAAA,CAAU,IAAA,CAAK,UAAA,IAAc,IAA4B,WAAW,CAAA;AAG5F,IAAA,MAAM,gBAAA,GAAmB;AAAA,MACvB,GAAG,IAAA,CAAK,QAAA;AAAA,MACR,GAAG;AAAA,KACL;AACA,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAA,CAAE,SAAS,CAAA,EAAG;AAC5C,MAAA,WAAA,CAAY,QAAA,GAAW,gBAAA;AAAA,IACzB;AAKA,IAAA,MAAM,OAA4B,EAAC;AAGnC,IAAA,IAAI,IAAA,CAAK,MAAM,MAAA,EAAQ;AACrB,MAAA,KAAA,MAAW,GAAA,IAAO,KAAK,IAAA,EAAM;AAC3B,QAAA,IAAA,CAAK,GAAG,CAAA,GAAI,IAAA;AAAA,MACd;AAAA,IACF;AAGA,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,MAAA,IAAA,CAAK,SAAA,GAAY;AAAA,QACf,OAAA,EAAS,KAAK,SAAA,CAAU,OAAA;AAAA,QACxB,GAAI,IAAA,CAAK,SAAA,CAAU,EAAA,GAAK,EAAE,IAAI,IAAA,CAAK,SAAA,CAAU,EAAA,EAAG,GAAI,EAAC;AAAA,QACrD,GAAI,IAAA,CAAK,SAAA,CAAU,MAAA,GAAS,EAAE,QAAQ,IAAA,CAAK,SAAA,CAAU,MAAA,EAAO,GAAI,EAAC;AAAA,QACjE,GAAI,IAAA,CAAK,SAAA,CAAU,QAAA,GAAW,EAAE,UAAU,IAAA,CAAK,SAAA,CAAU,QAAA,EAAS,GAAI;AAAC,OACzE;AAAA,IACF;AAEA,IAAA,IAAI,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAE,SAAS,CAAA,EAAG;AAChC,MAAA,WAAA,CAAY,IAAA,GAAO,IAAA;AAAA,IACrB;AAEA,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,GAA0B;AAE9B,IAAA,KAAA,MAAW,CAAC,OAAA,EAAS,KAAK,CAAA,IAAK,KAAK,UAAA,EAAY;AAC9C,MAAA,IAAI,MAAM,YAAA,EAAc;AACtB,QAAA,YAAA,CAAa,MAAM,YAAY,CAAA;AAAA,MACjC;AACA,MAAA,IAAI,MAAM,gBAAA,EAAkB;AAC1B,QAAA,YAAA,CAAa,MAAM,gBAAgB,CAAA;AAAA,MACrC;AACA,MAAA,IAAI,KAAA,CAAM,MAAA,CAAO,IAAA,GAAO,CAAA,EAAG;AACzB,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,6BAAA,EAA+B;AAAA,UAC9C,OAAA;AAAA,UACA,YAAA,EAAc,MAAM,MAAA,CAAO,IAAA;AAAA,UAC3B,SAAS,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAM;AAAA,SACxC,CAAA;AAAA,MACH;AAAA,IACF;AACA,IAAA,IAAA,CAAK,WAAW,KAAA,EAAM;AAGtB,IAAA,IAAIF,wBAAAA,CAAO,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI;AACF,QAAA,MAAMA,wBAAAA,CAAO,OAAO,KAAA,EAAM;AAAA,MAC5B,SAAS,CAAA,EAAG;AACV,QAAA,IAAA,CAAK,OAAO,KAAA,CAAM,uBAAA,EAAyB,EAAE,KAAA,EAAO,GAAG,CAAA;AAAA,MACzD;AAAA,IACF,CAAA,MAAA,IAAYA,yBAAe,KAAA,EAAO;AAChC,MAAA,IAAI;AACF,QAAA,MAAOA,yBAAe,KAAA,EAAM;AAAA,MAC9B,SAAS,CAAA,EAAG;AACV,QAAA,IAAA,CAAK,OAAO,KAAA,CAAM,uBAAA,EAAyB,EAAE,KAAA,EAAO,GAAG,CAAA;AAAA,MACzD;AAAA,IACF;AAGA,IAAA,IAAIA,wBAAAA,CAAO,QAAQ,OAAA,EAAS;AAC1B,MAAA,IAAI;AACF,QAAAA,wBAAAA,CAAO,OAAO,OAAA,EAAQ;AAAA,MACxB,SAAS,CAAA,EAAG;AACV,QAAA,IAAA,CAAK,OAAO,KAAA,CAAM,wBAAA,EAA0B,EAAE,KAAA,EAAO,GAAG,CAAA;AAAA,MAC1D;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AAExB,IAAA,MAAM,MAAM,QAAA,EAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,OAAA,EAA6B;AACzD,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AAC5C,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAI,SAAS,YAAA,EAAc;AACzB,QAAA,YAAA,CAAa,SAAS,YAAY,CAAA;AAClC,QAAA,QAAA,CAAS,YAAA,GAAe,MAAA;AAAA,MAC1B;AACA,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,MAAM,OAAA,GAAsB;AAAA,MAC1B,MAAA,sBAAY,GAAA,EAA6B;AAAA,MACzC,QAAA,sBAAc,GAAA,EAA6E;AAAA,MAC3F,SAAA,EAAW,KAAA;AAAA,MACX,WAAA,EAAa,KAAA;AAAA,MACb,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,MACpB,YAAA,EAAc,MAAA;AAAA,MACd,gBAAA,EAAkB;AAAA,KACpB;AAIA,IAAA,MAAM,gBAAA,GAAmB,WAAW,MAAM;AACxC,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AACzC,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,IAAI,MAAM,MAAA,CAAO,IAAA,GAAO,KAAK,KAAA,CAAM,QAAA,CAAS,OAAO,CAAA,EAAG;AACpD,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,+CAAA,EAAiD;AAAA,YAChE,OAAA;AAAA,YACA,aAAA,EAAe,MAAM,MAAA,CAAO,IAAA;AAAA,YAC5B,YAAA,EAAc,MAAM,QAAA,CAAS,IAAA;AAAA,YAC7B,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,KAAA,CAAM;AAAA,WAChC,CAAA;AAAA,QACH;AACA,QAAA,IAAI,MAAM,YAAA,EAAc;AACtB,UAAA,YAAA,CAAa,MAAM,YAAY,CAAA;AAAA,QACjC;AACA,QAAA,IAAA,CAAK,UAAA,CAAW,OAAO,OAAO,CAAA;AAC9B,QAAA,IAAA,CAAK,YAAA,CAAa,OAAO,OAAO,CAAA;AAAA,MAClC;AAAA,IACF,GAAG,qBAAqB,CAAA;AAExB,IAAC,iBAAyB,KAAA,IAAQ;AAClC,IAAA,OAAA,CAAQ,gBAAA,GAAmB,gBAAA;AAE3B,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,OAAA,EAAS,OAAO,CAAA;AACpC,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,kBAAkB,OAAA,EAAuB;AAC/C,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AACzC,IAAA,IAAI,CAAC,KAAA,EAAO;AAGZ,IAAA,IAAI,CAAC,MAAM,WAAA,EAAa;AAEtB,MAAA,IAAI,CAAC,MAAM,SAAA,EAAW;AAGtB,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,aAAA,CAAc,KAAA,CAAM,MAAM,CAAA;AAC5C,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,IAAA,CAAK,YAAA,CAAa,MAAM,KAAK,CAAA;AAAA,MAC/B;AAGA,MAAA,KAAA,CAAM,OAAO,KAAA,EAAM;AACnB,MAAA,KAAA,CAAM,WAAA,GAAc,IAAA;AAAA,IACtB,CAAA,MAAO;AAGL,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,GAAG;AACD,QAAA,OAAA,GAAU,KAAA;AACV,QAAA,KAAA,MAAW,CAAC,MAAA,EAAQ,IAAI,CAAA,IAAK,MAAM,MAAA,EAAQ;AACzC,UAAA,MAAM,SAAA,GAAY,KAAK,YAAA,GAAe,KAAA,CAAM,SAAS,GAAA,CAAI,IAAA,CAAK,YAAY,CAAA,GAAI,MAAA;AAC9E,UAAA,IAAI,IAAA,CAAK,YAAA,IAAgB,CAAC,SAAA,EAAW;AACnC,YAAA;AAAA,UACF;AAEA,UAAA,IAAA,CAAK,cAAA,CAAe,IAAA,EAAM,KAAA,EAAO,SAAA,EAAW,MAAM,CAAA;AAClD,UAAA,KAAA,CAAM,MAAA,CAAO,OAAO,MAAM,CAAA;AAC1B,UAAA,OAAA,GAAU,IAAA;AAAA,QACZ;AAAA,MACF,CAAA,QAAS,OAAA;AAAA,IACX;AAGA,IAAA,IAAI,KAAA,CAAM,aAAa,KAAA,CAAM,MAAA,CAAO,SAAS,CAAA,IAAK,CAAC,MAAM,YAAA,EAAc;AACrE,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,QAAA,MAAM,YAAA,GAAe,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AAChD,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,IAAI,YAAA,CAAa,MAAA,CAAO,IAAA,GAAO,CAAA,EAAG;AAChC,YAAA,IAAA,CAAK,MAAA,CAAO,KAAK,0CAAA,EAA4C;AAAA,cAC3D,OAAA;AAAA,cACA,aAAA,EAAe,aAAa,MAAA,CAAO,IAAA;AAAA,cACnC,SAAS,KAAA,CAAM,IAAA,CAAK,YAAA,CAAa,MAAA,CAAO,MAAM;AAAA,aAC/C,CAAA;AAAA,UACH;AAEA,UAAA,IAAI,aAAa,gBAAA,EAAkB;AACjC,YAAA,YAAA,CAAa,aAAa,gBAAgB,CAAA;AAAA,UAC5C;AAAA,QACF;AACA,QAAA,IAAA,CAAK,UAAA,CAAW,OAAO,OAAO,CAAA;AAC9B,QAAA,IAAA,CAAK,YAAA,CAAa,OAAO,OAAO,CAAA;AAAA,MAClC,GAAG,2BAA2B,CAAA;AAE9B,MAAC,MAAc,KAAA,IAAQ;AACvB,MAAA,KAAA,CAAM,YAAA,GAAe,KAAA;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAc,MAAA,EAA4D;AAEhF,IAAA,MAAM,KAAA,uBAAY,GAAA,EAAsB;AACxC,IAAA,IAAI,QAAA;AAEJ,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,MAAA,EAAO,EAAG;AAClC,MAAA,KAAA,CAAM,GAAA,CAAI,KAAK,EAAA,EAAI,EAAE,MAAM,QAAA,EAAU,IAAI,CAAA;AAAA,IAC3C;AAGA,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,CAAM,MAAA,EAAO,EAAG;AACjC,MAAA,IAAI,IAAA,CAAK,KAAK,UAAA,EAAY;AACxB,QAAA,QAAA,GAAW,IAAA;AAAA,MACb,CAAA,MAAA,IAAW,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc;AACjC,QAAA,MAAM,UAAA,GAAa,KAAA,CAAM,GAAA,CAAI,IAAA,CAAK,KAAK,YAAY,CAAA;AACnD,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,UAAA,CAAW,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA,QAC/B,CAAA,MAAO;AAGL,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,0CAAA,EAA4C;AAAA,YAC3D,MAAA,EAAQ,KAAK,IAAA,CAAK,EAAA;AAAA,YAClB,YAAA,EAAc,KAAK,IAAA,CAAK,YAAA;AAAA,YACxB,OAAA,EAAS,KAAK,IAAA,CAAK;AAAA,WACpB,CAAA;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,CAAM,MAAA,EAAO,EAAG;AACjC,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AAC3B,QAAA,MAAM,QACJ,CAAA,CAAE,IAAA,CAAK,SAAA,YAAqB,IAAA,GAAO,EAAE,IAAA,CAAK,SAAA,CAAU,OAAA,EAAQ,GAAI,IAAI,IAAA,CAAK,CAAA,CAAE,IAAA,CAAK,SAAS,EAAE,OAAA,EAAQ;AACrG,QAAA,MAAM,QACJ,CAAA,CAAE,IAAA,CAAK,SAAA,YAAqB,IAAA,GAAO,EAAE,IAAA,CAAK,SAAA,CAAU,OAAA,EAAQ,GAAI,IAAI,IAAA,CAAK,CAAA,CAAE,IAAA,CAAK,SAAS,EAAE,OAAA,EAAQ;AACrG,QAAA,OAAO,KAAA,GAAQ,KAAA;AAAA,MACjB,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,IAAA,EAA0C;AACjE,IAAA,MAAM,WAAW,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA,IAAK;AAAA,MACtD,MAAA,EAAQ,KAAK,QAAA,EAAU,MAAA;AAAA,MACvB,SAAA,EAAW,KAAK,QAAA,EAAU;AAAA,KAC5B;AAEA,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA;AAC9B,IAAA,MAAM,QAAQ,IAAA,CAAK,UAAA;AAEnB,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AAGvC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,GAAI,IAAA,CAAK,OAAA,GAAU,SAAA,mBAAY,IAAI,IAAA,EAAK;AAE1F,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,WAAW,QAAA,CAAS,SAAA;AAAA,MACpB,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,SAAA;AAAA,MACA,OAAA;AAAA,MACA,GAAI,IAAA,KAAS,KAAA,IAAS,KAAA,EAAO,KAAA,GAAQ,EAAE,SAAA,EAAW,KAAA,CAAM,KAAA,EAAM,GAAI,EAAC;AAAA,MACnE,GAAI,IAAA,KAAS,KAAA,IAAS,KAAA,EAAO,QAAA,GAAW,EAAE,aAAA,EAAe,KAAA,CAAM,QAAA,EAAS,GAAI;AAAC,KAC/E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAA,CAAa,MAAgB,KAAA,EAAyB;AAC5D,IAAA,MAAM,OAAO,IAAA,CAAK,IAAA;AAClB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA;AAI1C,IAAAA,wBAAAA,CAAO,MAAA,CAAO,KAAA,CAAM,OAAA,EAAgB,CAAC,MAAA,KAAgB;AAEnD,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA;AAC9C,MAAA,IAAI,MAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAAE,SAAS,CAAA,EAAG;AACvC,QAAAA,wBAAAA,CAAO,MAAA,CAAO,QAAA,CAAS,MAAA,EAAQ,WAAW,CAAA;AAAA,MAC5C;AAGA,MAAA,IAAI,KAAK,SAAA,EAAW;AAClB,QAAA,MAAA,CAAO,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,MAC7B;AAGA,MAAA,MAAM,QAAA,GAAWA,yBAAO,MAAA,CAAO,UAAA,GAAaA,yBAAO,MAAA,CAAO,UAAA,CAAW,MAAM,CAAA,GAAI,MAAA;AAC/E,MAAA,KAAA,CAAM,SAAS,GAAA,CAAI,IAAA,CAAK,IAAI,EAAE,MAAA,EAAQ,UAAU,CAAA;AAIhD,MAAA,KAAA,MAAW,KAAA,IAAS,KAAK,QAAA,EAAU;AACjC,QAAA,IAAA,CAAK,YAAA,CAAa,OAAO,KAAK,CAAA;AAAA,MAChC;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAA,CAAe,IAAA,EAAuB,KAAA,EAAmB,MAAA,EAAc;AAC7E,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA;AAE1C,IAAA,MAAM,WAAW,MACfA,wBAAAA,CAAO,OAAO,KAAA,CAAM,OAAA,EAAgB,CAAC,MAAA,KAAgB;AACnD,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA;AAC9C,MAAA,IAAI,MAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAAE,SAAS,CAAA,EAAG;AACvC,QAAAA,wBAAAA,CAAO,MAAA,CAAO,QAAA,CAAS,MAAA,EAAQ,WAAW,CAAA;AAAA,MAC5C;AAGA,MAAA,IAAI,KAAK,SAAA,EAAW;AAClB,QAAA,MAAA,CAAO,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,MAC7B;AAEA,MAAA,MAAM,QAAA,GAAWA,yBAAO,MAAA,CAAO,UAAA,GAAaA,yBAAO,MAAA,CAAO,UAAA,CAAW,MAAM,CAAA,GAAI,MAAA;AAC/E,MAAA,KAAA,CAAM,SAAS,GAAA,CAAI,IAAA,CAAK,IAAI,EAAE,MAAA,EAAQ,UAAU,CAAA;AAAA,IAClD,CAAC,CAAA;AAEH,IAAA,IAAI,MAAA,EAAQ;AACV,MAAAA,wBAAAA,CAAO,KAAA,EAAM,CAAE,QAAA,CAAS,QAAQ,QAAQ,CAAA;AAAA,IAC1C,CAAA,MAAO;AACL,MAAA,QAAA,EAAS;AAAA,IACX;AAAA,EACF;AACF","file":"index.cjs","sourcesContent":["import type { UsageStats } from '@mastra/core/observability';\nimport type tracer from 'dd-trace';\n\ntype DatadogAnnotationMetrics = tracer.llmobs.AnnotationOptions['metrics'];\n\nexport function formatUsageMetrics(usage?: UsageStats): DatadogAnnotationMetrics | undefined {\n if (!usage) return undefined;\n\n const result: DatadogAnnotationMetrics = {};\n\n const inputTokens = usage.inputTokens;\n if (inputTokens !== undefined) result.inputTokens = inputTokens;\n\n const outputTokens = usage.outputTokens;\n if (outputTokens !== undefined) result.outputTokens = outputTokens;\n\n if (inputTokens !== undefined && outputTokens !== undefined) {\n result.totalTokens = inputTokens + outputTokens;\n }\n\n if (usage?.outputDetails?.reasoning !== undefined) {\n result.reasoningTokens = usage.outputDetails.reasoning;\n }\n\n const cachedTokens = usage?.inputDetails?.cacheRead;\n if (cachedTokens !== undefined) {\n result.cachedInputTokens = cachedTokens;\n }\n\n const cachedOutputTokens = usage?.inputDetails?.cacheWrite;\n if (cachedOutputTokens !== undefined) {\n result.cachedOutputTokens = cachedOutputTokens;\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n","/**\n * Utility functions for Datadog LLM Observability Exporter\n */\n\nimport { SpanType } from '@mastra/core/observability';\nimport tracer from 'dd-trace';\n\n/**\n * Datadog LLM Observability span kinds.\n */\nexport type DatadogSpanKind = 'llm' | 'agent' | 'workflow' | 'tool' | 'task' | 'retrieval' | 'embedding';\n\n/**\n * Maps Mastra SpanTypes to Datadog LLMObs span kinds.\n * Only non-task mappings are defined; unmapped types fall back to 'task'.\n */\nexport const SPAN_TYPE_TO_KIND: Partial<Record<SpanType, DatadogSpanKind>> = {\n [SpanType.AGENT_RUN]: 'agent',\n [SpanType.MODEL_GENERATION]: 'workflow',\n [SpanType.MODEL_STEP]: 'llm',\n [SpanType.TOOL_CALL]: 'tool',\n [SpanType.MCP_TOOL_CALL]: 'tool',\n [SpanType.WORKFLOW_RUN]: 'workflow',\n};\n\n/**\n * Singleton flag to prevent multiple tracer initializations.\n * dd-trace should only be initialized once per process.\n */\nconst tracerInitFlag = { done: false };\n\n/**\n * Ensures dd-trace is initialized exactly once.\n * Respects any existing tracer initialization by the application.\n */\nexport function ensureTracer(config: {\n mlApp: string;\n site: string;\n apiKey?: string;\n agentless: boolean;\n service?: string;\n env?: string;\n integrationsEnabled?: boolean;\n}): void {\n if (tracerInitFlag.done) return;\n\n // Set environment variables for dd-trace to pick up\n // (LLMObsEnableOptions only accepts mlApp and agentlessEnabled)\n // Always set when config is provided to ensure explicit config takes precedence\n // over any stale env vars that may already be set in the process\n if (config.site) {\n process.env.DD_SITE = config.site;\n }\n if (config.apiKey) {\n process.env.DD_API_KEY = config.apiKey;\n }\n\n // Check if tracer was already started by the application\n const alreadyStarted = (tracer as any)._tracer?.started;\n\n if (!alreadyStarted) {\n tracer.init({\n service: config.service || config.mlApp,\n env: config.env || process.env.DD_ENV,\n // Disable automatic integrations by default to avoid surprise instrumentation\n plugins: config.integrationsEnabled ?? false,\n });\n }\n\n // Enable LLM Observability with the resolved configuration\n tracer.llmobs.enable({\n mlApp: config.mlApp,\n agentlessEnabled: config.agentless,\n });\n\n tracerInitFlag.done = true;\n}\n\n/**\n * Returns the Datadog kind for a Mastra span type.\n */\nexport function kindFor(spanType: SpanType): DatadogSpanKind {\n return SPAN_TYPE_TO_KIND[spanType] || 'task';\n}\n\n/**\n * Converts a value to a Date object.\n */\nexport function toDate(value: Date | string | number): Date {\n return value instanceof Date ? value : new Date(value);\n}\n\n/**\n * Safely stringifies data, handling circular references.\n */\nexport function safeStringify(data: unknown): string {\n try {\n return JSON.stringify(data);\n } catch {\n if (typeof data === 'object' && data !== null) {\n return `[Non-serializable ${data.constructor?.name || 'Object'}]`;\n }\n return String(data);\n }\n}\n\n/**\n * Checks if data is already in message array format ({role, content}[]).\n */\nfunction isMessageArray(data: any): data is Array<{ role: string; content: any }> {\n return Array.isArray(data) && data.every(m => m?.role && m?.content !== undefined);\n}\n\n/**\n * Formats input data for Datadog annotations.\n * LLM spans use message array format; others use raw or stringified data.\n */\nexport function formatInput(input: any, spanType: SpanType): any {\n // LLM spans expect {role, content}[] format\n if (spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP) {\n // Already in message format\n if (isMessageArray(input)) {\n return input.map(m => ({\n role: m.role,\n content: typeof m.content === 'string' ? m.content : safeStringify(m.content),\n }));\n }\n // String input becomes user message\n if (typeof input === 'string') {\n return [{ role: 'user', content: input }];\n }\n // Object input gets stringified as user message\n return [{ role: 'user', content: safeStringify(input) }];\n }\n\n // Non-LLM spans: pass through strings/arrays, stringify objects\n if (typeof input === 'string' || Array.isArray(input)) return input;\n return safeStringify(input);\n}\n\n/**\n * Formats output data for Datadog annotations.\n * LLM spans use message array format; others use raw or stringified data.\n */\nexport function formatOutput(output: any, spanType: SpanType): any {\n // LLM spans expect {role, content}[] format\n if (spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP) {\n // Already in message format\n if (isMessageArray(output)) {\n return output.map(m => ({\n role: m.role,\n content: typeof m.content === 'string' ? m.content : safeStringify(m.content),\n }));\n }\n // String output becomes assistant message\n if (typeof output === 'string') {\n return [{ role: 'assistant', content: output }];\n }\n // Object with text property (common AI SDK format)\n if (output?.text) {\n return [{ role: 'assistant', content: output.text }];\n }\n // Other objects get stringified as assistant message\n return [{ role: 'assistant', content: safeStringify(output) }];\n }\n\n // Non-LLM spans: pass through strings, stringify objects\n if (typeof output === 'string') return output;\n return safeStringify(output);\n}\n","/**\n * Datadog LLM Observability Exporter for Mastra\n *\n * Exports Mastra observability data to Datadog's LLM Observability product.\n * Uses a completion-only pattern where spans are emitted on span_ended events.\n *\n * Key features:\n * - Maps Mastra span types to Datadog span kinds\n * - Normalizes AI SDK v4/v5 token usage formats\n * - Formats LLM inputs/outputs as message arrays\n * - Flattens metadata into searchable tags\n * - Supports both agent and agentless modes\n */\n\nimport type {\n TracingEvent,\n AnyExportedSpan,\n ModelGenerationAttributes,\n ModelStepAttributes,\n} from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport { omitKeys } from '@mastra/core/utils';\nimport { BaseExporter } from '@mastra/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport tracer from 'dd-trace';\nimport { formatUsageMetrics } from './metrics';\nimport { ensureTracer, kindFor, toDate, formatInput, formatOutput } from './utils';\nimport type { DatadogSpanKind } from './utils';\n\n/**\n * LLMObs span options with required name and kind properties.\n */\ninterface LLMObsSpanOptions {\n kind: DatadogSpanKind;\n name: string;\n sessionId?: string;\n userId?: string;\n mlApp?: string;\n modelName?: string;\n modelProvider?: string;\n startTime?: Date;\n endTime?: Date;\n}\n\n/**\n * Minimal per-trace context for user/session tagging.\n */\ninterface TraceContext {\n userId?: string;\n sessionId?: string;\n}\n\ntype TraceState = {\n buffer: Map<string, AnyExportedSpan>;\n contexts: Map<string, { ddSpan: any; exported?: { traceId: string; spanId: string } }>;\n rootEnded: boolean;\n treeEmitted: boolean; // Whether the initial span tree has been emitted\n createdAt: number;\n cleanupTimer?: ReturnType<typeof setTimeout>;\n maxLifetimeTimer?: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Tree node representing a span and its children for recursive emission.\n */\ninterface SpanNode {\n span: AnyExportedSpan;\n children: SpanNode[];\n}\n\n/**\n * Maximum lifetime for a trace state entry (30 minutes).\n * This is a fallback cleanup mechanism for traces that never receive a root span\n * or have all spans marked as non-root, preventing unbounded memory growth.\n */\nconst MAX_TRACE_LIFETIME_MS = 30 * 60 * 1000;\n\n/**\n * Regular cleanup interval for trace state entries (1 minute).\n */\nconst REGULAR_CLEANUP_INTERVAL_MS = 1 * 60 * 1000;\n\n/**\n * Configuration options for the Datadog LLM Observability exporter.\n */\nexport interface DatadogExporterConfig extends BaseExporterConfig {\n /**\n * Datadog API key. Required (agentless mode is the default).\n * Falls back to DD_API_KEY environment variable.\n */\n apiKey?: string;\n\n /**\n * ML application name for grouping traces.\n * Required - falls back to DD_LLMOBS_ML_APP environment variable.\n */\n mlApp?: string;\n\n /**\n * Datadog site (e.g., 'datadoghq.com', 'datadoghq.eu').\n * Falls back to DD_SITE environment variable, defaults to 'datadoghq.com'.\n */\n site?: string;\n\n /**\n * Service name for the application.\n * Falls back to mlApp if not specified.\n */\n service?: string;\n\n /**\n * Environment name (e.g., 'production', 'staging').\n * Falls back to DD_ENV environment variable.\n */\n env?: string;\n\n /**\n * Use agentless mode (direct HTTPS intake without local Datadog Agent).\n * Defaults to true for consistency with other Mastra exporters.\n * Set to false to use a local Datadog Agent instead.\n * Falls back to DD_LLMOBS_AGENTLESS_ENABLED environment variable.\n */\n agentless?: boolean;\n\n /**\n * Enable dd-trace automatic integrations.\n * Defaults to false to avoid unexpected instrumentation.\n */\n integrationsEnabled?: boolean;\n}\n\n/**\n * Datadog LLM Observability Exporter for Mastra.\n *\n * Exports observability data to Datadog's LLM Observability product using\n * a completion-only pattern where spans are emitted on span_ended events.\n */\nexport class DatadogExporter extends BaseExporter {\n name = 'datadog';\n\n private config: Required<Pick<DatadogExporterConfig, 'mlApp' | 'site'>> & DatadogExporterConfig;\n private traceContext = new Map<string, TraceContext>();\n private traceState = new Map<string, TraceState>();\n\n constructor(config: DatadogExporterConfig = {}) {\n super(config);\n\n // Resolve configuration from config object and environment variables\n const mlApp = config.mlApp ?? process.env.DD_LLMOBS_ML_APP;\n const apiKey = config.apiKey ?? process.env.DD_API_KEY;\n const site = config.site ?? process.env.DD_SITE ?? 'datadoghq.com';\n const env = config.env ?? process.env.DD_ENV;\n\n // Default to agentless mode (true) for consistency with other Mastra exporters\n // Only disable if explicitly set to false via config or env var\n const envAgentless = process.env.DD_LLMOBS_AGENTLESS_ENABLED?.toLowerCase();\n const agentless = config.agentless ?? (envAgentless === 'false' || envAgentless === '0' ? false : true);\n\n // Validate required configuration\n if (!mlApp) {\n this.setDisabled(`Missing required mlApp. Set DD_LLMOBS_ML_APP environment variable or pass mlApp in config.`);\n this.config = config as any;\n return;\n }\n\n if (agentless && !apiKey) {\n this.setDisabled(\n `Missing required apiKey for agentless mode. Set DD_API_KEY environment variable or pass apiKey in config.`,\n );\n this.config = config as any;\n return;\n }\n\n this.config = { ...config, mlApp, site, apiKey, agentless, env };\n\n // Initialize tracer and enable LLM Observability\n ensureTracer({\n mlApp,\n site,\n apiKey,\n agentless,\n service: config.service,\n env,\n integrationsEnabled: config.integrationsEnabled,\n });\n\n this.logger.info('Datadog exporter initialized', { mlApp, site, agentless });\n }\n\n /**\n * Main entry point for tracing events from Mastra.\n */\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (this.isDisabled || !(tracer as any).llmobs) return;\n\n try {\n const span = event.exportedSpan;\n\n // Handle event spans (zero-duration spans) - buffer like regular spans for parent-first emission\n if (span.isEvent) {\n if (event.type === 'span_started') {\n this.captureTraceContext(span);\n this.enqueueSpan(span); // Route through buffer for proper parent context\n }\n return; // Skip span_updated and span_ended for events\n }\n\n // Handle regular spans based on event type\n switch (event.type) {\n case 'span_started':\n this.captureTraceContext(span);\n return;\n\n case 'span_updated':\n // No-op: completion-only pattern ignores mid-span updates\n return;\n\n case 'span_ended':\n this.enqueueSpan(span);\n return;\n }\n } catch (error) {\n this.logger.error('Datadog exporter error', {\n error,\n eventType: event.type,\n spanId: event.exportedSpan?.id,\n spanName: event.exportedSpan?.name,\n });\n }\n }\n\n /**\n * Captures user/session context from root spans for tagging all spans in the trace.\n */\n private captureTraceContext(span: AnyExportedSpan): void {\n if (span.isRootSpan && !this.traceContext.has(span.traceId)) {\n this.traceContext.set(span.traceId, {\n userId: span.metadata?.userId,\n sessionId: span.metadata?.sessionId,\n });\n }\n }\n\n /**\n * Queue span until its parent context is available, then emit spans parent-first.\n */\n private enqueueSpan(span: AnyExportedSpan): void {\n const state = this.getOrCreateTraceState(span.traceId);\n if (span.isRootSpan) {\n state.rootEnded = true;\n }\n\n state.buffer.set(span.id, span);\n this.tryEmitReadySpans(span.traceId);\n }\n\n /**\n * Builds annotations object for llmobs.annotate().\n * Uses dd-trace's expected property names: inputData, outputData, metadata, tags, metrics.\n */\n private buildAnnotations(span: AnyExportedSpan): Record<string, any> {\n const annotations: Record<string, any> = {};\n\n // Format and add input (dd-trace expects 'inputData')\n if (span.input !== undefined) {\n annotations.inputData = formatInput(span.input, span.type);\n }\n\n // Format and add output (dd-trace expects 'outputData')\n if (span.output !== undefined) {\n annotations.outputData = formatOutput(span.output, span.type);\n }\n\n // Add token usage metrics (only on MODEL_GENERATION or MODEL_STEP spans)\n if (span.type === SpanType.MODEL_GENERATION || span.type === SpanType.MODEL_STEP) {\n const usage = (span.attributes as ModelGenerationAttributes | ModelStepAttributes)?.usage;\n const metrics = formatUsageMetrics(usage);\n if (metrics) {\n annotations.metrics = metrics;\n }\n }\n\n // Forward span.attributes to metadata (minus known fields handled separately)\n // This ensures tool/workflow spans preserve custom attributes like other exporters\n const knownFields = ['usage', 'model', 'provider', 'parameters'];\n const otherAttributes = omitKeys((span.attributes ?? {}) as Record<string, any>, knownFields);\n\n // Merge span.metadata + remaining attributes into metadata\n const combinedMetadata = {\n ...span.metadata,\n ...otherAttributes,\n };\n if (Object.keys(combinedMetadata).length > 0) {\n annotations.metadata = combinedMetadata;\n }\n\n // Build tags from span.tags (user-provided string[] converted to object) and error info\n // Datadog annotation tags accept Record<string, any>, so we use proper types\n // The native span error status is also set via ddSpan.setTag('error', true) in emitSpan()\n const tags: Record<string, any> = {};\n\n // Convert span.tags (string[]) to object format - each tag becomes a key with value true\n if (span.tags?.length) {\n for (const tag of span.tags) {\n tags[tag] = true;\n }\n }\n\n // Add error info as consolidated tags\n if (span.errorInfo) {\n tags.error = true;\n tags.errorInfo = {\n message: span.errorInfo.message,\n ...(span.errorInfo.id ? { id: span.errorInfo.id } : {}),\n ...(span.errorInfo.domain ? { domain: span.errorInfo.domain } : {}),\n ...(span.errorInfo.category ? { category: span.errorInfo.category } : {}),\n };\n }\n\n if (Object.keys(tags).length > 0) {\n annotations.tags = tags;\n }\n\n return annotations;\n }\n\n /**\n * Gracefully shuts down the exporter.\n */\n async shutdown(): Promise<void> {\n // Cancel all pending cleanup timers and clear state FIRST\n for (const [traceId, state] of this.traceState) {\n if (state.cleanupTimer) {\n clearTimeout(state.cleanupTimer);\n }\n if (state.maxLifetimeTimer) {\n clearTimeout(state.maxLifetimeTimer);\n }\n if (state.buffer.size > 0) {\n this.logger.warn('Shutdown with pending spans', {\n traceId,\n pendingCount: state.buffer.size,\n spanIds: Array.from(state.buffer.keys()),\n });\n }\n }\n this.traceState.clear();\n\n // Flush any pending data\n if (tracer.llmobs?.flush) {\n try {\n await tracer.llmobs.flush();\n } catch (e) {\n this.logger.error('Error flushing llmobs', { error: e });\n }\n } else if ((tracer as any).flush) {\n try {\n await (tracer as any).flush();\n } catch (e) {\n this.logger.error('Error flushing tracer', { error: e });\n }\n }\n\n // Disable LLM Observability\n if (tracer.llmobs?.disable) {\n try {\n tracer.llmobs.disable();\n } catch (e) {\n this.logger.error('Error disabling llmobs', { error: e });\n }\n }\n\n // Clear local state\n this.traceContext.clear();\n\n await super.shutdown();\n }\n\n /**\n * Retrieve or initialize trace state for buffering and parent tracking.\n */\n private getOrCreateTraceState(traceId: string): TraceState {\n const existing = this.traceState.get(traceId);\n if (existing) {\n if (existing.cleanupTimer) {\n clearTimeout(existing.cleanupTimer);\n existing.cleanupTimer = undefined;\n }\n return existing;\n }\n\n const created: TraceState = {\n buffer: new Map<string, AnyExportedSpan>(),\n contexts: new Map<string, { ddSpan: any; exported?: { traceId: string; spanId: string } }>(),\n rootEnded: false,\n treeEmitted: false,\n createdAt: Date.now(),\n cleanupTimer: undefined,\n maxLifetimeTimer: undefined,\n };\n\n // Schedule fallback cleanup after max lifetime to prevent memory leaks\n // when traces never receive a root span or all spans are non-root\n const maxLifetimeTimer = setTimeout(() => {\n const state = this.traceState.get(traceId);\n if (state) {\n if (state.buffer.size > 0 || state.contexts.size > 0) {\n this.logger.warn('Discarding trace due to max lifetime exceeded', {\n traceId,\n bufferedSpans: state.buffer.size,\n emittedSpans: state.contexts.size,\n lifetimeMs: Date.now() - state.createdAt,\n });\n }\n if (state.cleanupTimer) {\n clearTimeout(state.cleanupTimer);\n }\n this.traceState.delete(traceId);\n this.traceContext.delete(traceId);\n }\n }, MAX_TRACE_LIFETIME_MS);\n // Prevent the timer from keeping the process alive\n (maxLifetimeTimer as any).unref?.();\n created.maxLifetimeTimer = maxLifetimeTimer;\n\n this.traceState.set(traceId, created);\n return created;\n }\n\n /**\n * Attempt to emit spans from the buffer.\n *\n * Two modes of operation:\n * 1. Initial tree emission: When root span ends and tree hasn't been emitted yet,\n * build a tree from all buffered spans and emit recursively using nested\n * llmobs.trace() calls. This ensures proper parent-child relationships in Datadog.\n * 2. Late-arriving spans: After the tree has been emitted, emit individual spans\n * with their parent context for proper linking.\n */\n private tryEmitReadySpans(traceId: string): void {\n const state = this.traceState.get(traceId);\n if (!state) return;\n\n // If tree hasn't been emitted yet, wait for root and emit as tree\n if (!state.treeEmitted) {\n // Wait until the root span has ended before emitting any spans\n if (!state.rootEnded) return;\n\n // Build tree and emit recursively\n const tree = this.buildSpanTree(state.buffer);\n if (tree) {\n this.emitSpanTree(tree, state);\n }\n\n // Clear the buffer and mark tree as emitted\n state.buffer.clear();\n state.treeEmitted = true;\n } else {\n // Tree already emitted - handle late-arriving spans individually\n // Use the old parent-first emission pattern for these\n let emitted = false;\n do {\n emitted = false;\n for (const [spanId, span] of state.buffer) {\n const parentCtx = span.parentSpanId ? state.contexts.get(span.parentSpanId) : undefined;\n if (span.parentSpanId && !parentCtx) {\n continue;\n }\n\n this.emitSingleSpan(span, state, parentCtx?.ddSpan);\n state.buffer.delete(spanId);\n emitted = true;\n }\n } while (emitted);\n }\n\n // Schedule cleanup if root has ended and buffer is empty\n if (state.rootEnded && state.buffer.size === 0 && !state.cleanupTimer) {\n const timer = setTimeout(() => {\n const currentState = this.traceState.get(traceId);\n if (currentState) {\n if (currentState.buffer.size > 0) {\n this.logger.warn('Discarding orphaned spans during cleanup', {\n traceId,\n orphanedCount: currentState.buffer.size,\n spanIds: Array.from(currentState.buffer.keys()),\n });\n }\n // Clear the max lifetime timer since normal cleanup is handling this\n if (currentState.maxLifetimeTimer) {\n clearTimeout(currentState.maxLifetimeTimer);\n }\n }\n this.traceState.delete(traceId);\n this.traceContext.delete(traceId);\n }, REGULAR_CLEANUP_INTERVAL_MS);\n // Prevent the timer from keeping the process alive\n (timer as any).unref?.();\n state.cleanupTimer = timer;\n }\n }\n\n /**\n * Builds a tree structure from buffered spans based on parentSpanId relationships.\n * Returns the root node of the tree, or undefined if no root span is found.\n */\n private buildSpanTree(buffer: Map<string, AnyExportedSpan>): SpanNode | undefined {\n // Create nodes for all spans\n const nodes = new Map<string, SpanNode>();\n let rootNode: SpanNode | undefined;\n\n for (const span of buffer.values()) {\n nodes.set(span.id, { span, children: [] });\n }\n\n // Build parent-child relationships\n for (const node of nodes.values()) {\n if (node.span.isRootSpan) {\n rootNode = node;\n } else if (node.span.parentSpanId) {\n const parentNode = nodes.get(node.span.parentSpanId);\n if (parentNode) {\n parentNode.children.push(node);\n } else {\n // Orphaned span - parent not in buffer, treat as root-level\n // This shouldn't happen normally but handles edge cases\n this.logger.warn('Orphaned span detected during tree build', {\n spanId: node.span.id,\n parentSpanId: node.span.parentSpanId,\n traceId: node.span.traceId,\n });\n }\n }\n }\n\n // Sort children by start time for consistent ordering\n for (const node of nodes.values()) {\n node.children.sort((a, b) => {\n const aTime =\n a.span.startTime instanceof Date ? a.span.startTime.getTime() : new Date(a.span.startTime).getTime();\n const bTime =\n b.span.startTime instanceof Date ? b.span.startTime.getTime() : new Date(b.span.startTime).getTime();\n return aTime - bTime;\n });\n }\n\n return rootNode;\n }\n\n /**\n * Builds LLMObs span options from a Mastra span.\n * Handles trace context, timestamps, and conditional model information for LLM spans.\n */\n private buildSpanOptions(span: AnyExportedSpan): LLMObsSpanOptions {\n const traceCtx = this.traceContext.get(span.traceId) || {\n userId: span.metadata?.userId,\n sessionId: span.metadata?.sessionId,\n };\n\n const kind = kindFor(span.type);\n const attrs = span.attributes as ModelGenerationAttributes | undefined;\n\n const startTime = toDate(span.startTime);\n // Event spans are point-in-time markers; use startTime for endTime if not set (zero duration)\n // Regular spans fall back to current time if endTime is not set\n const endTime = span.endTime ? toDate(span.endTime) : span.isEvent ? startTime : new Date();\n\n return {\n kind,\n name: span.name,\n sessionId: traceCtx.sessionId,\n userId: traceCtx.userId,\n startTime,\n endTime,\n ...(kind === 'llm' && attrs?.model ? { modelName: attrs.model } : {}),\n ...(kind === 'llm' && attrs?.provider ? { modelProvider: attrs.provider } : {}),\n };\n }\n\n /**\n * Recursively emits a span tree using nested llmobs.trace() calls.\n * This ensures parent-child relationships are properly established in Datadog\n * because child spans are created while their parent span is active in scope.\n */\n private emitSpanTree(node: SpanNode, state: TraceState): void {\n const span = node.span;\n const options = this.buildSpanOptions(span);\n\n // Use nested llmobs.trace() calls - children are emitted INSIDE the parent's callback\n // This ensures the Datadog SDK automatically establishes parent-child relationships\n tracer.llmobs.trace(options as any, (ddSpan: any) => {\n // Annotate this span\n const annotations = this.buildAnnotations(span);\n if (Object.keys(annotations).length > 0) {\n tracer.llmobs.annotate(ddSpan, annotations);\n }\n\n // Set native Datadog error status for proper UI highlighting\n if (span.errorInfo) {\n ddSpan.setTag('error', true);\n }\n\n // Store context for potential evaluation submissions\n const exported = tracer.llmobs.exportSpan ? tracer.llmobs.exportSpan(ddSpan) : undefined;\n state.contexts.set(span.id, { ddSpan, exported });\n\n // Recursively emit children INSIDE this span's callback\n // This is the key to establishing proper parent-child relationships\n for (const child of node.children) {\n this.emitSpanTree(child, state);\n }\n });\n }\n\n /**\n * Emit a single span with the proper Datadog parent context.\n * Used for late-arriving spans after the main tree has been emitted.\n */\n private emitSingleSpan(span: AnyExportedSpan, state: TraceState, parent?: any) {\n const options = this.buildSpanOptions(span);\n\n const runTrace = () =>\n tracer.llmobs.trace(options as any, (ddSpan: any) => {\n const annotations = this.buildAnnotations(span);\n if (Object.keys(annotations).length > 0) {\n tracer.llmobs.annotate(ddSpan, annotations);\n }\n\n // Set native Datadog error status for proper UI highlighting\n if (span.errorInfo) {\n ddSpan.setTag('error', true);\n }\n\n const exported = tracer.llmobs.exportSpan ? tracer.llmobs.exportSpan(ddSpan) : undefined;\n state.contexts.set(span.id, { ddSpan, exported });\n });\n\n if (parent) {\n tracer.scope().activate(parent, runTrace);\n } else {\n runTrace();\n }\n }\n}\n"]}
package/dist/index.js CHANGED
@@ -126,29 +126,32 @@ var DatadogExporter = class extends BaseExporter {
126
126
  traceState = /* @__PURE__ */ new Map();
127
127
  constructor(config = {}) {
128
128
  super(config);
129
- const mlApp = config.mlApp || process.env.DD_LLMOBS_ML_APP;
130
- const apiKey = config.apiKey || process.env.DD_API_KEY;
131
- const site = config.site || process.env.DD_SITE || "datadoghq.com";
129
+ const mlApp = config.mlApp ?? process.env.DD_LLMOBS_ML_APP;
130
+ const apiKey = config.apiKey ?? process.env.DD_API_KEY;
131
+ const site = config.site ?? process.env.DD_SITE ?? "datadoghq.com";
132
+ const env = config.env ?? process.env.DD_ENV;
132
133
  const envAgentless = process.env.DD_LLMOBS_AGENTLESS_ENABLED?.toLowerCase();
133
134
  const agentless = config.agentless ?? (envAgentless === "false" || envAgentless === "0" ? false : true);
134
135
  if (!mlApp) {
135
- this.setDisabled("Missing required mlApp (set config.mlApp or DD_LLMOBS_ML_APP)");
136
+ this.setDisabled(`Missing required mlApp. Set DD_LLMOBS_ML_APP environment variable or pass mlApp in config.`);
136
137
  this.config = config;
137
138
  return;
138
139
  }
139
140
  if (agentless && !apiKey) {
140
- this.setDisabled("Missing required apiKey (set config.apiKey or DD_API_KEY)");
141
+ this.setDisabled(
142
+ `Missing required apiKey for agentless mode. Set DD_API_KEY environment variable or pass apiKey in config.`
143
+ );
141
144
  this.config = config;
142
145
  return;
143
146
  }
144
- this.config = { ...config, mlApp, site, apiKey, agentless };
147
+ this.config = { ...config, mlApp, site, apiKey, agentless, env };
145
148
  ensureTracer({
146
149
  mlApp,
147
150
  site,
148
151
  apiKey,
149
152
  agentless,
150
153
  service: config.service,
151
- env: config.env,
154
+ env,
152
155
  integrationsEnabled: config.integrationsEnabled
153
156
  });
154
157
  this.logger.info("Datadog exporter initialized", { mlApp, site, agentless });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/metrics.ts","../src/utils.ts","../src/tracing.ts"],"names":["tracer","SpanType"],"mappings":"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","file":"index.js","sourcesContent":["import type { UsageStats } from '@mastra/core/observability';\nimport type tracer from 'dd-trace';\n\ntype DatadogAnnotationMetrics = tracer.llmobs.AnnotationOptions['metrics'];\n\nexport function formatUsageMetrics(usage?: UsageStats): DatadogAnnotationMetrics | undefined {\n if (!usage) return undefined;\n\n const result: DatadogAnnotationMetrics = {};\n\n const inputTokens = usage.inputTokens;\n if (inputTokens !== undefined) result.inputTokens = inputTokens;\n\n const outputTokens = usage.outputTokens;\n if (outputTokens !== undefined) result.outputTokens = outputTokens;\n\n if (inputTokens !== undefined && outputTokens !== undefined) {\n result.totalTokens = inputTokens + outputTokens;\n }\n\n if (usage?.outputDetails?.reasoning !== undefined) {\n result.reasoningTokens = usage.outputDetails.reasoning;\n }\n\n const cachedTokens = usage?.inputDetails?.cacheRead;\n if (cachedTokens !== undefined) {\n result.cachedInputTokens = cachedTokens;\n }\n\n const cachedOutputTokens = usage?.inputDetails?.cacheWrite;\n if (cachedOutputTokens !== undefined) {\n result.cachedOutputTokens = cachedOutputTokens;\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n","/**\n * Utility functions for Datadog LLM Observability Exporter\n */\n\nimport { SpanType } from '@mastra/core/observability';\nimport tracer from 'dd-trace';\n\n/**\n * Datadog LLM Observability span kinds.\n */\nexport type DatadogSpanKind = 'llm' | 'agent' | 'workflow' | 'tool' | 'task' | 'retrieval' | 'embedding';\n\n/**\n * Maps Mastra SpanTypes to Datadog LLMObs span kinds.\n * Only non-task mappings are defined; unmapped types fall back to 'task'.\n */\nexport const SPAN_TYPE_TO_KIND: Partial<Record<SpanType, DatadogSpanKind>> = {\n [SpanType.AGENT_RUN]: 'agent',\n [SpanType.MODEL_GENERATION]: 'workflow',\n [SpanType.MODEL_STEP]: 'llm',\n [SpanType.TOOL_CALL]: 'tool',\n [SpanType.MCP_TOOL_CALL]: 'tool',\n [SpanType.WORKFLOW_RUN]: 'workflow',\n};\n\n/**\n * Singleton flag to prevent multiple tracer initializations.\n * dd-trace should only be initialized once per process.\n */\nconst tracerInitFlag = { done: false };\n\n/**\n * Ensures dd-trace is initialized exactly once.\n * Respects any existing tracer initialization by the application.\n */\nexport function ensureTracer(config: {\n mlApp: string;\n site: string;\n apiKey?: string;\n agentless: boolean;\n service?: string;\n env?: string;\n integrationsEnabled?: boolean;\n}): void {\n if (tracerInitFlag.done) return;\n\n // Set environment variables for dd-trace to pick up\n // (LLMObsEnableOptions only accepts mlApp and agentlessEnabled)\n // Always set when config is provided to ensure explicit config takes precedence\n // over any stale env vars that may already be set in the process\n if (config.site) {\n process.env.DD_SITE = config.site;\n }\n if (config.apiKey) {\n process.env.DD_API_KEY = config.apiKey;\n }\n\n // Check if tracer was already started by the application\n const alreadyStarted = (tracer as any)._tracer?.started;\n\n if (!alreadyStarted) {\n tracer.init({\n service: config.service || config.mlApp,\n env: config.env || process.env.DD_ENV,\n // Disable automatic integrations by default to avoid surprise instrumentation\n plugins: config.integrationsEnabled ?? false,\n });\n }\n\n // Enable LLM Observability with the resolved configuration\n tracer.llmobs.enable({\n mlApp: config.mlApp,\n agentlessEnabled: config.agentless,\n });\n\n tracerInitFlag.done = true;\n}\n\n/**\n * Returns the Datadog kind for a Mastra span type.\n */\nexport function kindFor(spanType: SpanType): DatadogSpanKind {\n return SPAN_TYPE_TO_KIND[spanType] || 'task';\n}\n\n/**\n * Converts a value to a Date object.\n */\nexport function toDate(value: Date | string | number): Date {\n return value instanceof Date ? value : new Date(value);\n}\n\n/**\n * Safely stringifies data, handling circular references.\n */\nexport function safeStringify(data: unknown): string {\n try {\n return JSON.stringify(data);\n } catch {\n if (typeof data === 'object' && data !== null) {\n return `[Non-serializable ${data.constructor?.name || 'Object'}]`;\n }\n return String(data);\n }\n}\n\n/**\n * Checks if data is already in message array format ({role, content}[]).\n */\nfunction isMessageArray(data: any): data is Array<{ role: string; content: any }> {\n return Array.isArray(data) && data.every(m => m?.role && m?.content !== undefined);\n}\n\n/**\n * Formats input data for Datadog annotations.\n * LLM spans use message array format; others use raw or stringified data.\n */\nexport function formatInput(input: any, spanType: SpanType): any {\n // LLM spans expect {role, content}[] format\n if (spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP) {\n // Already in message format\n if (isMessageArray(input)) {\n return input.map(m => ({\n role: m.role,\n content: typeof m.content === 'string' ? m.content : safeStringify(m.content),\n }));\n }\n // String input becomes user message\n if (typeof input === 'string') {\n return [{ role: 'user', content: input }];\n }\n // Object input gets stringified as user message\n return [{ role: 'user', content: safeStringify(input) }];\n }\n\n // Non-LLM spans: pass through strings/arrays, stringify objects\n if (typeof input === 'string' || Array.isArray(input)) return input;\n return safeStringify(input);\n}\n\n/**\n * Formats output data for Datadog annotations.\n * LLM spans use message array format; others use raw or stringified data.\n */\nexport function formatOutput(output: any, spanType: SpanType): any {\n // LLM spans expect {role, content}[] format\n if (spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP) {\n // Already in message format\n if (isMessageArray(output)) {\n return output.map(m => ({\n role: m.role,\n content: typeof m.content === 'string' ? m.content : safeStringify(m.content),\n }));\n }\n // String output becomes assistant message\n if (typeof output === 'string') {\n return [{ role: 'assistant', content: output }];\n }\n // Object with text property (common AI SDK format)\n if (output?.text) {\n return [{ role: 'assistant', content: output.text }];\n }\n // Other objects get stringified as assistant message\n return [{ role: 'assistant', content: safeStringify(output) }];\n }\n\n // Non-LLM spans: pass through strings, stringify objects\n if (typeof output === 'string') return output;\n return safeStringify(output);\n}\n","/**\n * Datadog LLM Observability Exporter for Mastra\n *\n * Exports Mastra observability data to Datadog's LLM Observability product.\n * Uses a completion-only pattern where spans are emitted on span_ended events.\n *\n * Key features:\n * - Maps Mastra span types to Datadog span kinds\n * - Normalizes AI SDK v4/v5 token usage formats\n * - Formats LLM inputs/outputs as message arrays\n * - Flattens metadata into searchable tags\n * - Supports both agent and agentless modes\n */\n\nimport type {\n TracingEvent,\n AnyExportedSpan,\n ModelGenerationAttributes,\n ModelStepAttributes,\n} from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport { omitKeys } from '@mastra/core/utils';\nimport { BaseExporter } from '@mastra/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport tracer from 'dd-trace';\nimport { formatUsageMetrics } from './metrics';\nimport { ensureTracer, kindFor, toDate, formatInput, formatOutput } from './utils';\nimport type { DatadogSpanKind } from './utils';\n\n/**\n * LLMObs span options with required name and kind properties.\n */\ninterface LLMObsSpanOptions {\n kind: DatadogSpanKind;\n name: string;\n sessionId?: string;\n userId?: string;\n mlApp?: string;\n modelName?: string;\n modelProvider?: string;\n startTime?: Date;\n endTime?: Date;\n}\n\n/**\n * Minimal per-trace context for user/session tagging.\n */\ninterface TraceContext {\n userId?: string;\n sessionId?: string;\n}\n\ntype TraceState = {\n buffer: Map<string, AnyExportedSpan>;\n contexts: Map<string, { ddSpan: any; exported?: { traceId: string; spanId: string } }>;\n rootEnded: boolean;\n treeEmitted: boolean; // Whether the initial span tree has been emitted\n createdAt: number;\n cleanupTimer?: ReturnType<typeof setTimeout>;\n maxLifetimeTimer?: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Tree node representing a span and its children for recursive emission.\n */\ninterface SpanNode {\n span: AnyExportedSpan;\n children: SpanNode[];\n}\n\n/**\n * Maximum lifetime for a trace state entry (30 minutes).\n * This is a fallback cleanup mechanism for traces that never receive a root span\n * or have all spans marked as non-root, preventing unbounded memory growth.\n */\nconst MAX_TRACE_LIFETIME_MS = 30 * 60 * 1000;\n\n/**\n * Regular cleanup interval for trace state entries (1 minute).\n */\nconst REGULAR_CLEANUP_INTERVAL_MS = 1 * 60 * 1000;\n\n/**\n * Configuration options for the Datadog LLM Observability exporter.\n */\nexport interface DatadogExporterConfig extends BaseExporterConfig {\n /**\n * Datadog API key. Required (agentless mode is the default).\n * Falls back to DD_API_KEY environment variable.\n */\n apiKey?: string;\n\n /**\n * ML application name for grouping traces.\n * Required - falls back to DD_LLMOBS_ML_APP environment variable.\n */\n mlApp?: string;\n\n /**\n * Datadog site (e.g., 'datadoghq.com', 'datadoghq.eu').\n * Falls back to DD_SITE environment variable, defaults to 'datadoghq.com'.\n */\n site?: string;\n\n /**\n * Service name for the application.\n * Falls back to mlApp if not specified.\n */\n service?: string;\n\n /**\n * Environment name (e.g., 'production', 'staging').\n * Falls back to DD_ENV environment variable.\n */\n env?: string;\n\n /**\n * Use agentless mode (direct HTTPS intake without local Datadog Agent).\n * Defaults to true for consistency with other Mastra exporters.\n * Set to false to use a local Datadog Agent instead.\n * Falls back to DD_LLMOBS_AGENTLESS_ENABLED environment variable.\n */\n agentless?: boolean;\n\n /**\n * Enable dd-trace automatic integrations.\n * Defaults to false to avoid unexpected instrumentation.\n */\n integrationsEnabled?: boolean;\n}\n\n/**\n * Datadog LLM Observability Exporter for Mastra.\n *\n * Exports observability data to Datadog's LLM Observability product using\n * a completion-only pattern where spans are emitted on span_ended events.\n */\nexport class DatadogExporter extends BaseExporter {\n name = 'datadog';\n\n private config: Required<Pick<DatadogExporterConfig, 'mlApp' | 'site'>> & DatadogExporterConfig;\n private traceContext = new Map<string, TraceContext>();\n private traceState = new Map<string, TraceState>();\n\n constructor(config: DatadogExporterConfig = {}) {\n super(config);\n\n // Resolve configuration from config object and environment variables\n const mlApp = config.mlApp || process.env.DD_LLMOBS_ML_APP;\n const apiKey = config.apiKey || process.env.DD_API_KEY;\n const site = config.site || process.env.DD_SITE || 'datadoghq.com';\n\n // Default to agentless mode (true) for consistency with other Mastra exporters\n // Only disable if explicitly set to false via config or env var\n const envAgentless = process.env.DD_LLMOBS_AGENTLESS_ENABLED?.toLowerCase();\n const agentless = config.agentless ?? (envAgentless === 'false' || envAgentless === '0' ? false : true);\n\n // Validate required configuration\n if (!mlApp) {\n this.setDisabled('Missing required mlApp (set config.mlApp or DD_LLMOBS_ML_APP)');\n this.config = config as any;\n return;\n }\n\n if (agentless && !apiKey) {\n this.setDisabled('Missing required apiKey (set config.apiKey or DD_API_KEY)');\n this.config = config as any;\n return;\n }\n\n this.config = { ...config, mlApp, site, apiKey, agentless };\n\n // Initialize tracer and enable LLM Observability\n ensureTracer({\n mlApp,\n site,\n apiKey,\n agentless,\n service: config.service,\n env: config.env,\n integrationsEnabled: config.integrationsEnabled,\n });\n\n this.logger.info('Datadog exporter initialized', { mlApp, site, agentless });\n }\n\n /**\n * Main entry point for tracing events from Mastra.\n */\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (this.isDisabled || !(tracer as any).llmobs) return;\n\n try {\n const span = event.exportedSpan;\n\n // Handle event spans (zero-duration spans) - buffer like regular spans for parent-first emission\n if (span.isEvent) {\n if (event.type === 'span_started') {\n this.captureTraceContext(span);\n this.enqueueSpan(span); // Route through buffer for proper parent context\n }\n return; // Skip span_updated and span_ended for events\n }\n\n // Handle regular spans based on event type\n switch (event.type) {\n case 'span_started':\n this.captureTraceContext(span);\n return;\n\n case 'span_updated':\n // No-op: completion-only pattern ignores mid-span updates\n return;\n\n case 'span_ended':\n this.enqueueSpan(span);\n return;\n }\n } catch (error) {\n this.logger.error('Datadog exporter error', {\n error,\n eventType: event.type,\n spanId: event.exportedSpan?.id,\n spanName: event.exportedSpan?.name,\n });\n }\n }\n\n /**\n * Captures user/session context from root spans for tagging all spans in the trace.\n */\n private captureTraceContext(span: AnyExportedSpan): void {\n if (span.isRootSpan && !this.traceContext.has(span.traceId)) {\n this.traceContext.set(span.traceId, {\n userId: span.metadata?.userId,\n sessionId: span.metadata?.sessionId,\n });\n }\n }\n\n /**\n * Queue span until its parent context is available, then emit spans parent-first.\n */\n private enqueueSpan(span: AnyExportedSpan): void {\n const state = this.getOrCreateTraceState(span.traceId);\n if (span.isRootSpan) {\n state.rootEnded = true;\n }\n\n state.buffer.set(span.id, span);\n this.tryEmitReadySpans(span.traceId);\n }\n\n /**\n * Builds annotations object for llmobs.annotate().\n * Uses dd-trace's expected property names: inputData, outputData, metadata, tags, metrics.\n */\n private buildAnnotations(span: AnyExportedSpan): Record<string, any> {\n const annotations: Record<string, any> = {};\n\n // Format and add input (dd-trace expects 'inputData')\n if (span.input !== undefined) {\n annotations.inputData = formatInput(span.input, span.type);\n }\n\n // Format and add output (dd-trace expects 'outputData')\n if (span.output !== undefined) {\n annotations.outputData = formatOutput(span.output, span.type);\n }\n\n // Add token usage metrics (only on MODEL_GENERATION or MODEL_STEP spans)\n if (span.type === SpanType.MODEL_GENERATION || span.type === SpanType.MODEL_STEP) {\n const usage = (span.attributes as ModelGenerationAttributes | ModelStepAttributes)?.usage;\n const metrics = formatUsageMetrics(usage);\n if (metrics) {\n annotations.metrics = metrics;\n }\n }\n\n // Forward span.attributes to metadata (minus known fields handled separately)\n // This ensures tool/workflow spans preserve custom attributes like other exporters\n const knownFields = ['usage', 'model', 'provider', 'parameters'];\n const otherAttributes = omitKeys((span.attributes ?? {}) as Record<string, any>, knownFields);\n\n // Merge span.metadata + remaining attributes into metadata\n const combinedMetadata = {\n ...span.metadata,\n ...otherAttributes,\n };\n if (Object.keys(combinedMetadata).length > 0) {\n annotations.metadata = combinedMetadata;\n }\n\n // Build tags from span.tags (user-provided string[] converted to object) and error info\n // Datadog annotation tags accept Record<string, any>, so we use proper types\n // The native span error status is also set via ddSpan.setTag('error', true) in emitSpan()\n const tags: Record<string, any> = {};\n\n // Convert span.tags (string[]) to object format - each tag becomes a key with value true\n if (span.tags?.length) {\n for (const tag of span.tags) {\n tags[tag] = true;\n }\n }\n\n // Add error info as consolidated tags\n if (span.errorInfo) {\n tags.error = true;\n tags.errorInfo = {\n message: span.errorInfo.message,\n ...(span.errorInfo.id ? { id: span.errorInfo.id } : {}),\n ...(span.errorInfo.domain ? { domain: span.errorInfo.domain } : {}),\n ...(span.errorInfo.category ? { category: span.errorInfo.category } : {}),\n };\n }\n\n if (Object.keys(tags).length > 0) {\n annotations.tags = tags;\n }\n\n return annotations;\n }\n\n /**\n * Gracefully shuts down the exporter.\n */\n async shutdown(): Promise<void> {\n // Cancel all pending cleanup timers and clear state FIRST\n for (const [traceId, state] of this.traceState) {\n if (state.cleanupTimer) {\n clearTimeout(state.cleanupTimer);\n }\n if (state.maxLifetimeTimer) {\n clearTimeout(state.maxLifetimeTimer);\n }\n if (state.buffer.size > 0) {\n this.logger.warn('Shutdown with pending spans', {\n traceId,\n pendingCount: state.buffer.size,\n spanIds: Array.from(state.buffer.keys()),\n });\n }\n }\n this.traceState.clear();\n\n // Flush any pending data\n if (tracer.llmobs?.flush) {\n try {\n await tracer.llmobs.flush();\n } catch (e) {\n this.logger.error('Error flushing llmobs', { error: e });\n }\n } else if ((tracer as any).flush) {\n try {\n await (tracer as any).flush();\n } catch (e) {\n this.logger.error('Error flushing tracer', { error: e });\n }\n }\n\n // Disable LLM Observability\n if (tracer.llmobs?.disable) {\n try {\n tracer.llmobs.disable();\n } catch (e) {\n this.logger.error('Error disabling llmobs', { error: e });\n }\n }\n\n // Clear local state\n this.traceContext.clear();\n\n await super.shutdown();\n }\n\n /**\n * Retrieve or initialize trace state for buffering and parent tracking.\n */\n private getOrCreateTraceState(traceId: string): TraceState {\n const existing = this.traceState.get(traceId);\n if (existing) {\n if (existing.cleanupTimer) {\n clearTimeout(existing.cleanupTimer);\n existing.cleanupTimer = undefined;\n }\n return existing;\n }\n\n const created: TraceState = {\n buffer: new Map<string, AnyExportedSpan>(),\n contexts: new Map<string, { ddSpan: any; exported?: { traceId: string; spanId: string } }>(),\n rootEnded: false,\n treeEmitted: false,\n createdAt: Date.now(),\n cleanupTimer: undefined,\n maxLifetimeTimer: undefined,\n };\n\n // Schedule fallback cleanup after max lifetime to prevent memory leaks\n // when traces never receive a root span or all spans are non-root\n const maxLifetimeTimer = setTimeout(() => {\n const state = this.traceState.get(traceId);\n if (state) {\n if (state.buffer.size > 0 || state.contexts.size > 0) {\n this.logger.warn('Discarding trace due to max lifetime exceeded', {\n traceId,\n bufferedSpans: state.buffer.size,\n emittedSpans: state.contexts.size,\n lifetimeMs: Date.now() - state.createdAt,\n });\n }\n if (state.cleanupTimer) {\n clearTimeout(state.cleanupTimer);\n }\n this.traceState.delete(traceId);\n this.traceContext.delete(traceId);\n }\n }, MAX_TRACE_LIFETIME_MS);\n // Prevent the timer from keeping the process alive\n (maxLifetimeTimer as any).unref?.();\n created.maxLifetimeTimer = maxLifetimeTimer;\n\n this.traceState.set(traceId, created);\n return created;\n }\n\n /**\n * Attempt to emit spans from the buffer.\n *\n * Two modes of operation:\n * 1. Initial tree emission: When root span ends and tree hasn't been emitted yet,\n * build a tree from all buffered spans and emit recursively using nested\n * llmobs.trace() calls. This ensures proper parent-child relationships in Datadog.\n * 2. Late-arriving spans: After the tree has been emitted, emit individual spans\n * with their parent context for proper linking.\n */\n private tryEmitReadySpans(traceId: string): void {\n const state = this.traceState.get(traceId);\n if (!state) return;\n\n // If tree hasn't been emitted yet, wait for root and emit as tree\n if (!state.treeEmitted) {\n // Wait until the root span has ended before emitting any spans\n if (!state.rootEnded) return;\n\n // Build tree and emit recursively\n const tree = this.buildSpanTree(state.buffer);\n if (tree) {\n this.emitSpanTree(tree, state);\n }\n\n // Clear the buffer and mark tree as emitted\n state.buffer.clear();\n state.treeEmitted = true;\n } else {\n // Tree already emitted - handle late-arriving spans individually\n // Use the old parent-first emission pattern for these\n let emitted = false;\n do {\n emitted = false;\n for (const [spanId, span] of state.buffer) {\n const parentCtx = span.parentSpanId ? state.contexts.get(span.parentSpanId) : undefined;\n if (span.parentSpanId && !parentCtx) {\n continue;\n }\n\n this.emitSingleSpan(span, state, parentCtx?.ddSpan);\n state.buffer.delete(spanId);\n emitted = true;\n }\n } while (emitted);\n }\n\n // Schedule cleanup if root has ended and buffer is empty\n if (state.rootEnded && state.buffer.size === 0 && !state.cleanupTimer) {\n const timer = setTimeout(() => {\n const currentState = this.traceState.get(traceId);\n if (currentState) {\n if (currentState.buffer.size > 0) {\n this.logger.warn('Discarding orphaned spans during cleanup', {\n traceId,\n orphanedCount: currentState.buffer.size,\n spanIds: Array.from(currentState.buffer.keys()),\n });\n }\n // Clear the max lifetime timer since normal cleanup is handling this\n if (currentState.maxLifetimeTimer) {\n clearTimeout(currentState.maxLifetimeTimer);\n }\n }\n this.traceState.delete(traceId);\n this.traceContext.delete(traceId);\n }, REGULAR_CLEANUP_INTERVAL_MS);\n // Prevent the timer from keeping the process alive\n (timer as any).unref?.();\n state.cleanupTimer = timer;\n }\n }\n\n /**\n * Builds a tree structure from buffered spans based on parentSpanId relationships.\n * Returns the root node of the tree, or undefined if no root span is found.\n */\n private buildSpanTree(buffer: Map<string, AnyExportedSpan>): SpanNode | undefined {\n // Create nodes for all spans\n const nodes = new Map<string, SpanNode>();\n let rootNode: SpanNode | undefined;\n\n for (const span of buffer.values()) {\n nodes.set(span.id, { span, children: [] });\n }\n\n // Build parent-child relationships\n for (const node of nodes.values()) {\n if (node.span.isRootSpan) {\n rootNode = node;\n } else if (node.span.parentSpanId) {\n const parentNode = nodes.get(node.span.parentSpanId);\n if (parentNode) {\n parentNode.children.push(node);\n } else {\n // Orphaned span - parent not in buffer, treat as root-level\n // This shouldn't happen normally but handles edge cases\n this.logger.warn('Orphaned span detected during tree build', {\n spanId: node.span.id,\n parentSpanId: node.span.parentSpanId,\n traceId: node.span.traceId,\n });\n }\n }\n }\n\n // Sort children by start time for consistent ordering\n for (const node of nodes.values()) {\n node.children.sort((a, b) => {\n const aTime =\n a.span.startTime instanceof Date ? a.span.startTime.getTime() : new Date(a.span.startTime).getTime();\n const bTime =\n b.span.startTime instanceof Date ? b.span.startTime.getTime() : new Date(b.span.startTime).getTime();\n return aTime - bTime;\n });\n }\n\n return rootNode;\n }\n\n /**\n * Builds LLMObs span options from a Mastra span.\n * Handles trace context, timestamps, and conditional model information for LLM spans.\n */\n private buildSpanOptions(span: AnyExportedSpan): LLMObsSpanOptions {\n const traceCtx = this.traceContext.get(span.traceId) || {\n userId: span.metadata?.userId,\n sessionId: span.metadata?.sessionId,\n };\n\n const kind = kindFor(span.type);\n const attrs = span.attributes as ModelGenerationAttributes | undefined;\n\n const startTime = toDate(span.startTime);\n // Event spans are point-in-time markers; use startTime for endTime if not set (zero duration)\n // Regular spans fall back to current time if endTime is not set\n const endTime = span.endTime ? toDate(span.endTime) : span.isEvent ? startTime : new Date();\n\n return {\n kind,\n name: span.name,\n sessionId: traceCtx.sessionId,\n userId: traceCtx.userId,\n startTime,\n endTime,\n ...(kind === 'llm' && attrs?.model ? { modelName: attrs.model } : {}),\n ...(kind === 'llm' && attrs?.provider ? { modelProvider: attrs.provider } : {}),\n };\n }\n\n /**\n * Recursively emits a span tree using nested llmobs.trace() calls.\n * This ensures parent-child relationships are properly established in Datadog\n * because child spans are created while their parent span is active in scope.\n */\n private emitSpanTree(node: SpanNode, state: TraceState): void {\n const span = node.span;\n const options = this.buildSpanOptions(span);\n\n // Use nested llmobs.trace() calls - children are emitted INSIDE the parent's callback\n // This ensures the Datadog SDK automatically establishes parent-child relationships\n tracer.llmobs.trace(options as any, (ddSpan: any) => {\n // Annotate this span\n const annotations = this.buildAnnotations(span);\n if (Object.keys(annotations).length > 0) {\n tracer.llmobs.annotate(ddSpan, annotations);\n }\n\n // Set native Datadog error status for proper UI highlighting\n if (span.errorInfo) {\n ddSpan.setTag('error', true);\n }\n\n // Store context for potential evaluation submissions\n const exported = tracer.llmobs.exportSpan ? tracer.llmobs.exportSpan(ddSpan) : undefined;\n state.contexts.set(span.id, { ddSpan, exported });\n\n // Recursively emit children INSIDE this span's callback\n // This is the key to establishing proper parent-child relationships\n for (const child of node.children) {\n this.emitSpanTree(child, state);\n }\n });\n }\n\n /**\n * Emit a single span with the proper Datadog parent context.\n * Used for late-arriving spans after the main tree has been emitted.\n */\n private emitSingleSpan(span: AnyExportedSpan, state: TraceState, parent?: any) {\n const options = this.buildSpanOptions(span);\n\n const runTrace = () =>\n tracer.llmobs.trace(options as any, (ddSpan: any) => {\n const annotations = this.buildAnnotations(span);\n if (Object.keys(annotations).length > 0) {\n tracer.llmobs.annotate(ddSpan, annotations);\n }\n\n // Set native Datadog error status for proper UI highlighting\n if (span.errorInfo) {\n ddSpan.setTag('error', true);\n }\n\n const exported = tracer.llmobs.exportSpan ? tracer.llmobs.exportSpan(ddSpan) : undefined;\n state.contexts.set(span.id, { ddSpan, exported });\n });\n\n if (parent) {\n tracer.scope().activate(parent, runTrace);\n } else {\n runTrace();\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/metrics.ts","../src/utils.ts","../src/tracing.ts"],"names":["tracer","SpanType"],"mappings":"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","file":"index.js","sourcesContent":["import type { UsageStats } from '@mastra/core/observability';\nimport type tracer from 'dd-trace';\n\ntype DatadogAnnotationMetrics = tracer.llmobs.AnnotationOptions['metrics'];\n\nexport function formatUsageMetrics(usage?: UsageStats): DatadogAnnotationMetrics | undefined {\n if (!usage) return undefined;\n\n const result: DatadogAnnotationMetrics = {};\n\n const inputTokens = usage.inputTokens;\n if (inputTokens !== undefined) result.inputTokens = inputTokens;\n\n const outputTokens = usage.outputTokens;\n if (outputTokens !== undefined) result.outputTokens = outputTokens;\n\n if (inputTokens !== undefined && outputTokens !== undefined) {\n result.totalTokens = inputTokens + outputTokens;\n }\n\n if (usage?.outputDetails?.reasoning !== undefined) {\n result.reasoningTokens = usage.outputDetails.reasoning;\n }\n\n const cachedTokens = usage?.inputDetails?.cacheRead;\n if (cachedTokens !== undefined) {\n result.cachedInputTokens = cachedTokens;\n }\n\n const cachedOutputTokens = usage?.inputDetails?.cacheWrite;\n if (cachedOutputTokens !== undefined) {\n result.cachedOutputTokens = cachedOutputTokens;\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n","/**\n * Utility functions for Datadog LLM Observability Exporter\n */\n\nimport { SpanType } from '@mastra/core/observability';\nimport tracer from 'dd-trace';\n\n/**\n * Datadog LLM Observability span kinds.\n */\nexport type DatadogSpanKind = 'llm' | 'agent' | 'workflow' | 'tool' | 'task' | 'retrieval' | 'embedding';\n\n/**\n * Maps Mastra SpanTypes to Datadog LLMObs span kinds.\n * Only non-task mappings are defined; unmapped types fall back to 'task'.\n */\nexport const SPAN_TYPE_TO_KIND: Partial<Record<SpanType, DatadogSpanKind>> = {\n [SpanType.AGENT_RUN]: 'agent',\n [SpanType.MODEL_GENERATION]: 'workflow',\n [SpanType.MODEL_STEP]: 'llm',\n [SpanType.TOOL_CALL]: 'tool',\n [SpanType.MCP_TOOL_CALL]: 'tool',\n [SpanType.WORKFLOW_RUN]: 'workflow',\n};\n\n/**\n * Singleton flag to prevent multiple tracer initializations.\n * dd-trace should only be initialized once per process.\n */\nconst tracerInitFlag = { done: false };\n\n/**\n * Ensures dd-trace is initialized exactly once.\n * Respects any existing tracer initialization by the application.\n */\nexport function ensureTracer(config: {\n mlApp: string;\n site: string;\n apiKey?: string;\n agentless: boolean;\n service?: string;\n env?: string;\n integrationsEnabled?: boolean;\n}): void {\n if (tracerInitFlag.done) return;\n\n // Set environment variables for dd-trace to pick up\n // (LLMObsEnableOptions only accepts mlApp and agentlessEnabled)\n // Always set when config is provided to ensure explicit config takes precedence\n // over any stale env vars that may already be set in the process\n if (config.site) {\n process.env.DD_SITE = config.site;\n }\n if (config.apiKey) {\n process.env.DD_API_KEY = config.apiKey;\n }\n\n // Check if tracer was already started by the application\n const alreadyStarted = (tracer as any)._tracer?.started;\n\n if (!alreadyStarted) {\n tracer.init({\n service: config.service || config.mlApp,\n env: config.env || process.env.DD_ENV,\n // Disable automatic integrations by default to avoid surprise instrumentation\n plugins: config.integrationsEnabled ?? false,\n });\n }\n\n // Enable LLM Observability with the resolved configuration\n tracer.llmobs.enable({\n mlApp: config.mlApp,\n agentlessEnabled: config.agentless,\n });\n\n tracerInitFlag.done = true;\n}\n\n/**\n * Returns the Datadog kind for a Mastra span type.\n */\nexport function kindFor(spanType: SpanType): DatadogSpanKind {\n return SPAN_TYPE_TO_KIND[spanType] || 'task';\n}\n\n/**\n * Converts a value to a Date object.\n */\nexport function toDate(value: Date | string | number): Date {\n return value instanceof Date ? value : new Date(value);\n}\n\n/**\n * Safely stringifies data, handling circular references.\n */\nexport function safeStringify(data: unknown): string {\n try {\n return JSON.stringify(data);\n } catch {\n if (typeof data === 'object' && data !== null) {\n return `[Non-serializable ${data.constructor?.name || 'Object'}]`;\n }\n return String(data);\n }\n}\n\n/**\n * Checks if data is already in message array format ({role, content}[]).\n */\nfunction isMessageArray(data: any): data is Array<{ role: string; content: any }> {\n return Array.isArray(data) && data.every(m => m?.role && m?.content !== undefined);\n}\n\n/**\n * Formats input data for Datadog annotations.\n * LLM spans use message array format; others use raw or stringified data.\n */\nexport function formatInput(input: any, spanType: SpanType): any {\n // LLM spans expect {role, content}[] format\n if (spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP) {\n // Already in message format\n if (isMessageArray(input)) {\n return input.map(m => ({\n role: m.role,\n content: typeof m.content === 'string' ? m.content : safeStringify(m.content),\n }));\n }\n // String input becomes user message\n if (typeof input === 'string') {\n return [{ role: 'user', content: input }];\n }\n // Object input gets stringified as user message\n return [{ role: 'user', content: safeStringify(input) }];\n }\n\n // Non-LLM spans: pass through strings/arrays, stringify objects\n if (typeof input === 'string' || Array.isArray(input)) return input;\n return safeStringify(input);\n}\n\n/**\n * Formats output data for Datadog annotations.\n * LLM spans use message array format; others use raw or stringified data.\n */\nexport function formatOutput(output: any, spanType: SpanType): any {\n // LLM spans expect {role, content}[] format\n if (spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP) {\n // Already in message format\n if (isMessageArray(output)) {\n return output.map(m => ({\n role: m.role,\n content: typeof m.content === 'string' ? m.content : safeStringify(m.content),\n }));\n }\n // String output becomes assistant message\n if (typeof output === 'string') {\n return [{ role: 'assistant', content: output }];\n }\n // Object with text property (common AI SDK format)\n if (output?.text) {\n return [{ role: 'assistant', content: output.text }];\n }\n // Other objects get stringified as assistant message\n return [{ role: 'assistant', content: safeStringify(output) }];\n }\n\n // Non-LLM spans: pass through strings, stringify objects\n if (typeof output === 'string') return output;\n return safeStringify(output);\n}\n","/**\n * Datadog LLM Observability Exporter for Mastra\n *\n * Exports Mastra observability data to Datadog's LLM Observability product.\n * Uses a completion-only pattern where spans are emitted on span_ended events.\n *\n * Key features:\n * - Maps Mastra span types to Datadog span kinds\n * - Normalizes AI SDK v4/v5 token usage formats\n * - Formats LLM inputs/outputs as message arrays\n * - Flattens metadata into searchable tags\n * - Supports both agent and agentless modes\n */\n\nimport type {\n TracingEvent,\n AnyExportedSpan,\n ModelGenerationAttributes,\n ModelStepAttributes,\n} from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport { omitKeys } from '@mastra/core/utils';\nimport { BaseExporter } from '@mastra/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport tracer from 'dd-trace';\nimport { formatUsageMetrics } from './metrics';\nimport { ensureTracer, kindFor, toDate, formatInput, formatOutput } from './utils';\nimport type { DatadogSpanKind } from './utils';\n\n/**\n * LLMObs span options with required name and kind properties.\n */\ninterface LLMObsSpanOptions {\n kind: DatadogSpanKind;\n name: string;\n sessionId?: string;\n userId?: string;\n mlApp?: string;\n modelName?: string;\n modelProvider?: string;\n startTime?: Date;\n endTime?: Date;\n}\n\n/**\n * Minimal per-trace context for user/session tagging.\n */\ninterface TraceContext {\n userId?: string;\n sessionId?: string;\n}\n\ntype TraceState = {\n buffer: Map<string, AnyExportedSpan>;\n contexts: Map<string, { ddSpan: any; exported?: { traceId: string; spanId: string } }>;\n rootEnded: boolean;\n treeEmitted: boolean; // Whether the initial span tree has been emitted\n createdAt: number;\n cleanupTimer?: ReturnType<typeof setTimeout>;\n maxLifetimeTimer?: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Tree node representing a span and its children for recursive emission.\n */\ninterface SpanNode {\n span: AnyExportedSpan;\n children: SpanNode[];\n}\n\n/**\n * Maximum lifetime for a trace state entry (30 minutes).\n * This is a fallback cleanup mechanism for traces that never receive a root span\n * or have all spans marked as non-root, preventing unbounded memory growth.\n */\nconst MAX_TRACE_LIFETIME_MS = 30 * 60 * 1000;\n\n/**\n * Regular cleanup interval for trace state entries (1 minute).\n */\nconst REGULAR_CLEANUP_INTERVAL_MS = 1 * 60 * 1000;\n\n/**\n * Configuration options for the Datadog LLM Observability exporter.\n */\nexport interface DatadogExporterConfig extends BaseExporterConfig {\n /**\n * Datadog API key. Required (agentless mode is the default).\n * Falls back to DD_API_KEY environment variable.\n */\n apiKey?: string;\n\n /**\n * ML application name for grouping traces.\n * Required - falls back to DD_LLMOBS_ML_APP environment variable.\n */\n mlApp?: string;\n\n /**\n * Datadog site (e.g., 'datadoghq.com', 'datadoghq.eu').\n * Falls back to DD_SITE environment variable, defaults to 'datadoghq.com'.\n */\n site?: string;\n\n /**\n * Service name for the application.\n * Falls back to mlApp if not specified.\n */\n service?: string;\n\n /**\n * Environment name (e.g., 'production', 'staging').\n * Falls back to DD_ENV environment variable.\n */\n env?: string;\n\n /**\n * Use agentless mode (direct HTTPS intake without local Datadog Agent).\n * Defaults to true for consistency with other Mastra exporters.\n * Set to false to use a local Datadog Agent instead.\n * Falls back to DD_LLMOBS_AGENTLESS_ENABLED environment variable.\n */\n agentless?: boolean;\n\n /**\n * Enable dd-trace automatic integrations.\n * Defaults to false to avoid unexpected instrumentation.\n */\n integrationsEnabled?: boolean;\n}\n\n/**\n * Datadog LLM Observability Exporter for Mastra.\n *\n * Exports observability data to Datadog's LLM Observability product using\n * a completion-only pattern where spans are emitted on span_ended events.\n */\nexport class DatadogExporter extends BaseExporter {\n name = 'datadog';\n\n private config: Required<Pick<DatadogExporterConfig, 'mlApp' | 'site'>> & DatadogExporterConfig;\n private traceContext = new Map<string, TraceContext>();\n private traceState = new Map<string, TraceState>();\n\n constructor(config: DatadogExporterConfig = {}) {\n super(config);\n\n // Resolve configuration from config object and environment variables\n const mlApp = config.mlApp ?? process.env.DD_LLMOBS_ML_APP;\n const apiKey = config.apiKey ?? process.env.DD_API_KEY;\n const site = config.site ?? process.env.DD_SITE ?? 'datadoghq.com';\n const env = config.env ?? process.env.DD_ENV;\n\n // Default to agentless mode (true) for consistency with other Mastra exporters\n // Only disable if explicitly set to false via config or env var\n const envAgentless = process.env.DD_LLMOBS_AGENTLESS_ENABLED?.toLowerCase();\n const agentless = config.agentless ?? (envAgentless === 'false' || envAgentless === '0' ? false : true);\n\n // Validate required configuration\n if (!mlApp) {\n this.setDisabled(`Missing required mlApp. Set DD_LLMOBS_ML_APP environment variable or pass mlApp in config.`);\n this.config = config as any;\n return;\n }\n\n if (agentless && !apiKey) {\n this.setDisabled(\n `Missing required apiKey for agentless mode. Set DD_API_KEY environment variable or pass apiKey in config.`,\n );\n this.config = config as any;\n return;\n }\n\n this.config = { ...config, mlApp, site, apiKey, agentless, env };\n\n // Initialize tracer and enable LLM Observability\n ensureTracer({\n mlApp,\n site,\n apiKey,\n agentless,\n service: config.service,\n env,\n integrationsEnabled: config.integrationsEnabled,\n });\n\n this.logger.info('Datadog exporter initialized', { mlApp, site, agentless });\n }\n\n /**\n * Main entry point for tracing events from Mastra.\n */\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (this.isDisabled || !(tracer as any).llmobs) return;\n\n try {\n const span = event.exportedSpan;\n\n // Handle event spans (zero-duration spans) - buffer like regular spans for parent-first emission\n if (span.isEvent) {\n if (event.type === 'span_started') {\n this.captureTraceContext(span);\n this.enqueueSpan(span); // Route through buffer for proper parent context\n }\n return; // Skip span_updated and span_ended for events\n }\n\n // Handle regular spans based on event type\n switch (event.type) {\n case 'span_started':\n this.captureTraceContext(span);\n return;\n\n case 'span_updated':\n // No-op: completion-only pattern ignores mid-span updates\n return;\n\n case 'span_ended':\n this.enqueueSpan(span);\n return;\n }\n } catch (error) {\n this.logger.error('Datadog exporter error', {\n error,\n eventType: event.type,\n spanId: event.exportedSpan?.id,\n spanName: event.exportedSpan?.name,\n });\n }\n }\n\n /**\n * Captures user/session context from root spans for tagging all spans in the trace.\n */\n private captureTraceContext(span: AnyExportedSpan): void {\n if (span.isRootSpan && !this.traceContext.has(span.traceId)) {\n this.traceContext.set(span.traceId, {\n userId: span.metadata?.userId,\n sessionId: span.metadata?.sessionId,\n });\n }\n }\n\n /**\n * Queue span until its parent context is available, then emit spans parent-first.\n */\n private enqueueSpan(span: AnyExportedSpan): void {\n const state = this.getOrCreateTraceState(span.traceId);\n if (span.isRootSpan) {\n state.rootEnded = true;\n }\n\n state.buffer.set(span.id, span);\n this.tryEmitReadySpans(span.traceId);\n }\n\n /**\n * Builds annotations object for llmobs.annotate().\n * Uses dd-trace's expected property names: inputData, outputData, metadata, tags, metrics.\n */\n private buildAnnotations(span: AnyExportedSpan): Record<string, any> {\n const annotations: Record<string, any> = {};\n\n // Format and add input (dd-trace expects 'inputData')\n if (span.input !== undefined) {\n annotations.inputData = formatInput(span.input, span.type);\n }\n\n // Format and add output (dd-trace expects 'outputData')\n if (span.output !== undefined) {\n annotations.outputData = formatOutput(span.output, span.type);\n }\n\n // Add token usage metrics (only on MODEL_GENERATION or MODEL_STEP spans)\n if (span.type === SpanType.MODEL_GENERATION || span.type === SpanType.MODEL_STEP) {\n const usage = (span.attributes as ModelGenerationAttributes | ModelStepAttributes)?.usage;\n const metrics = formatUsageMetrics(usage);\n if (metrics) {\n annotations.metrics = metrics;\n }\n }\n\n // Forward span.attributes to metadata (minus known fields handled separately)\n // This ensures tool/workflow spans preserve custom attributes like other exporters\n const knownFields = ['usage', 'model', 'provider', 'parameters'];\n const otherAttributes = omitKeys((span.attributes ?? {}) as Record<string, any>, knownFields);\n\n // Merge span.metadata + remaining attributes into metadata\n const combinedMetadata = {\n ...span.metadata,\n ...otherAttributes,\n };\n if (Object.keys(combinedMetadata).length > 0) {\n annotations.metadata = combinedMetadata;\n }\n\n // Build tags from span.tags (user-provided string[] converted to object) and error info\n // Datadog annotation tags accept Record<string, any>, so we use proper types\n // The native span error status is also set via ddSpan.setTag('error', true) in emitSpan()\n const tags: Record<string, any> = {};\n\n // Convert span.tags (string[]) to object format - each tag becomes a key with value true\n if (span.tags?.length) {\n for (const tag of span.tags) {\n tags[tag] = true;\n }\n }\n\n // Add error info as consolidated tags\n if (span.errorInfo) {\n tags.error = true;\n tags.errorInfo = {\n message: span.errorInfo.message,\n ...(span.errorInfo.id ? { id: span.errorInfo.id } : {}),\n ...(span.errorInfo.domain ? { domain: span.errorInfo.domain } : {}),\n ...(span.errorInfo.category ? { category: span.errorInfo.category } : {}),\n };\n }\n\n if (Object.keys(tags).length > 0) {\n annotations.tags = tags;\n }\n\n return annotations;\n }\n\n /**\n * Gracefully shuts down the exporter.\n */\n async shutdown(): Promise<void> {\n // Cancel all pending cleanup timers and clear state FIRST\n for (const [traceId, state] of this.traceState) {\n if (state.cleanupTimer) {\n clearTimeout(state.cleanupTimer);\n }\n if (state.maxLifetimeTimer) {\n clearTimeout(state.maxLifetimeTimer);\n }\n if (state.buffer.size > 0) {\n this.logger.warn('Shutdown with pending spans', {\n traceId,\n pendingCount: state.buffer.size,\n spanIds: Array.from(state.buffer.keys()),\n });\n }\n }\n this.traceState.clear();\n\n // Flush any pending data\n if (tracer.llmobs?.flush) {\n try {\n await tracer.llmobs.flush();\n } catch (e) {\n this.logger.error('Error flushing llmobs', { error: e });\n }\n } else if ((tracer as any).flush) {\n try {\n await (tracer as any).flush();\n } catch (e) {\n this.logger.error('Error flushing tracer', { error: e });\n }\n }\n\n // Disable LLM Observability\n if (tracer.llmobs?.disable) {\n try {\n tracer.llmobs.disable();\n } catch (e) {\n this.logger.error('Error disabling llmobs', { error: e });\n }\n }\n\n // Clear local state\n this.traceContext.clear();\n\n await super.shutdown();\n }\n\n /**\n * Retrieve or initialize trace state for buffering and parent tracking.\n */\n private getOrCreateTraceState(traceId: string): TraceState {\n const existing = this.traceState.get(traceId);\n if (existing) {\n if (existing.cleanupTimer) {\n clearTimeout(existing.cleanupTimer);\n existing.cleanupTimer = undefined;\n }\n return existing;\n }\n\n const created: TraceState = {\n buffer: new Map<string, AnyExportedSpan>(),\n contexts: new Map<string, { ddSpan: any; exported?: { traceId: string; spanId: string } }>(),\n rootEnded: false,\n treeEmitted: false,\n createdAt: Date.now(),\n cleanupTimer: undefined,\n maxLifetimeTimer: undefined,\n };\n\n // Schedule fallback cleanup after max lifetime to prevent memory leaks\n // when traces never receive a root span or all spans are non-root\n const maxLifetimeTimer = setTimeout(() => {\n const state = this.traceState.get(traceId);\n if (state) {\n if (state.buffer.size > 0 || state.contexts.size > 0) {\n this.logger.warn('Discarding trace due to max lifetime exceeded', {\n traceId,\n bufferedSpans: state.buffer.size,\n emittedSpans: state.contexts.size,\n lifetimeMs: Date.now() - state.createdAt,\n });\n }\n if (state.cleanupTimer) {\n clearTimeout(state.cleanupTimer);\n }\n this.traceState.delete(traceId);\n this.traceContext.delete(traceId);\n }\n }, MAX_TRACE_LIFETIME_MS);\n // Prevent the timer from keeping the process alive\n (maxLifetimeTimer as any).unref?.();\n created.maxLifetimeTimer = maxLifetimeTimer;\n\n this.traceState.set(traceId, created);\n return created;\n }\n\n /**\n * Attempt to emit spans from the buffer.\n *\n * Two modes of operation:\n * 1. Initial tree emission: When root span ends and tree hasn't been emitted yet,\n * build a tree from all buffered spans and emit recursively using nested\n * llmobs.trace() calls. This ensures proper parent-child relationships in Datadog.\n * 2. Late-arriving spans: After the tree has been emitted, emit individual spans\n * with their parent context for proper linking.\n */\n private tryEmitReadySpans(traceId: string): void {\n const state = this.traceState.get(traceId);\n if (!state) return;\n\n // If tree hasn't been emitted yet, wait for root and emit as tree\n if (!state.treeEmitted) {\n // Wait until the root span has ended before emitting any spans\n if (!state.rootEnded) return;\n\n // Build tree and emit recursively\n const tree = this.buildSpanTree(state.buffer);\n if (tree) {\n this.emitSpanTree(tree, state);\n }\n\n // Clear the buffer and mark tree as emitted\n state.buffer.clear();\n state.treeEmitted = true;\n } else {\n // Tree already emitted - handle late-arriving spans individually\n // Use the old parent-first emission pattern for these\n let emitted = false;\n do {\n emitted = false;\n for (const [spanId, span] of state.buffer) {\n const parentCtx = span.parentSpanId ? state.contexts.get(span.parentSpanId) : undefined;\n if (span.parentSpanId && !parentCtx) {\n continue;\n }\n\n this.emitSingleSpan(span, state, parentCtx?.ddSpan);\n state.buffer.delete(spanId);\n emitted = true;\n }\n } while (emitted);\n }\n\n // Schedule cleanup if root has ended and buffer is empty\n if (state.rootEnded && state.buffer.size === 0 && !state.cleanupTimer) {\n const timer = setTimeout(() => {\n const currentState = this.traceState.get(traceId);\n if (currentState) {\n if (currentState.buffer.size > 0) {\n this.logger.warn('Discarding orphaned spans during cleanup', {\n traceId,\n orphanedCount: currentState.buffer.size,\n spanIds: Array.from(currentState.buffer.keys()),\n });\n }\n // Clear the max lifetime timer since normal cleanup is handling this\n if (currentState.maxLifetimeTimer) {\n clearTimeout(currentState.maxLifetimeTimer);\n }\n }\n this.traceState.delete(traceId);\n this.traceContext.delete(traceId);\n }, REGULAR_CLEANUP_INTERVAL_MS);\n // Prevent the timer from keeping the process alive\n (timer as any).unref?.();\n state.cleanupTimer = timer;\n }\n }\n\n /**\n * Builds a tree structure from buffered spans based on parentSpanId relationships.\n * Returns the root node of the tree, or undefined if no root span is found.\n */\n private buildSpanTree(buffer: Map<string, AnyExportedSpan>): SpanNode | undefined {\n // Create nodes for all spans\n const nodes = new Map<string, SpanNode>();\n let rootNode: SpanNode | undefined;\n\n for (const span of buffer.values()) {\n nodes.set(span.id, { span, children: [] });\n }\n\n // Build parent-child relationships\n for (const node of nodes.values()) {\n if (node.span.isRootSpan) {\n rootNode = node;\n } else if (node.span.parentSpanId) {\n const parentNode = nodes.get(node.span.parentSpanId);\n if (parentNode) {\n parentNode.children.push(node);\n } else {\n // Orphaned span - parent not in buffer, treat as root-level\n // This shouldn't happen normally but handles edge cases\n this.logger.warn('Orphaned span detected during tree build', {\n spanId: node.span.id,\n parentSpanId: node.span.parentSpanId,\n traceId: node.span.traceId,\n });\n }\n }\n }\n\n // Sort children by start time for consistent ordering\n for (const node of nodes.values()) {\n node.children.sort((a, b) => {\n const aTime =\n a.span.startTime instanceof Date ? a.span.startTime.getTime() : new Date(a.span.startTime).getTime();\n const bTime =\n b.span.startTime instanceof Date ? b.span.startTime.getTime() : new Date(b.span.startTime).getTime();\n return aTime - bTime;\n });\n }\n\n return rootNode;\n }\n\n /**\n * Builds LLMObs span options from a Mastra span.\n * Handles trace context, timestamps, and conditional model information for LLM spans.\n */\n private buildSpanOptions(span: AnyExportedSpan): LLMObsSpanOptions {\n const traceCtx = this.traceContext.get(span.traceId) || {\n userId: span.metadata?.userId,\n sessionId: span.metadata?.sessionId,\n };\n\n const kind = kindFor(span.type);\n const attrs = span.attributes as ModelGenerationAttributes | undefined;\n\n const startTime = toDate(span.startTime);\n // Event spans are point-in-time markers; use startTime for endTime if not set (zero duration)\n // Regular spans fall back to current time if endTime is not set\n const endTime = span.endTime ? toDate(span.endTime) : span.isEvent ? startTime : new Date();\n\n return {\n kind,\n name: span.name,\n sessionId: traceCtx.sessionId,\n userId: traceCtx.userId,\n startTime,\n endTime,\n ...(kind === 'llm' && attrs?.model ? { modelName: attrs.model } : {}),\n ...(kind === 'llm' && attrs?.provider ? { modelProvider: attrs.provider } : {}),\n };\n }\n\n /**\n * Recursively emits a span tree using nested llmobs.trace() calls.\n * This ensures parent-child relationships are properly established in Datadog\n * because child spans are created while their parent span is active in scope.\n */\n private emitSpanTree(node: SpanNode, state: TraceState): void {\n const span = node.span;\n const options = this.buildSpanOptions(span);\n\n // Use nested llmobs.trace() calls - children are emitted INSIDE the parent's callback\n // This ensures the Datadog SDK automatically establishes parent-child relationships\n tracer.llmobs.trace(options as any, (ddSpan: any) => {\n // Annotate this span\n const annotations = this.buildAnnotations(span);\n if (Object.keys(annotations).length > 0) {\n tracer.llmobs.annotate(ddSpan, annotations);\n }\n\n // Set native Datadog error status for proper UI highlighting\n if (span.errorInfo) {\n ddSpan.setTag('error', true);\n }\n\n // Store context for potential evaluation submissions\n const exported = tracer.llmobs.exportSpan ? tracer.llmobs.exportSpan(ddSpan) : undefined;\n state.contexts.set(span.id, { ddSpan, exported });\n\n // Recursively emit children INSIDE this span's callback\n // This is the key to establishing proper parent-child relationships\n for (const child of node.children) {\n this.emitSpanTree(child, state);\n }\n });\n }\n\n /**\n * Emit a single span with the proper Datadog parent context.\n * Used for late-arriving spans after the main tree has been emitted.\n */\n private emitSingleSpan(span: AnyExportedSpan, state: TraceState, parent?: any) {\n const options = this.buildSpanOptions(span);\n\n const runTrace = () =>\n tracer.llmobs.trace(options as any, (ddSpan: any) => {\n const annotations = this.buildAnnotations(span);\n if (Object.keys(annotations).length > 0) {\n tracer.llmobs.annotate(ddSpan, annotations);\n }\n\n // Set native Datadog error status for proper UI highlighting\n if (span.errorInfo) {\n ddSpan.setTag('error', true);\n }\n\n const exported = tracer.llmobs.exportSpan ? tracer.llmobs.exportSpan(ddSpan) : undefined;\n state.contexts.set(span.id, { ddSpan, exported });\n });\n\n if (parent) {\n tracer.scope().activate(parent, runTrace);\n } else {\n runTrace();\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AA2DhE;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,IAAI,SAAa;IAEjB,OAAO,CAAC,MAAM,CAAkF;IAChG,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,UAAU,CAAiC;gBAEvC,MAAM,GAAE,qBAA0B;IA0C9C;;OAEG;cACa,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCvE;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAkExB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAiD/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgD7B;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IA+DzB;;;OAGG;IACH,OAAO,CAAC,aAAa;IA2CrB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IA8BpB;;;OAGG;IACH,OAAO,CAAC,cAAc;CAyBvB"}
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AA2DhE;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,IAAI,SAAa;IAEjB,OAAO,CAAC,MAAM,CAAkF;IAChG,OAAO,CAAC,YAAY,CAAmC;IACvD,OAAO,CAAC,UAAU,CAAiC;gBAEvC,MAAM,GAAE,qBAA0B;IA6C9C;;OAEG;cACa,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCvE;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAkExB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAiD/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgD7B;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IA+DzB;;;OAGG;IACH,OAAO,CAAC,aAAa;IA2CrB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IA8BpB;;;OAGG;IACH,OAAO,CAAC,cAAc;CAyBvB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/datadog",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.3",
4
4
  "description": "Datadog LLM Observability exporter for Mastra - exports tracing data to Datadog's LLM Observability product",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -48,7 +48,17 @@
48
48
  "vitest": "catalog:"
49
49
  },
50
50
  "peerDependencies": {
51
- "@mastra/core": ">=1.0.0-0 <2.0.0-0"
51
+ "@mastra/core": ">=1.0.0-0 <2.0.0-0",
52
+ "@openfeature/core": "^1.7.0",
53
+ "@openfeature/server-sdk": "^1.18.0"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "@openfeature/core": {
57
+ "optional": true
58
+ },
59
+ "@openfeature/server-sdk": {
60
+ "optional": true
61
+ }
52
62
  },
53
63
  "homepage": "https://mastra.ai",
54
64
  "repository": {