Skip to content

observability

Mastra observability wired through the same OTel pipeline AppKit’s built-in plugins (e.g. agents) use, via @mastra/otel-bridge.

How traces flow:

  1. @databricks/appkit boots a global NodeSDK in TelemetryManager.initialize() (during createApp) when OTEL_EXPORTER_OTLP_ENDPOINT is set in the process env.
  2. Every AppKit plugin span (e.g. the agents plugin’s executeStream) is created via the global OTel tracer (trace.getTracer(<plugin>)), so it lands on that NodeSDK and is shipped through its OTLP exporter.
  3. The Mastra OtelBridge ALSO creates real OTel spans on the same global tracer for every Mastra operation (agent runs, model calls, tool invocations, workflow steps). They inherit the ambient OTel context, so when Mastra is invoked from inside an AppKit HTTP span the trace stays connected.

Net effect: Mastra spans get exactly the treatment AppKit’s agents plugin gets. No custom OTLP pipeline lives in this package; the OTLP endpoint, headers, and resource attributes are driven by the standard OTel env vars (OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS, OTEL_SERVICE_NAME, OTEL_RESOURCE_ATTRIBUTES, …) and consumed by AppKit’s TelemetryManager. Set those once and both AppKit and Mastra spans end up at the same backend.

When OTEL_EXPORTER_OTLP_ENDPOINT is unset the bridge is not registered at all (unless observability: true forces it on), so Mastra does not emit [OtelBridge] No OTEL span found warnings.

On Databricks Apps the supported sink is Unity Catalog via telemetry_export_destinations (the platform injects the local OTLP sidecar). Managed MLflow has no OTLP ingest endpoint - do not point OTEL_EXPORTER_OTLP_* at the workspace host. Set OTEL_PROPAGATORS=none so Apps ingress traceparent does not hide every request-scoped root span from the UC *_trace_unified view. Chat request/response on that root span is stamped by traceIo.attachChatTurnTraceIo (see trace-io.ts).