Collect performance metrics and traces from both the browser and the server-side runtime of your Next.js app.
npm install @opentelemetry/api @opentelemetry/sdk-trace-web @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http next-otelCreate src/otel/web.js:
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-web';
const provider = new WebTracerProvider();
provider.addSpanProcessor(
new SimpleSpanProcessor(
new OTLPTraceExporter({
url: process.env.NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT,
headers: { 'mcp-token': process.env.NEXT_PUBLIC_MCP_TOKEN },
})
)
);
provider.register();import it in _app.tsx:
if (typeof window !== 'undefined') {
import('../otel/web');
}Create otel.server.js in project root:
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
headers: { 'mcp-token': process.env.MCP_TOKEN },
}),
});
sdk.start();Add to server.js or custom next start entry point:
require('./otel.server');
const next = require('next');
// ... your Next.js server code| Variable | Example |
|---|---|
| NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT | https://mcp.example.com:4318 |
| NEXT_PUBLIC_MCP_TOKEN | 4d3c9f... |
| OTEL_EXPORTER_OTLP_ENDPOINT | http://otel-collector.observability.svc:4318 |
| MCP_TOKEN | 4d3c9f... |
- Open Explore and query
trace_idto see client→server spans. - Dashboards ▸ Web Vitals will show FCP, LCP, CLS if you export them as metrics.
"You are an AI coding agent. Instrument the current Next.js app with OpenTelemetry on both client and server. Requirements:\n\n* Use
next-otelif available, otherwise manual setup.\n* Export to${OTEL_EXPORTER_OTLP_ENDPOINT}with${MCP_TOKEN}header.\n* Capture web vitals and API route traces.\n* UpdateDockerfileandVercelenv vars."
Paste into Cursor or Claude to auto-modify your repo.
| Symptom | Cause | Fix |
|---|---|---|
ReferenceError: window during build |
Client tracer imported on server | Import only in browser (see _app.tsx) |
| Spans dropped | CORS block | Add OTLP endpoint domain to allowed origins |