/** * Datadog LLM Observability Exporter for Mastra * * Exports Mastra observability data to Datadog's LLM Observability product. * Uses a completion-only pattern where spans are emitted on span_ended events. * * Key features: * - Maps Mastra span types to Datadog span kinds * - Normalizes AI SDK v4/v5 token usage formats * - Formats LLM inputs/outputs as message arrays * - Flattens metadata into searchable tags * - Supports both agent and agentless modes */ import type { TracingEvent, ScoreEvent } from '@mastra/core/observability'; import { BaseExporter } from '@mastra/observability'; import type { BaseExporterConfig } from '@mastra/observability'; /** * Configuration options for the Datadog LLM Observability exporter. */ export interface DatadogExporterConfig extends BaseExporterConfig { /** * Datadog API key. Required (agentless mode is the default). * Falls back to DD_API_KEY environment variable. */ apiKey?: string; /** * ML application name for grouping traces. * Required - falls back to DD_LLMOBS_ML_APP environment variable. */ mlApp?: string; /** * Datadog site (e.g., 'datadoghq.com', 'datadoghq.eu'). * Falls back to DD_SITE environment variable, defaults to 'datadoghq.com'. */ site?: string; /** * Service name for the application. * Falls back to mlApp if not specified. */ service?: string; /** * Environment name (e.g., 'production', 'staging'). * Falls back to DD_ENV environment variable. */ env?: string; /** * Use agentless mode (direct HTTPS intake without local Datadog Agent). * Defaults to true for consistency with other Mastra exporters. * Set to false to use a local Datadog Agent instead. * Falls back to DD_LLMOBS_AGENTLESS_ENABLED environment variable. */ agentless?: boolean; /** * Enable dd-trace automatic integrations. * Defaults to false to avoid unexpected instrumentation. */ integrationsEnabled?: boolean; /** * Keys from the request context (set via `requestContextKeys` in the Mastra * Observability config) that should be promoted to flat Datadog LLM Observability * tags instead of being nested inside `annotations.metadata`. * * Flat tags are indexable and filterable in the Datadog LLM Observability UI, * which makes them suitable for multi-tenant filtering (e.g. tenantId, agentId). * * @example * ```typescript * new DatadogExporter({ * mlApp: 'my-app', * requestContextKeys: ['tenantId', 'agentId'], * }) * ``` */ requestContextKeys?: string[]; } /** * Datadog LLM Observability Exporter for Mastra. * * Exports observability data to Datadog's LLM Observability product using * a completion-only pattern where spans are emitted on span_ended events. */ export declare class DatadogExporter extends BaseExporter { name: string; private config; private traceContext; private traceState; constructor(config?: DatadogExporterConfig); /** * Main entry point for tracing events from Mastra. */ protected _exportTracingEvent(event: TracingEvent): Promise; /** * Captures user/session context from root spans for tagging all spans in the trace. */ private captureTraceContext; /** * Queue span until its parent context is available, then emit spans parent-first. */ private enqueueSpan; /** * Sets native dd-trace error tags required by Datadog's Error Tracking UI. */ private setErrorTags; /** * Builds annotations object for llmobs.annotate(). * Uses dd-trace's expected property names: inputData, outputData, metadata, tags, metrics. */ private buildAnnotations; /** * Submit an eval score to Datadog LLM Observability for the matching ddSpan. * * Ordering constraint: the matching span must have already been emitted to dd-trace * (i.e. its `SPAN_ENDED` event must have been processed and the trace tree flushed). * On Mastra's normal scoring path this is always true — scorer hooks fire after the * scored entity completes, so the root span has ended by the time `onScoreEvent` runs. * * If a score arrives for an unexported span (either before `SPAN_ENDED` or after the * `traceState` entry has been cleaned up), the event is dropped and a warning is logged * so the misuse is observable. Scores must therefore only be submitted for spans whose * lifecycle has completed. */ onScoreEvent(event: ScoreEvent): Promise; /** * Force flush any buffered spans without shutting down the exporter. * This is useful in serverless environments where you need to ensure spans * are exported before the runtime instance is terminated. */ flush(): Promise; /** * Gracefully shuts down the exporter. */ shutdown(): Promise; /** * Retrieve or initialize trace state for buffering and parent tracking. */ private getOrCreateTraceState; /** * Attempt to emit spans from the buffer. * * Two modes of operation: * 1. Initial tree emission: When root span ends and tree hasn't been emitted yet, * build a tree from all buffered spans and emit recursively using nested * llmobs.trace() calls. This ensures proper parent-child relationships in Datadog. * 2. Late-arriving spans: After the tree has been emitted, emit individual spans * with their parent context for proper linking. */ private tryEmitReadySpans; /** * Builds a tree structure from buffered spans based on parentSpanId relationships. * Returns the root node of the tree, or undefined if no root span is found. */ private buildSpanTree; /** * Builds LLMObs span options from a Mastra span. * Handles trace context, timestamps, and conditional model information for LLM spans. */ private buildSpanOptions; /** * Recursively emits a span tree using nested llmobs.trace() calls. * This ensures parent-child relationships are properly established in Datadog * because child spans are created while their parent span is active in scope. */ private emitSpanTree; /** * Emit a single span with the proper Datadog parent context. * Used for late-arriving spans after the main tree has been emitted. */ private emitSingleSpan; } //# sourceMappingURL=tracing.d.ts.map