From harness-claude
Adds OpenTelemetry tracing to Next.js apps via instrumentation hooks for Server Components, API routes, middleware, rendering, data fetching, and route resolution. Use for distributed tracing, debugging slow loads, and backend integration.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Add OpenTelemetry tracing to Next.js with the instrumentation hook for Server Components, API routes, and middleware
Integrates OpenTelemetry with NestJS using auto-instrumentation, tracing interceptors, decorators, and module-based tracer injection via DI. Traces controllers, services, guards, and HTTP calls.
Instruments apps with OpenTelemetry for distributed tracing and Jaeger/Tempo integration. Debugs latency in microservices, analyzes request flows, correlates traces with logs/metrics.
Sets up distributed tracing for microservices with OpenTelemetry, Jaeger, or Zipkin, handling instrumentation, context propagation, spans, and trace collection for request visibility.
Share bugs, ideas, or general feedback.
Add OpenTelemetry tracing to Next.js with the instrumentation hook for Server Components, API routes, and middleware
instrumentation.ts (or instrumentation.node.ts) in the project root — Next.js loads it automatically.register function that initializes the OpenTelemetry SDK. This runs once on server startup.instrumentationHook in next.config.js (Next.js 13-14). In Next.js 15+, it is enabled by default.@vercel/otel for simplified setup on Vercel, or configure the standard OTel SDK for any platform.// instrumentation.ts (project root)
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
// Only initialize on the Node.js runtime, not edge
const { NodeSDK } = await import('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } =
await import('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = await import('@opentelemetry/exporter-trace-otlp-http');
const { Resource } = await import('@opentelemetry/resources');
const { ATTR_SERVICE_NAME } = await import('@opentelemetry/semantic-conventions');
const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: process.env.OTEL_SERVICE_NAME || 'nextjs-app',
}),
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/traces',
}),
instrumentations: [
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-fs': { enabled: false },
}),
],
});
sdk.start();
}
}
// next.config.js (Next.js 13-14, not needed in 15+)
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
instrumentationHook: true,
},
};
module.exports = nextConfig;
// Simplified setup with @vercel/otel
// instrumentation.ts
import { registerOTel } from '@vercel/otel';
export function register() {
registerOTel({
serviceName: 'nextjs-app',
// Automatically configured for Vercel's tracing infrastructure
});
}
Next.js automatic spans: With OpenTelemetry configured, Next.js creates spans for:
next.route — route matching and resolutionnext.render — Server Component renderingnext.getServerSideProps — data fetching (Pages Router)next.fetch — server-side fetch() callsnext.middleware — middleware executionCustom spans in Server Components:
// app/dashboard/page.tsx
import { trace } from '@opentelemetry/api';
const tracer = trace.getTracer('dashboard');
export default async function DashboardPage() {
const data = await tracer.startActiveSpan('dashboard.loadData', async (span) => {
try {
const [users, metrics] = await Promise.all([
fetchUsers(),
fetchMetrics(),
]);
span.setAttribute('users.count', users.length);
return { users, metrics };
} finally {
span.end();
}
});
return <Dashboard data={data} />;
}
Custom spans in Route Handlers:
// app/api/orders/route.ts
import { trace, SpanStatusCode } from '@opentelemetry/api';
const tracer = trace.getTracer('orders-api');
export async function POST(request: Request) {
return tracer.startActiveSpan('orders.create', async (span) => {
try {
const body = await request.json();
span.setAttribute('order.items', body.items.length);
const order = await createOrder(body);
span.setAttribute('order.id', order.id);
return Response.json(order, { status: 201 });
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR });
span.recordException(error as Error);
return Response.json({ error: 'Failed' }, { status: 500 });
} finally {
span.end();
}
});
}
Edge runtime limitations: The Edge runtime does not support the full Node.js OTel SDK. For edge middleware and edge routes, use @vercel/otel which provides a lightweight implementation, or check for NEXT_RUNTIME === 'edge' and use a compatible exporter.
Vercel integration: On Vercel, use @vercel/otel for zero-config tracing. Traces are sent to Vercel's observability dashboard and can be forwarded to external backends (Datadog, Honeycomb, Axiom).
https://nextjs.org/docs/app/building-your-application/optimizing/open-telemetry