observability/otel-bridge/README.md
OpenTelemetry Bridge for Mastra Observability.
Enables bidirectional integration between Mastra and OpenTelemetry infrastructure, creating real OTEL spans for Mastra operations and maintaining proper trace hierarchy.
@mastra/otel-bridge connects Mastra's observability system with standard OpenTelemetry instrumentation through bidirectional integration:
From OTEL to Mastra:
From Mastra to OTEL:
npm install @mastra/otel-bridge
# or
pnpm add @mastra/otel-bridge
For the standard OTEL setup (recommended), also install:
npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node
# or
pnpm add @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node
Create an instrumentation.js file and import it before any other code:
// instrumentation.js
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
const sdk = new NodeSDK({
serviceName: 'my-service',
traceExporter: new OTLPTraceExporter({
url: 'http://localhost:4318/v1/traces',
}),
instrumentations: [
getNodeAutoInstrumentations({
// Automatically instruments Express, Fastify, HTTP, and many others
'@opentelemetry/instrumentation-fs': {
enabled: false,
},
}),
],
});
sdk.start();
process.on('SIGTERM', async () => {
await sdk.shutdown();
process.exit(0);
});
Then import this file first in your application:
// IMPORTANT: Import instrumentation FIRST!
import './instrumentation.js';
// Now import your application code
import express from 'express';
import { Mastra } from '@mastra/core';
// ... rest of your imports
import { OtelBridge } from '@mastra/otel-bridge';
import { Mastra } from '@mastra/core';
import { Observability } from '@mastra/observability';
const mastra = new Mastra({
agents: { myAgent },
observability: new Observability({
configs: {
default: {
serviceName: 'my-service',
bridge: new OtelBridge(),
},
},
}),
});
The OTEL SDK's auto-instrumentation handles context propagation automatically via AsyncLocalStorage. The bridge creates OTEL spans for all Mastra operations.
// Example: Express endpoint using Mastra agent
app.post('/chat', async (req, res) => {
// OTEL auto-instrumentation creates HTTP span
// Bridge inherits trace context and creates child spans for agent operations
const result = await myAgent.generate(req.body.message);
res.json(result);
});
When Mastra creates a span (agent run, LLM call, tool execution, etc.):
Bridge creates OTEL span at span creation time with:
Mastra uses OTEL IDs:
spanId = OTEL span's 16-char hex IDtraceId = OTEL span's 32-char hex trace IDparentSpanId = parent OTEL span's IDInternal spans are skipped:
When a Mastra span ends:
gen_ai.*)chat gpt-4, agent.my-agent)The bridge provides executeInContext() and executeInContextSync() to run code within a Mastra span's OTEL context. This allows OTEL-instrumented code (DB clients, HTTP clients) to nest correctly under Mastra spans.
@mastra/core >= 1.0.0@opentelemetry/api >= 1.9.0For Standard OTEL Setup:
@opentelemetry/sdk-node >= 0.205.0@opentelemetry/auto-instrumentations-node >= 0.64.1Apache 2.0