Capítulo 315 de 456

OpenTelemetry

Core Idea

Next.js já vem instrumentado com OpenTelemetry; habilitar via @vercel/otel no instrumentation.ts envolve automaticamente código como getStaticProps em spans com atributos úteis, sem precisar trocar de provedor de observabilidade depois.

Key Concepts

  • @vercel/otel: pacote que simplifica o setup verboso do OpenTelemetry puro; chamado dentro de register() em instrumentation.ts.
  • Configuração manual: usar NodeSDK diretamente dá mais controle, mas não é compatível com Edge runtime; precisa isolar em instrumentation.node.ts, importado condicionalmente só quando NEXT_RUNTIME === 'nodejs'.
  • NEXT_OTEL_VERBOSE=1: expõe mais spans que os emitidos por padrão, útil pra debug local.
  • NEXT_OTEL_FETCH_DISABLED=1: desliga o span automático de fetch, útil se você já usa outra lib de instrumentação de fetch.
  • Custom spans: via @opentelemetry/api, trace.getTracer(...).startActiveSpan(name, async (span) => { ...; span.end() }).
  • Spans automáticos do Next.js: cobrem request root ([http.method] [next.route]), render de rota, fetch, execução de Route Handler, getServerSideProps, getStaticProps, render de documento (pages), generateMetadata, resolução de componentes/módulos de segmento, e o zero-length span start response.
  • Atributos next.*: next.span_name, next.span_type, next.route, next.rsc, next.page (identificador interno usado com layout.ts/page.ts/etc, precisa combinar com next.route pra ser único).

Code Examples

import { registerOTel } from '@vercel/otel'

export function register() {
  registerOTel({ serviceName: 'next-app' })
}
  • O que demonstra: setup mínimo recomendado, delegando a complexidade do SDK ao @vercel/otel.
export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('./instrumentation.node.ts')
  }
}
const sdk = new NodeSDK({
  resource: resourceFromAttributes({ [ATTR_SERVICE_NAME]: 'next-app' }),
  spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter()),
})
sdk.start()
  • O que demonstra: setup manual com NodeSDK, isolado do Edge runtime via import condicional.
import { trace } from '@opentelemetry/api'

export async function fetchGithubStars() {
  return await trace.getTracer('nextjs-example').startActiveSpan('fetchGithubStars', async (span) => {
    try {
      return await getValue()
    } finally {
      span.end()
    }
  })
}
  • O que demonstra: criação de span custom em volta de uma chamada assíncrona, com span.end() garantido no finally.

Reference Tables

Spannext.span_typeO que representa
[http.method] [next.route]BaseServer.handleRequestRequest raiz
render route (app) [next.route]AppRender.getBodyResultRender de rota no App Router
fetch [http.method] [http.url]AppRender.fetchChamada fetch no código
executing api route (app) [next.route]AppRouteRouteHandlers.runHandlerExecução de Route Handler
getServerSideProps [next.route]Render.getServerSidePropsExecução de getServerSideProps
getStaticProps [next.route]Render.getStaticPropsExecução de getStaticProps
generateMetadata [next.page]ResolveMetadata.generateMetadataGeração de metadata

Anti-patterns

  • Usar NodeSDK sem isolar do Edge runtime: NodeSDK não é compatível com Edge; precisa de import condicional via NEXT_RUNTIME.
  • Esquecer span.end(): sempre chamar dentro de finally pra não deixar span aberto em caso de erro.

Key Takeaways

  1. @vercel/otel cobre a maioria dos casos com setup mínimo; configuração manual só quando precisa de algo que ele não expõe.
  2. Spans automáticos do Next.js já cobrem request, render, fetch, data fetching functions e API routes sem código extra.
  3. NEXT_OTEL_VERBOSE=1 e NEXT_OTEL_FETCH_DISABLED=1 são os dois env vars de controle mais usados em debug/produção.

Connects To

  • ch306 Instrumentation: OpenTelemetry é o caso de uso mais comum do register() em instrumentation.ts.
  • ch294 Analytics: outra forma de observabilidade, focada em Web Vitals em vez de tracing distribuído.