{"version":3,"file":"index.cjs","names":["coreFeatures","tracer","SpanType","tracer","BaseExporter","SpanTypeEnum","BaseExporter","tracer","SpanType"],"sources":["../src/features.ts","../src/metrics.ts","../src/utils.ts","../src/bridge.ts","../src/tracing.ts"],"sourcesContent":["/**\n * Feature detection for paired @mastra/core and @mastra/observability versions.\n *\n * `coreFeatures` is a hard peer dependency, so it can be imported statically.\n * `observabilityFeatures` is loaded via dynamic import so this exporter degrades\n * gracefully against older `@mastra/observability` versions that don't export it\n * (per the pattern documented in `observability/mastra/src/features.ts`).\n *\n * Detection runs once at module load. Callers consume the result through the\n * sync `isModelInferenceEnabled()` accessor, which conservatively returns\n * `false` until detection settles — long enough only to cover the microtask\n * window before any spans are emitted in practice.\n */\n\nimport { coreFeatures } from '@mastra/core/features';\n\nconst FEATURE = 'model-inference-span';\n\nlet observabilityFeatures: ReadonlySet<string> | undefined;\nlet featureLoadPromise: Promise<void> | undefined;\n\nfunction loadObservabilityFeatures(): Promise<void> {\n  if (!featureLoadPromise) {\n    featureLoadPromise = import('@mastra/observability')\n      .then(mod => {\n        observabilityFeatures = (mod as { observabilityFeatures?: ReadonlySet<string> }).observabilityFeatures;\n      })\n      .catch(() => {\n        // Older @mastra/observability without the `observabilityFeatures` export.\n      });\n  }\n  return featureLoadPromise;\n}\n\n// Kick off detection at module load so the cached value is ready by the time\n// the first span is emitted.\nvoid loadObservabilityFeatures();\n\n/**\n * Returns true when both packages report the `model-inference-span` feature,\n * meaning MODEL_INFERENCE spans are emitted by the tracker. Drives the\n * Datadog kind mapping and usage-source switch (legacy: MODEL_STEP carries\n * 'llm' kind + usage; new: MODEL_INFERENCE does).\n */\nexport function isModelInferenceEnabled(): boolean {\n  return observabilityFeatures?.has(FEATURE) === true && coreFeatures.has(FEATURE);\n}\n\n/**\n * @internal Test-only override. Allows tests to simulate a paired older or\n * newer `@mastra/observability` without juggling dynamic imports.\n */\nexport function __setObservabilityFeaturesForTest(features: ReadonlySet<string> | undefined): void {\n  observabilityFeatures = features;\n  // Mark detection complete so isModelInferenceEnabled stops waiting.\n  featureLoadPromise = Promise.resolve();\n}\n","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.reasoningOutputTokens = usage.outputDetails.reasoning;\n  }\n\n  const cacheReadTokens = usage?.inputDetails?.cacheRead;\n  if (cacheReadTokens !== undefined) {\n    result.cacheReadTokens = cacheReadTokens;\n  }\n\n  const cacheWriteTokens = usage?.inputDetails?.cacheWrite;\n  if (cacheWriteTokens !== undefined) {\n    result.cacheWriteTokens = cacheWriteTokens;\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';\nimport { isModelInferenceEnabled } from './features';\n\n/**\n * Datadog span links for Mastra span links, such as the caller of a served MCP\n * request. Each link is resolved from a W3C `traceparent`, so only full-length\n * W3C IDs are kept, and links dd-trace can't resolve are skipped.\n */\nexport function toDatadogLinks(links: { traceId: string; spanId: string }[] | undefined): { context: any }[] {\n  const ddLinks: { context: any }[] = [];\n  for (const link of links ?? []) {\n    if (!/^[0-9a-f]{32}$/.test(link.traceId) || !/^[0-9a-f]{16}$/.test(link.spanId)) continue;\n    const context = tracer.extract('text_map', { traceparent: `00-${link.traceId}-${link.spanId}-01` });\n    if (context) ddLinks.push({ context });\n  }\n  return ddLinks;\n}\n\n/**\n * Datadog LLM Observability span kinds.\n */\nexport type DatadogSpanKind = 'llm' | 'agent' | 'workflow' | 'tool' | 'task' | 'retrieval' | 'embedding';\n\ntype DatadogToolCall = {\n  name?: string;\n  arguments?: Record<string, any>;\n  toolId?: string;\n  type?: string;\n};\n\ntype DatadogMessage = {\n  role: string;\n  content: string;\n  toolCalls?: DatadogToolCall[];\n};\n\n/**\n * Maps Mastra SpanTypes to Datadog LLMObs span kinds for the legacy hierarchy\n * (no `model-inference-span` feature). MODEL_STEP is the actual API call here\n * because MODEL_INFERENCE doesn't exist.\n *\n * Unmapped types fall back to 'task'.\n */\nconst SPAN_TYPE_TO_KIND_LEGACY: 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.PROVIDER_TOOL_CALL]: 'tool',\n  [SpanType.WORKFLOW_RUN]: 'workflow',\n};\n\n/**\n * Maps Mastra SpanTypes to Datadog LLMObs span kinds for the new hierarchy\n * (`model-inference-span` feature). MODEL_INFERENCE is the LLM API call;\n * MODEL_STEP wraps processors + inference + tool execution as a workflow.\n *\n * Unmapped types fall back to 'task'.\n */\nconst SPAN_TYPE_TO_KIND_INFERENCE: Partial<Record<SpanType, DatadogSpanKind>> = {\n  [SpanType.AGENT_RUN]: 'agent',\n  [SpanType.MODEL_GENERATION]: 'workflow',\n  [SpanType.MODEL_STEP]: 'workflow',\n  [SpanType.MODEL_INFERENCE]: 'llm',\n  [SpanType.TOOL_CALL]: 'tool',\n  [SpanType.MCP_TOOL_CALL]: 'tool',\n  [SpanType.PROVIDER_TOOL_CALL]: 'tool',\n  [SpanType.WORKFLOW_RUN]: 'workflow',\n};\n\n/**\n * Resolves the active span-type → Datadog kind mapping based on whether the\n * paired @mastra/core + @mastra/observability emit MODEL_INFERENCE spans.\n * Re-evaluated on each call so tests can flip the feature flag at runtime.\n */\nexport function getSpanTypeToKind(): Partial<Record<SpanType, DatadogSpanKind>> {\n  return isModelInferenceEnabled() ? SPAN_TYPE_TO_KIND_INFERENCE : SPAN_TYPE_TO_KIND_LEGACY;\n}\n\n/** @deprecated Prefer `getSpanTypeToKind()` so the mapping reflects the active feature flag. */\nexport const SPAN_TYPE_TO_KIND: Partial<Record<SpanType, DatadogSpanKind>> = SPAN_TYPE_TO_KIND_LEGACY;\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, using the mapping that\n * matches the active span hierarchy (legacy vs MODEL_INFERENCE).\n */\nexport function kindFor(spanType: SpanType): DatadogSpanKind {\n  return getSpanTypeToKind()[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; toolCalls?: DatadogToolCall[] }> {\n  return Array.isArray(data) && data.every(m => m?.role && (m?.content !== undefined || Array.isArray(m.toolCalls)));\n}\n\nfunction isModelDataSpan(spanType: SpanType): boolean {\n  return (\n    spanType === SpanType.MODEL_GENERATION || spanType === SpanType.MODEL_STEP || spanType === SpanType.MODEL_INFERENCE\n  );\n}\n\n/**\n * Checks if data is in Gemini content array format ({role, parts}[]).\n */\nfunction isGeminiContentArray(data: any): data is Array<{ role: string; parts: any[] }> {\n  return Array.isArray(data) && data.every(m => m?.role && Array.isArray(m?.parts));\n}\n\nfunction toMessageContent(content: any): string {\n  return typeof content === 'string' ? content : safeStringify(content);\n}\n\n/**\n * Maps a {role, content}[] message array into the Datadog message shape,\n * stringifying any non-string content (e.g. multimodal part arrays).\n */\nfunction toDatadogMessages(\n  messages: Array<{ role: string; content: any; toolCalls?: DatadogToolCall[] }>,\n): DatadogMessage[] {\n  return messages\n    .map(m => {\n      const message: DatadogMessage = {\n        role: m.role,\n        content: m.content == null ? '' : toMessageContent(m.content),\n      };\n      if (Array.isArray(m.toolCalls) && m.toolCalls.length > 0) {\n        // Normalize to Datadog's tool-call shape ({name, arguments, toolId, type}).\n        // Raw Mastra tool calls ({toolName, toolCallId, args}) are not recognized by\n        // dd-trace's tagger and would be emitted as empty objects, dropping the tool\n        // call from the LLM input in Datadog.\n        message.toolCalls = toDatadogToolCalls(m.toolCalls);\n      }\n      return message;\n    })\n    .filter(m => !(m.role === 'user' && m.content.trim().length === 0));\n}\n\nfunction parseToolArguments(args: unknown): Record<string, any> | undefined {\n  if (args == null) return undefined;\n  if (typeof args === 'string') {\n    try {\n      const parsed = JSON.parse(args);\n      if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n        return parsed;\n      }\n    } catch {\n      // Datadog's tool-call schema expects an object. Preserve opaque strings\n      // under a stable key instead of dropping the argument payload.\n    }\n    return { value: args };\n  }\n  if (typeof args === 'object' && !Array.isArray(args)) return args as Record<string, any>;\n  return { value: args };\n}\n\nfunction toDatadogToolCalls(toolCalls: any[]): DatadogToolCall[] {\n  // Accept both raw Mastra tool calls ({toolName, args, toolCallId}) and\n  // already-normalized Datadog tool calls ({name, arguments, toolId}) so this is\n  // idempotent — callers may pass messages that were normalized upstream.\n  return toolCalls.map(c => ({\n    name: c?.toolName ?? c?.name ?? c?.function?.name ?? 'unknown',\n    arguments: parseToolArguments(c?.args ?? c?.input ?? c?.arguments ?? c?.function?.arguments),\n    toolId: c?.toolCallId ?? c?.toolId ?? c?.id,\n    type: c?.type === 'function' ? c.type : 'function',\n  }));\n}\n\n/**\n * Converts a Gemini content item to Datadog message format.\n * Extracts text from parts, skips binary data to avoid bloating traces.\n */\nfunction geminiContentToMessage(item: { role: string; parts: any[] }): { role: string; content: string } {\n  const text = item.parts\n    .map(p => {\n      if (typeof p === 'string') return p;\n      if (p?.text) return p.text;\n      if (p?.inlineData) return `[${p.inlineData.mimeType ?? 'binary'}]`;\n      if (p?.functionCall) return `[tool: ${p.functionCall.name ?? 'unknown'}]`;\n      return safeStringify(p);\n    })\n    .join('');\n  return { role: item.role, content: text };\n}\n\n/**\n * Formats input data for Datadog annotations.\n * Model spans use message array format; others use raw or stringified data.\n */\nexport function formatInput(input: any, spanType: SpanType): any {\n  // Model spans expect {role, content}[] format\n  if (isModelDataSpan(spanType)) {\n    // Already in message format\n    if (isMessageArray(input)) {\n      return toDatadogMessages(input);\n    }\n    // Gemini format: {role, parts} → normalize to {role, content}\n    if (isGeminiContentArray(input)) {\n      return toDatadogMessages(input.map(geminiContentToMessage));\n    }\n    // Mastra wraps MODEL_GENERATION input as { messages, schema? } and Gemini\n    // request bodies use { contents }. Unwrap so we don't bury the message array\n    // inside a single stringified user-message content (double-encoded JSON).\n    if (input && typeof input === 'object' && !Array.isArray(input)) {\n      if (isMessageArray((input as any).messages)) {\n        return toDatadogMessages((input as any).messages);\n      }\n      if (isGeminiContentArray((input as any).messages)) {\n        return toDatadogMessages((input as any).messages.map(geminiContentToMessage));\n      }\n      if (isGeminiContentArray((input as any).contents)) {\n        return toDatadogMessages((input as any).contents.map(geminiContentToMessage));\n      }\n    }\n    // String input becomes user message\n    if (typeof input === 'string') {\n      return toDatadogMessages([{ role: 'user', content: input }]);\n    }\n    // Object input gets stringified as user message\n    return toDatadogMessages([{ role: 'user', content: safeStringify(input) }]);\n  }\n\n  // Non-model 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 * Model spans use message array format; others use raw or stringified data.\n */\nexport function formatOutput(output: any, spanType: SpanType): any {\n  // Model spans expect {role, content}[] format\n  if (isModelDataSpan(spanType)) {\n    // Already in message format\n    if (isMessageArray(output)) {\n      return toDatadogMessages(output);\n    }\n    // String output becomes assistant message\n    if (typeof output === 'string') {\n      return [{ role: 'assistant', content: output }];\n    }\n    // AI SDK shape: { text, object, reasoning, toolCalls, ... }.\n    // Prefer structured tool-call messages when present so Datadog renders\n    // them as tool-call blocks instead of escaped JSON or text summaries.\n    if (output && typeof output === 'object') {\n      if (Array.isArray(output.toolCalls) && output.toolCalls.length > 0) {\n        return [\n          {\n            role: 'assistant',\n            content: typeof output.text === 'string' ? output.text : '',\n            toolCalls: toDatadogToolCalls(output.toolCalls),\n          },\n        ];\n      }\n      if (typeof output.text === 'string' && output.text.length > 0) {\n        return [{ role: 'assistant', content: output.text }];\n      }\n      if (output.object !== undefined) {\n        return [{ role: 'assistant', content: safeStringify(output.object) }];\n      }\n    }\n    // Other objects get stringified as assistant message\n    return [{ role: 'assistant', content: safeStringify(output) }];\n  }\n\n  // Non-model spans: pass through strings, stringify objects\n  if (typeof output === 'string') return output;\n  return safeStringify(output);\n}\n","/**\n * Datadog Bridge for Mastra Observability\n *\n * This bridge enables bidirectional integration with dd-trace:\n * 1. Creates real dd-trace APM spans eagerly when Mastra spans are created\n * 2. Activates spans in dd-trace's scope so auto-instrumented operations\n *    (HTTP requests, database queries, etc.) have correct parent spans\n * 3. Registers those same spans with Datadog LLMObs and annotates them\n *    before finish, avoiding a second synthetic APM span tree\n *\n * This fixes the core problem with the DatadogExporter: because the exporter\n * creates LLMObs spans retroactively (after execution completes), there is no\n * active dd-trace span in scope when tools and processors make outbound calls.\n * dd-trace's auto-instrumentation can't find the correct parent, so APM spans\n * fall back to the nearest active span (typically the request handler).\n */\n\nimport type {\n  TracingEvent,\n  AnyExportedSpan,\n  ModelGenerationAttributes,\n  ModelInferenceAttributes,\n  ModelStepAttributes,\n  ObservabilityBridge,\n  CreateSpanOptions,\n  ScoreEvent,\n  SpanType,\n  SpanIds,\n} from '@mastra/core/observability';\nimport { SpanType as SpanTypeEnum } from '@mastra/core/observability';\nimport { omitKeys } from '@mastra/core/utils';\nimport { BaseExporter, getExternalParentId } from '@mastra/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport tracer from 'dd-trace';\nimport { isModelInferenceEnabled } from './features';\nimport { formatUsageMetrics } from './metrics';\nimport { ensureTracer, formatInput, formatOutput, kindFor, toDate, toDatadogLinks } from './utils';\nimport type { DatadogSpanKind } from './utils';\n\n// These types model dd-trace internals, not its public API surface.\n// The bridge uses them intentionally for experimental LLM Observability support\n// and they should be reviewed when upgrading dd-trace.\ntype LLMObsTagger = {\n  registerLLMObsSpan: (\n    span: any,\n    options: {\n      parent?: any;\n      kind: DatadogSpanKind;\n      name: string;\n      userId?: string;\n      sessionId?: string;\n      modelName?: string;\n      modelProvider?: string;\n    },\n  ) => void;\n};\n\ntype LLMObsInternalApi = {\n  _activate?: <T>(span: any, options: Record<string, never> | undefined, fn: () => T) => T;\n};\n\ninterface TraceContext {\n  userId?: string;\n  sessionId?: string;\n}\n\nfunction flushApmExporter(): Promise<void> {\n  const exporterFlush = (tracer as any)?._tracer?._exporter?.flush;\n  if (typeof exporterFlush !== 'function') {\n    return Promise.resolve();\n  }\n\n  return new Promise((resolve, reject) => {\n    let settled = false;\n\n    const done = (error?: unknown) => {\n      if (settled) return;\n      settled = true;\n\n      if (error) {\n        reject(error);\n        return;\n      }\n\n      resolve();\n    };\n\n    try {\n      exporterFlush.call((tracer as any)._tracer._exporter, done);\n    } catch (error) {\n      reject(error);\n    }\n  });\n}\n\n/**\n * Configuration options for the Datadog Bridge.\n */\nexport interface DatadogBridgeConfig extends BaseExporterConfig {\n  /**\n   * Datadog API key. Required in agentless mode.\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 a local Datadog Agent).\n   *\n   * Defaults to `false` for the bridge — most users running dd-trace\n   * auto-instrumentation already have a local Datadog Agent (required for\n   * APM data). Agentless mode only routes LLMObs data directly to Datadog\n   * intake, which would split your APM and LLMObs telemetry across two\n   * paths.\n   *\n   * Set to `true` if you only want LLMObs data (no APM auto-instrumentation)\n   * and don't have a local Datadog Agent. Falls back to the\n   * `DD_LLMOBS_AGENTLESS_ENABLED` environment variable.\n   */\n  agentless?: boolean;\n\n  /**\n   * Enable dd-trace automatic integrations (HTTP, database, etc.).\n   * Defaults to true since the bridge is designed for APM integration.\n   */\n  integrationsEnabled?: boolean;\n\n  /**\n   * Keys from the request context that should be promoted to flat Datadog\n   * LLM Observability tags instead of being nested in annotations.metadata.\n   */\n  requestContextKeys?: string[];\n\n  /**\n   * How long `flush()` waits, in milliseconds, after handing data to dd-trace.\n   * dd-trace sends LLM Observability spans and evaluations from a background\n   * writer and offers no way to await that request, so the wait keeps a process\n   * that exits right after `flush()` from cutting the send off. The wait only\n   * happens when something was sent since the last flush. Set to 0 to disable.\n   * Defaults to 2000.\n   */\n  flushGraceMs?: number;\n}\n\n/**\n * Datadog Bridge for Mastra Observability.\n *\n * Creates native dd-trace spans in real time during execution for proper APM\n * context propagation, and uses the same live dd span for Datadog LLMObs\n * tagging and annotations.\n */\nexport class DatadogBridge extends BaseExporter implements ObservabilityBridge {\n  name = 'datadog-bridge';\n\n  private config: Required<Pick<DatadogBridgeConfig, 'mlApp' | 'site'>> & DatadogBridgeConfig;\n  private ddSpanMap = new Map<string, any>();\n  /** Keys of the links each dd span was started with, so links set later are added once at finish. */\n  private startLinkKeys = new WeakMap<object, Set<string>>();\n  private traceContext = new Map<string, TraceContext>();\n  private openSpanCounts = new Map<string, number>();\n  private flushGraceMs: number;\n  /** True when spans or evaluations were handed to dd-trace since the last flush() */\n  private pendingSend = false;\n  /** Grace wait in progress, shared by flush() calls that overlap it */\n  private graceWait: Promise<void> | null = null;\n\n  constructor(config: DatadogBridgeConfig = {}) {\n    super(config);\n    this.flushGraceMs = config.flushGraceMs ?? 2000;\n\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 false for the bridge — assume a local Datadog Agent is\n    // present (required for the APM auto-instrumentation the bridge enables)\n    const envAgentless = process.env.DD_LLMOBS_AGENTLESS_ENABLED?.toLowerCase();\n    const agentless = config.agentless ?? (envAgentless === 'true' || envAgentless === '1' ? true : false);\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 = {\n      ...config,\n      mlApp,\n      site,\n      apiKey,\n      agentless,\n      env,\n    };\n\n    ensureTracer({\n      mlApp,\n      site,\n      apiKey,\n      agentless,\n      service: config.service,\n      env,\n      integrationsEnabled: config.integrationsEnabled ?? true,\n    });\n\n    this.logger.info('Datadog bridge initialized', { mlApp, site, agentless });\n  }\n\n  /**\n   * Create a dd-trace span eagerly when a Mastra span is constructed.\n   */\n  createSpan(options: CreateSpanOptions<SpanType>): SpanIds | undefined {\n    if (this.isDisabled) return undefined;\n\n    try {\n      let apmParentDdSpan: any = undefined;\n      let llmobsParentDdSpan: any = undefined;\n      let parentSource: 'external-parent' | 'active-scope' | 'none' = 'none';\n\n      const externalParentId = getExternalParentId(options);\n      if (externalParentId) {\n        apmParentDdSpan = this.ddSpanMap.get(externalParentId);\n        llmobsParentDdSpan = apmParentDdSpan;\n        if (apmParentDdSpan) {\n          parentSource = 'external-parent';\n        }\n      }\n\n      if (!apmParentDdSpan) {\n        apmParentDdSpan = tracer.scope().active() ?? undefined;\n        if (apmParentDdSpan) {\n          parentSource = 'active-scope';\n        }\n      }\n\n      if (!llmobsParentDdSpan && externalParentId) {\n        llmobsParentDdSpan = apmParentDdSpan;\n      }\n\n      const links = toDatadogLinks(options.links);\n      const ddSpan = tracer.startSpan(options.name, {\n        ...(apmParentDdSpan ? { childOf: apmParentDdSpan } : {}),\n        ...(options.startTime ? { startTime: toDate(options.startTime).getTime() } : {}),\n        ...(links.length > 0 ? { links } : {}),\n      });\n      if (options.links?.length) {\n        this.startLinkKeys.set(ddSpan, new Set(options.links.map(link => `${link.traceId}:${link.spanId}`)));\n      }\n\n      const ddContext = ddSpan.context?.() as\n        | {\n            toSpanId?: (hex?: boolean) => string;\n            toTraceId?: (hex?: boolean) => string;\n          }\n        | undefined;\n      const spanId = ddContext?.toSpanId?.(true) ?? generateSpanId();\n      const traceId =\n        ddContext?.toTraceId?.(true) ??\n        (externalParentId ? (options.parent?.traceId ?? generateTraceId()) : generateTraceId());\n      const parentContext = apmParentDdSpan?.context?.() as { toSpanId?: (hex?: boolean) => string } | undefined;\n      const parentSpanId = parentContext?.toSpanId?.(true) ?? externalParentId;\n\n      // Declare which kind of parent was used. A parent resolved from the\n      // Mastra span chain is part of the Mastra trace; an active dd-trace scope\n      // span is a Mastra span only if this bridge created it, otherwise it\n      // belongs to Datadog (e.g. APM auto-instrumentation).\n      const parentIsMastraSpan =\n        parentSpanId !== undefined && (parentSource !== 'active-scope' || this.ddSpanMap.has(parentSpanId));\n\n      this.captureTraceContext(traceId, options);\n      this.openSpanCounts.set(traceId, (this.openSpanCounts.get(traceId) ?? 0) + 1);\n      this.ddSpanMap.set(spanId, ddSpan);\n      this.registerLlmObsSpan(ddSpan, traceId, options, llmobsParentDdSpan);\n\n      this.logger.debug(\n        `[DatadogBridge.createSpan] Created APM span [spanId=${spanId}] [traceId=${traceId}] ` +\n          `[parentSpanId=${parentSpanId}] [type=${options.type}] [mapSize=${this.ddSpanMap.size}] ` +\n          `[parentSource=${parentSource}] [externalParentId=${externalParentId ?? 'none'}]`,\n      );\n\n      return {\n        spanId,\n        traceId,\n        ...(parentIsMastraSpan ? { parentSpanId } : { externalParentSpanId: parentSpanId }),\n      };\n    } catch (error) {\n      this.logger.error('[DatadogBridge] Failed to create span:', error);\n      return undefined;\n    }\n  }\n\n  /**\n   * Execute an async function within the dd-trace context of a Mastra span.\n   */\n  executeInContext<T>(spanId: string, fn: () => Promise<T>): Promise<T> {\n    return this.executeWithSpanContext(spanId, fn);\n  }\n\n  /**\n   * Execute a synchronous function within the dd-trace context of a Mastra span.\n   */\n  executeInContextSync<T>(spanId: string, fn: () => T): T {\n    return this.executeWithSpanContext(spanId, fn);\n  }\n\n  async onScoreEvent(event: ScoreEvent): Promise<void> {\n    if (this.isDisabled || !(tracer as any).llmobs?.submitEvaluation) return;\n\n    const { score } = event;\n    if (!score.traceId || !score.spanId) {\n      this.logger.warn('Datadog bridge: dropping score with no traceId/spanId', {\n        scorerId: score.scorerId,\n      });\n      return;\n    }\n\n    try {\n      this.pendingSend = true;\n      tracer.llmobs.submitEvaluation(\n        { traceId: score.traceId, spanId: toDatadogSpanId(score.spanId) },\n        {\n          label: score.scorerName ?? score.scorerId,\n          value: score.score,\n          metricType: 'score',\n          mlApp: this.config.mlApp,\n          timestampMs: score.timestamp instanceof Date ? score.timestamp.getTime() : Date.now(),\n          ...(score.reason ? { reasoning: score.reason } : {}),\n          ...(score.metadata ? { metadata: score.metadata } : {}),\n        },\n      );\n    } catch (error) {\n      this.logger.error('Datadog bridge: Failed to submit evaluation', {\n        error,\n        traceId: score.traceId,\n        spanId: score.spanId,\n        scorerId: score.scorerId,\n      });\n    }\n  }\n\n  private executeWithSpanContext<T>(spanId: string, fn: () => T): T {\n    const ddSpan = this.ddSpanMap.get(spanId);\n\n    if (ddSpan) {\n      return tracer.scope().activate(ddSpan, () => {\n        const llmobs = (tracer as any).llmobs as LLMObsInternalApi | undefined;\n        // `_activate` is an internal dd-trace hook. Keep this usage aligned\n        // with supported dd-trace versions when the dependency is upgraded.\n        if (typeof llmobs?._activate === 'function') {\n          return llmobs._activate(ddSpan, undefined, fn);\n        }\n\n        return fn();\n      });\n    }\n\n    return fn();\n  }\n\n  /**\n   * Handle tracing events from the observability bus.\n   */\n  protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n    if (this.isDisabled) return;\n\n    try {\n      const span = event.exportedSpan;\n\n      if (span.isEvent) {\n        if (event.type === 'span_started' || event.type === 'span_ended') {\n          this.annotateAndFinishSpan(span);\n        }\n        return;\n      }\n\n      switch (event.type) {\n        case 'span_started':\n        case 'span_updated':\n          return;\n        case 'span_ended':\n          this.annotateAndFinishSpan(span);\n          return;\n      }\n    } catch (error) {\n      this.logger.error('Datadog bridge error', {\n        error,\n        eventType: event.type,\n        spanId: event.exportedSpan?.id,\n        spanName: event.exportedSpan?.name,\n      });\n    }\n  }\n\n  private registerLlmObsSpan(\n    ddSpan: any,\n    traceId: string,\n    options: CreateSpanOptions<SpanType>,\n    parentDdSpan?: any,\n  ): void {\n    const tagger = this.getLlmObsTagger();\n    if (!tagger) return;\n\n    try {\n      const kind = kindFor(options.type);\n      const ownAttrs = options.attributes as ModelGenerationAttributes | undefined;\n      const inheritedModelAttrs =\n        options.parent?.type === SpanTypeEnum.MODEL_GENERATION\n          ? (options.parent.attributes as ModelGenerationAttributes | undefined)\n          : undefined;\n      const traceCtx = this.resolveTraceContext(traceId, options);\n\n      // `registerLLMObsSpan` comes from dd-trace internals. Keep it under\n      // review because the bridge depends on experimental behavior here.\n      tagger.registerLLMObsSpan(ddSpan, {\n        parent: parentDdSpan,\n        kind,\n        name: options.name,\n        userId: traceCtx.userId,\n        sessionId: traceCtx.sessionId,\n        ...(kind === 'llm' && (ownAttrs?.model ?? inheritedModelAttrs?.model)\n          ? { modelName: ownAttrs?.model ?? inheritedModelAttrs?.model }\n          : {}),\n        ...(kind === 'llm' && (ownAttrs?.provider ?? inheritedModelAttrs?.provider)\n          ? { modelProvider: ownAttrs?.provider ?? inheritedModelAttrs?.provider }\n          : {}),\n      });\n    } catch (error) {\n      this.logger.warn('[DatadogBridge] Failed to register LLMObs span', {\n        error,\n        spanName: options.name,\n        spanType: options.type,\n      });\n    }\n  }\n\n  private getLlmObsTagger(): LLMObsTagger | undefined {\n    const tagger = (tracer as any).llmobs?._tagger;\n    // `_tagger` is also internal dd-trace state and may change between releases.\n    if (tagger && typeof tagger.registerLLMObsSpan === 'function') {\n      return tagger as LLMObsTagger;\n    }\n    return undefined;\n  }\n\n  /**\n   * Annotate the eagerly-created dd span and finish it using the final Mastra\n   * span state.\n   */\n  private annotateAndFinishSpan(span: AnyExportedSpan): void {\n    const ddSpan = this.ddSpanMap.get(span.id);\n    if (!ddSpan) {\n      this.logger.warn('[DatadogBridge] No dd span found when finalizing Mastra span', {\n        spanId: span.id,\n        spanName: span.name,\n        spanType: span.type,\n        mapSize: this.ddSpanMap.size,\n      });\n      return;\n    }\n\n    const endTime = span.endTime ? toDate(span.endTime) : span.isEvent ? toDate(span.startTime) : new Date();\n\n    const annotations = this.buildAnnotations(span);\n\n    try {\n      if (Object.keys(annotations).length > 0 && tracer.llmobs?.annotate) {\n        tracer.llmobs.annotate(ddSpan, annotations);\n      }\n    } catch (error) {\n      this.logger.error('[DatadogBridge] Failed to annotate span before finish', {\n        error,\n        spanId: span.id,\n        spanName: span.name,\n      });\n    }\n\n    try {\n      if (span.errorInfo) {\n        this.setErrorTags(ddSpan, span.errorInfo);\n      }\n    } catch (error) {\n      this.logger.error('[DatadogBridge] Failed to set error tags on dd span', {\n        error,\n        spanId: span.id,\n        spanName: span.name,\n      });\n    }\n\n    try {\n      // Links set after the span started, such as an MCP tool call's link to the\n      // server span that handled it\n      const startKeys = this.startLinkKeys.get(ddSpan);\n      const lateLinks = toDatadogLinks(span.links?.filter(link => !startKeys?.has(`${link.traceId}:${link.spanId}`)));\n      if (lateLinks.length > 0 && typeof ddSpan.addLinks === 'function') {\n        ddSpan.addLinks(lateLinks);\n      }\n    } catch (error) {\n      this.logger.error('[DatadogBridge] Failed to add span links', { error, spanId: span.id });\n    }\n\n    try {\n      if (typeof ddSpan.finish === 'function') {\n        this.pendingSend = true;\n        ddSpan.finish(endTime.getTime());\n      }\n    } catch (error) {\n      this.logger.error('[DatadogBridge] Failed to finish dd span', {\n        error,\n        spanId: span.id,\n        spanName: span.name,\n      });\n    } finally {\n      this.ddSpanMap.delete(span.id);\n      this.releaseTraceContext(span.traceId);\n    }\n  }\n\n  /**\n   * Release the dd span held for a Mastra span that ended without being exported.\n   *\n   * The dd span is deliberately not finished: finishing it would send a span the\n   * user's filtering just removed. The per-trace context is released too, since\n   * createSpan() counted this span as open.\n   */\n  releaseSpan(spanId: string, traceId: string): void {\n    if (this.ddSpanMap.delete(spanId)) {\n      this.releaseTraceContext(traceId);\n    }\n  }\n\n  private captureTraceContext(traceId: string, options: CreateSpanOptions<SpanType>): void {\n    const existing = this.traceContext.get(traceId);\n    const next: TraceContext = {\n      userId: firstString(options.metadata?.userId, options.parent?.metadata?.userId, existing?.userId),\n      sessionId: firstString(options.metadata?.sessionId, options.parent?.metadata?.sessionId, existing?.sessionId),\n    };\n\n    if (next.userId || next.sessionId) {\n      this.traceContext.set(traceId, next);\n    }\n  }\n\n  private resolveTraceContext(traceId: string, options: CreateSpanOptions<SpanType>): TraceContext {\n    const stored = this.traceContext.get(traceId);\n    return {\n      userId: firstString(options.metadata?.userId, options.parent?.metadata?.userId, stored?.userId),\n      sessionId: firstString(options.metadata?.sessionId, options.parent?.metadata?.sessionId, stored?.sessionId),\n    };\n  }\n\n  private releaseTraceContext(traceId: string): void {\n    const nextCount = (this.openSpanCounts.get(traceId) ?? 1) - 1;\n    if (nextCount > 0) {\n      this.openSpanCounts.set(traceId, nextCount);\n      return;\n    }\n\n    this.openSpanCounts.delete(traceId);\n    this.traceContext.delete(traceId);\n  }\n\n  private buildAnnotations(span: AnyExportedSpan): Record<string, any> {\n    const annotations: Record<string, any> = {};\n\n    if (span.input !== undefined) {\n      annotations.inputData = formatInput(span.input, span.type);\n    }\n\n    if (span.output !== undefined) {\n      annotations.outputData = formatOutput(span.output, span.type);\n    }\n\n    // Token usage attaches to the LLM-kind span only — MODEL_INFERENCE when\n    // the feature is enabled, MODEL_STEP on legacy paired packages.\n    const usageSpanType = isModelInferenceEnabled() ? SpanTypeEnum.MODEL_INFERENCE : SpanTypeEnum.MODEL_STEP;\n    if (span.type === usageSpanType) {\n      const usage = (span.attributes as ModelStepAttributes | ModelInferenceAttributes | undefined)?.usage;\n      const metrics = formatUsageMetrics(usage);\n      if (metrics) {\n        annotations.metrics = metrics;\n      }\n    }\n\n    // `model`/`provider` are surfaced as native LLM Obs fields and `usage` as metrics;\n    // everything else (including `parameters` — model settings like reasoning_effort)\n    // flows into metadata so it reaches Datadog.\n    const knownFields = ['usage', 'model', 'provider'];\n    const otherAttributes = omitKeys((span.attributes ?? {}) as Record<string, any>, knownFields);\n\n    const contextKeySet = new Set(this.config.requestContextKeys ?? []);\n    const flatContextTags: Record<string, any> = {};\n    const remainingMetadata: Record<string, any> = {};\n\n    for (const [key, value] of Object.entries(span.metadata ?? {})) {\n      if (contextKeySet.has(key)) {\n        flatContextTags[key] = value;\n      } else {\n        remainingMetadata[key] = value;\n      }\n    }\n\n    const remainingAttributes: Record<string, any> = {};\n    for (const [key, value] of Object.entries(otherAttributes)) {\n      if (contextKeySet.has(key)) {\n        if (!(key in flatContextTags)) {\n          flatContextTags[key] = value;\n        }\n      } else {\n        remainingAttributes[key] = value;\n      }\n    }\n\n    const combinedMetadata: Record<string, any> = {\n      ...remainingMetadata,\n      ...remainingAttributes,\n    };\n    if (span.errorInfo) {\n      combinedMetadata['error.message'] = span.errorInfo.message;\n    }\n    if (Object.keys(combinedMetadata).length > 0) {\n      annotations.metadata = combinedMetadata;\n    }\n\n    const tags: Record<string, any> = {\n      ...flatContextTags,\n    };\n\n    if (span.tags?.length) {\n      for (const tag of span.tags) {\n        const colonIndex = tag.indexOf(':');\n        if (colonIndex > 0) {\n          tags[tag.substring(0, colonIndex)] = tag.substring(colonIndex + 1);\n        } else {\n          tags[tag] = true;\n        }\n      }\n    }\n\n    if (span.errorInfo) {\n      tags.error = true;\n      if (span.errorInfo.id) {\n        tags['error.id'] = span.errorInfo.id;\n      }\n      if (span.errorInfo.domain) {\n        tags['error.domain'] = span.errorInfo.domain;\n      }\n      if (span.errorInfo.category) {\n        tags['error.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  private setErrorTags(ddSpan: any, errorInfo: NonNullable<AnyExportedSpan['errorInfo']>): void {\n    ddSpan.setTag('error', true);\n    ddSpan.setTag('error.message', errorInfo.message);\n    ddSpan.setTag('error.type', errorInfo.name ?? errorInfo.category ?? 'Error');\n    if (errorInfo.stack) {\n      ddSpan.setTag('error.stack', errorInfo.stack);\n    }\n  }\n\n  async flush(): Promise<void> {\n    if (this.isDisabled) return;\n\n    if (tracer.llmobs?.flush) {\n      try {\n        await tracer.llmobs.flush();\n        this.logger.debug('Datadog llmobs flushed');\n      } catch (e) {\n        this.logger.error('Error flushing llmobs', { error: e });\n      }\n    }\n\n    await this.waitForBackgroundSend();\n\n    try {\n      await flushApmExporter();\n      this.logger.debug('Datadog APM exporter flushed');\n    } catch (e) {\n      this.logger.error('Error flushing Datadog APM exporter', { error: e });\n    }\n  }\n\n  /**\n   * `llmobs.flush()` returns before the background writer's HTTP request\n   * completes and dd-trace gives nothing to await, so wait a bounded time\n   * instead. Starts one wait per batch of new data, so the repeated flushes\n   * during shutdown don't stack. A flush that overlaps a running wait joins\n   * it, so no caller resolves before the data it produced had its wait.\n   */\n  private async waitForBackgroundSend(): Promise<void> {\n    if (!(this.flushGraceMs > 0) || !Number.isFinite(this.flushGraceMs)) return;\n    if (this.pendingSend) {\n      this.pendingSend = false;\n      const wait: Promise<void> = new Promise<void>(resolve => setTimeout(resolve, this.flushGraceMs)).finally(() => {\n        if (this.graceWait === wait) this.graceWait = null;\n      });\n      this.graceWait = wait;\n    }\n    await this.graceWait;\n  }\n\n  async shutdown(): Promise<void> {\n    for (const [spanId, ddSpan] of this.ddSpanMap) {\n      this.logger.warn(`[DatadogBridge] Force-finishing APM span that was not properly closed [id=${spanId}]`);\n      try {\n        if (typeof ddSpan.finish === 'function') {\n          this.pendingSend = true;\n          ddSpan.finish();\n        }\n      } catch {\n        // Best-effort cleanup\n      }\n    }\n    this.ddSpanMap.clear();\n    this.openSpanCounts.clear();\n    this.traceContext.clear();\n\n    await this.flush();\n\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    await super.shutdown();\n  }\n}\n\nfunction firstString(...values: Array<unknown>): string | undefined {\n  for (const value of values) {\n    if (typeof value === 'string') {\n      return value;\n    }\n  }\n  return undefined;\n}\n\nfunction fillRandomBytes(bytes: Uint8Array): void {\n  try {\n    const webCrypto = globalThis.crypto;\n    if (webCrypto?.getRandomValues) {\n      webCrypto.getRandomValues.call(webCrypto, bytes);\n      return;\n    }\n  } catch {\n    // Fall through to fallback\n  }\n  for (let i = 0; i < bytes.length; i++) {\n    bytes[i] = Math.floor(Math.random() * 256);\n  }\n}\n\nfunction toDatadogSpanId(spanId: string): string {\n  if (/^[0-9a-f]{16}$/i.test(spanId)) {\n    return BigInt(`0x${spanId}`).toString(10);\n  }\n  return spanId;\n}\n\nfunction generateSpanId(): string {\n  const bytes = new Uint8Array(8);\n  fillRandomBytes(bytes);\n  return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');\n}\n\nfunction generateTraceId(): string {\n  const bytes = new Uint8Array(16);\n  fillRandomBytes(bytes);\n  return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');\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  ModelInferenceAttributes,\n  ModelStepAttributes,\n  ScoreEvent,\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 { isModelInferenceEnabled } from './features';\nimport { formatUsageMetrics } from './metrics';\nimport { ensureTracer, kindFor, toDate, formatInput, formatOutput, toDatadogLinks } from './utils';\nimport type { DatadogSpanKind } from './utils';\n\n/**\n * LLMObs span options passed to dd-trace's llmobs.trace().\n * Note: endTime is not included because dd-trace does not honor it in trace options.\n * Instead, we call ddSpan.finish(endTimeMs) explicitly inside the trace callback.\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  /** Links to spans in other traces, forwarded by llmobs.trace() to the APM span. */\n  links?: { context: any }[];\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   * How long `flush()` waits, in milliseconds, after handing data to dd-trace.\n   * dd-trace sends LLM Observability spans and evaluations from a background\n   * writer and offers no way to await that request, so the wait keeps a process\n   * that exits right after `flush()` from cutting the send off. The wait only\n   * happens when something was sent since the last flush. Set to 0 to disable.\n   * Defaults to 2000.\n   */\n  flushGraceMs?: number;\n\n  /**\n   * Keys from the request context (set via `requestContextKeys` in the Mastra\n   * Observability config) that should be promoted to flat Datadog LLM Observability\n   * tags instead of being nested inside `annotations.metadata`.\n   *\n   * Flat tags are indexable and filterable in the Datadog LLM Observability UI,\n   * which makes them suitable for multi-tenant filtering (e.g. tenantId, agentId).\n   *\n   * @example\n   * ```typescript\n   * new DatadogExporter({\n   *   mlApp: 'my-app',\n   *   requestContextKeys: ['tenantId', 'agentId'],\n   * })\n   * ```\n   */\n  requestContextKeys?: string[];\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  private flushGraceMs: number;\n  /** True when spans or evaluations were handed to dd-trace since the last flush() */\n  private pendingSend = false;\n  /** Grace wait in progress, shared by flush() calls that overlap it */\n  private graceWait: Promise<void> | null = null;\n\n  constructor(config: DatadogExporterConfig = {}) {\n    super(config);\n    this.flushGraceMs = config.flushGraceMs ?? 2000;\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   * Sets native dd-trace error tags required by Datadog's Error Tracking UI.\n   */\n  private setErrorTags(ddSpan: any, errorInfo: NonNullable<AnyExportedSpan['errorInfo']>): void {\n    ddSpan.setTag('error', true);\n    ddSpan.setTag('error.message', errorInfo.message);\n    ddSpan.setTag('error.type', errorInfo.name ?? errorInfo.category ?? 'Error');\n    if (errorInfo.stack) {\n      ddSpan.setTag('error.stack', errorInfo.stack);\n    }\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    // Token usage metrics attach to the LLM-kind span only, to avoid\n    // double-counting cost in Datadog. With the `model-inference-span` feature\n    // that's MODEL_INFERENCE (the actual provider call); without it, MODEL_STEP\n    // is still the API call.\n    const usageSpanType = isModelInferenceEnabled() ? SpanType.MODEL_INFERENCE : SpanType.MODEL_STEP;\n    if (span.type === usageSpanType) {\n      const usage = (span.attributes as ModelStepAttributes | ModelInferenceAttributes | undefined)?.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    // `model`/`provider` are surfaced as native LLM Obs fields and `usage` as metrics;\n    // everything else (including `parameters`, which carries model settings like\n    // reasoning_effort/temperature) flows into metadata so it reaches Datadog.\n    const knownFields = ['usage', 'model', 'provider'];\n    const otherAttributes = omitKeys((span.attributes ?? {}) as Record<string, any>, knownFields);\n\n    // Separate requestContextKeys from span.metadata AND span.attributes:\n    // - Keys listed in this.config.requestContextKeys are promoted to flat LLM Obs tags,\n    //   making them indexable and filterable in the Datadog UI (e.g. tenantId, agentId).\n    // - All remaining keys stay nested in annotations.metadata as before.\n    const contextKeySet = new Set(this.config.requestContextKeys ?? []);\n    const flatContextTags: Record<string, any> = {};\n    const remainingMetadata: Record<string, any> = {};\n\n    for (const [key, value] of Object.entries(span.metadata ?? {})) {\n      if (contextKeySet.has(key)) {\n        flatContextTags[key] = value;\n      } else {\n        remainingMetadata[key] = value;\n      }\n    }\n\n    // Also promote matching keys from span.attributes so requestContextKeys\n    // are consistently elevated regardless of where the caller stored them.\n    const remainingAttributes: Record<string, any> = {};\n    for (const [key, value] of Object.entries(otherAttributes)) {\n      if (contextKeySet.has(key)) {\n        // Only promote if not already set from span.metadata (metadata wins)\n        if (!(key in flatContextTags)) {\n          flatContextTags[key] = value;\n        }\n      } else {\n        remainingAttributes[key] = value;\n      }\n    }\n\n    // Merge remaining span.metadata + span attributes into metadata\n    // Error message goes into metadata (not tags) because tags get normalized/truncated\n    // which mangles free-form error text (e.g. colons split into key/value, spaces become underscores)\n    const combinedMetadata: Record<string, any> = {\n      ...remainingMetadata,\n      ...remainingAttributes,\n    };\n    if (span.errorInfo) {\n      combinedMetadata['error.message'] = span.errorInfo.message;\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),\n    // promoted requestContextKeys values (flat, indexable in Datadog), 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      // Promote requestContextKeys values to flat, searchable LLM Observability tags\n      ...flatContextTags,\n    };\n\n    // Convert span.tags (string[]) to object format\n    // Tags in \"key:value\" format (e.g. \"instance_name:career-scout-api\") are split into { key: \"value\" }\n    // Tags without a colon (e.g. \"production\") are set as { tag: true } (preserving existing behavior)\n    if (span.tags?.length) {\n      for (const tag of span.tags) {\n        const colonIndex = tag.indexOf(':');\n        if (colonIndex > 0) {\n          tags[tag.substring(0, colonIndex)] = tag.substring(colonIndex + 1);\n        } else {\n          tags[tag] = true;\n        }\n      }\n    }\n\n    // Add error status and structured error fields as tags (short, structured values that survive normalization)\n    // The error message itself is in metadata above to avoid tag normalization/truncation\n    if (span.errorInfo) {\n      tags.error = true;\n      if (span.errorInfo.id) {\n        tags['error.id'] = span.errorInfo.id;\n      }\n      if (span.errorInfo.domain) {\n        tags['error.domain'] = span.errorInfo.domain;\n      }\n      if (span.errorInfo.category) {\n        tags['error.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   * Submit an eval score to Datadog LLM Observability for the matching ddSpan.\n   *\n   * Ordering constraint: the matching span must have already been emitted to dd-trace\n   * (i.e. its `SPAN_ENDED` event must have been processed and the trace tree flushed).\n   * On Mastra's normal scoring path this is always true — scorer hooks fire after the\n   * scored entity completes, so the root span has ended by the time `onScoreEvent` runs.\n   *\n   * If a score arrives for an unexported span (either before `SPAN_ENDED` or after the\n   * `traceState` entry has been cleaned up), the event is dropped and a warning is logged\n   * so the misuse is observable. Scores must therefore only be submitted for spans whose\n   * lifecycle has completed.\n   */\n  async onScoreEvent(event: ScoreEvent): Promise<void> {\n    if (this.isDisabled || !(tracer as any).llmobs?.submitEvaluation) return;\n\n    const { score } = event;\n    if (!score.traceId || !score.spanId) {\n      this.logger.warn('Datadog exporter: dropping score with no traceId/spanId', {\n        scorerId: score.scorerId,\n      });\n      return;\n    }\n\n    const ctx = this.traceState.get(score.traceId)?.contexts.get(score.spanId);\n    const exported = ctx?.exported;\n    if (!exported) {\n      this.logger.warn(\n        'Datadog exporter: dropping score for span that has not been emitted to dd-trace yet ' +\n          '(span_ended must be processed before submitting a score for it)',\n        {\n          traceId: score.traceId,\n          spanId: score.spanId,\n          scorerId: score.scorerId,\n        },\n      );\n      return;\n    }\n\n    try {\n      this.pendingSend = true;\n      tracer.llmobs.submitEvaluation(\n        { traceId: exported.traceId, spanId: exported.spanId },\n        {\n          label: score.scorerName ?? score.scorerId,\n          value: score.score,\n          metricType: 'score',\n          mlApp: this.config.mlApp,\n          timestampMs: score.timestamp instanceof Date ? score.timestamp.getTime() : Date.now(),\n          ...(score.reason ? { reasoning: score.reason } : {}),\n          ...(score.metadata ? { metadata: score.metadata } : {}),\n        },\n      );\n    } catch (err) {\n      this.logger.error('Datadog exporter: Failed to submit evaluation', {\n        error: err,\n        traceId: score.traceId,\n        spanId: score.spanId,\n        scorerId: score.scorerId,\n      });\n    }\n  }\n\n  /**\n   * Force flush any buffered spans without shutting down the exporter.\n   * This is useful in serverless environments where you need to ensure spans\n   * are exported before the runtime instance is terminated.\n   */\n  async flush(): Promise<void> {\n    if (this.isDisabled || !(tracer as any).llmobs) return;\n\n    // Flush any pending data to Datadog\n    if (tracer.llmobs?.flush) {\n      try {\n        await tracer.llmobs.flush();\n        this.logger.debug('Datadog llmobs flushed');\n      } catch (e) {\n        this.logger.error('Error flushing llmobs', { error: e });\n      }\n    }\n\n    await this.waitForBackgroundSend();\n  }\n\n  /**\n   * `llmobs.flush()` returns before the background writer's HTTP request\n   * completes and dd-trace gives nothing to await, so wait a bounded time\n   * instead. Starts one wait per batch of new data, so the repeated flushes\n   * during shutdown don't stack. A flush that overlaps a running wait joins\n   * it, so no caller resolves before the data it produced had its wait.\n   */\n  private async waitForBackgroundSend(): Promise<void> {\n    if (!(this.flushGraceMs > 0) || !Number.isFinite(this.flushGraceMs)) return;\n    if (this.pendingSend) {\n      this.pendingSend = false;\n      const wait: Promise<void> = new Promise<void>(resolve => setTimeout(resolve, this.flushGraceMs)).finally(() => {\n        if (this.graceWait === wait) this.graceWait = null;\n      });\n      this.graceWait = wait;\n    }\n    await this.graceWait;\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    await this.flush();\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 (e.g. fire-and-forget\n      // work like memory title generation that outlives the root span).\n      // dd-trace derives LLMObs parent linkage only from an enclosing\n      // llmobs.trace() callback - scope().activate() does not link LLMObs\n      // parents - so emitting these spans one at a time flattens every chain\n      // into disconnected root spans. Emit each chain as a nested sub-tree\n      // instead, once the chain's local root can be resolved.\n      let emitted = true;\n      while (emitted) {\n        emitted = false;\n        for (const span of state.buffer.values()) {\n          // Will be emitted as part of the buffered parent's sub-tree\n          if (span.parentSpanId && state.buffer.has(span.parentSpanId)) {\n            continue;\n          }\n\n          const parentCtx = span.parentSpanId ? state.contexts.get(span.parentSpanId) : undefined;\n          if (span.parentSpanId && !parentCtx) {\n            continue;\n          }\n\n          const subTree = this.takeSubTree(span, state.buffer);\n          if (parentCtx) {\n            // Activating the parent keeps APM trace continuity even though\n            // LLMObs cannot re-parent onto an already-emitted span\n            tracer.scope().activate(parentCtx.ddSpan, () => this.emitSpanTree(subTree, state));\n          } else {\n            this.emitSpanTree(subTree, state);\n          }\n          emitted = true;\n          break;\n        }\n      }\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 a sub-tree rooted at the given span from its buffered descendants,\n   * removing every collected span from the buffer. Used for late-arriving span\n   * chains emitted after the main tree.\n   */\n  private takeSubTree(rootSpan: AnyExportedSpan, buffer: Map<string, AnyExportedSpan>): SpanNode {\n    buffer.delete(rootSpan.id);\n\n    const children: SpanNode[] = [];\n    for (const candidate of [...buffer.values()]) {\n      if (candidate.parentSpanId === rootSpan.id) {\n        children.push(this.takeSubTree(candidate, buffer));\n      }\n    }\n\n    // Sort children by start time for consistent ordering\n    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    return { span: rootSpan, children };\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(\n    span: AnyExportedSpan,\n    inheritedModelAttrs?: { model?: string; provider?: string },\n  ): { traceOptions: LLMObsSpanOptions; endTimeMs: number } {\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    // MODEL_GENERATION carries model/provider; MODEL_STEP children inherit it from their parent.\n    const ownAttrs = span.attributes as ModelGenerationAttributes | undefined;\n    const attrs = {\n      model: ownAttrs?.model ?? inheritedModelAttrs?.model,\n      provider: ownAttrs?.provider ?? inheritedModelAttrs?.provider,\n    };\n\n    const startTime = toDate(span.startTime);\n    const links = toDatadogLinks(span.links);\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      traceOptions: {\n        kind,\n        name: span.name,\n        sessionId: traceCtx.sessionId,\n        userId: traceCtx.userId,\n        startTime,\n        ...(kind === 'llm' && attrs?.model ? { modelName: attrs.model } : {}),\n        ...(kind === 'llm' && attrs?.provider ? { modelProvider: attrs.provider } : {}),\n        ...(links.length > 0 ? { links } : {}),\n      },\n      // endTime as milliseconds for ddSpan.finish() — dd-trace's llmobs.trace() does not\n      // honor endTime in options, so we must call finish(ms) explicitly on the span.\n      endTimeMs: endTime.getTime(),\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(\n    node: SpanNode,\n    state: TraceState,\n    inheritedModelAttrs?: { model?: string; provider?: string },\n  ): void {\n    const span = node.span;\n    const { traceOptions, endTimeMs } = this.buildSpanOptions(span, inheritedModelAttrs);\n\n    // If this is a MODEL_GENERATION, propagate its model/provider to MODEL_STEP descendants\n    // so the LLM-kind step spans in Datadog have a model name attached.\n    const childInheritedModelAttrs =\n      span.type === SpanType.MODEL_GENERATION\n        ? {\n            model: (span.attributes as ModelGenerationAttributes | undefined)?.model,\n            provider: (span.attributes as ModelGenerationAttributes | undefined)?.provider,\n          }\n        : inheritedModelAttrs;\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    this.pendingSend = true;\n    tracer.llmobs.trace(traceOptions as any, (ddSpan: any) => {\n      // Annotate this span (must happen before finish — annotate throws on finished spans)\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 tags for proper Error Tracking UI\n      if (span.errorInfo) {\n        this.setErrorTags(ddSpan, span.errorInfo);\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, childInheritedModelAttrs);\n      }\n\n      // Explicitly finish with the correct end time. dd-trace's llmobs.trace() does not\n      // honor endTime in span options — it auto-finishes with Date.now() when the callback\n      // returns. By calling finish() here first, the auto-finish becomes a no-op (dd-trace\n      // skips finish if _duration is already set).\n      if (typeof ddSpan.finish === 'function') {\n        ddSpan.finish(endTimeMs);\n      }\n    });\n  }\n}\n"],"mappings":"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"}