Capítulo 116 de 456

instrumentation.js

Core Idea

instrumentation.js|ts (na raiz do projeto ou dentro de src/) integra ferramentas de observabilidade, exportando um hook register que roda uma vez na inicialização do servidor e um hook onRequestError para rastrear erros de servidor em qualquer provedor.

Key Concepts

  • register() (opcional): chamada uma única vez quando uma nova instância do servidor Next.js inicia; deve completar antes do servidor aceitar requests; pode ser async.
  • onRequestError() (opcional): rastreia erros do servidor; recebe (error, request, context); tarefas async dentro dela precisam ser awaitadas.
  • error tipado unknown: pode não ser a instância original do erro (React pode reprocessá-lo durante RSC rendering); use digest para identificar o erro real.
  • context.routeType: 'render' | 'route' | 'action' | 'proxy', identifica onde o erro ocorreu.
  • context.renderType: 'dynamic' | 'dynamic-resume' ('dynamic-resume' é específico de PPR).
  • Runtime targeting: instrumentation.js roda tanto em Node.js quanto Edge runtime; use process.env.NEXT_RUNTIME === 'edge' para diferenciar comportamento.

Code Examples

import { registerOTel } from '@vercel/otel'

export function register() {
  registerOTel('next-app')
}
  • O que demonstra: registro de OpenTelemetry no startup do servidor.
import { type Instrumentation } from 'next'

export const onRequestError: Instrumentation.onRequestError = async (
  err,
  request,
  context
) => {
  const message = err instanceof Error ? err.message : String(err)
  const digest =
    typeof err === 'object' && err !== null && 'digest' in err
      ? String(err.digest)
      : undefined

  await fetch('https://.../report-error', {
    method: 'POST',
    body: JSON.stringify({ message, digest, request, context }),
    headers: { 'Content-Type': 'application/json' },
  })
}
  • O que demonstra: reporte de erro server-side para um serviço externo, narrowing seguro de unknown antes de ler message/digest.

Reference Tables

ParâmetroTipoConteúdo
errorunknownprecisa narrowing antes de ler message/digest
request.pathstringex. /blog?name=foo
request.methodstringGET, POST, etc
request.headers{ [key: string]: string | string[] }headers da request
context.routerKind'Pages Router' | 'App Router'tipo de router
context.routeType'render' | 'route' | 'action' | 'proxy'contexto do erro
context.renderSource'react-server-components' | 'react-server-components-payload' | 'server-rendering'origem do render
context.revalidateReason'on-demand' | 'stale' | undefinedmotivo de revalidação (undefined = request normal)
context.renderType'dynamic' | 'dynamic-resume'tipo de render (dynamic-resume é PPR)

Anti-patterns

  • Não aguardar tarefa async dentro de onRequestError: pode não completar antes do processo seguir; sempre await.
  • Ler error.message sem narrowing: error é unknown, acesso direto quebra o type-check.
  • Assumir que error é sempre a instância original lançada: React pode reprocessar o erro durante RSC rendering; use digest para correlação confiável.

Key Takeaways

  1. register roda uma única vez por instância de servidor, ideal para setup de tracing/observability (ex. OpenTelemetry).
  2. onRequestError complementa error.js: enquanto error.js mostra UI ao usuário, onRequestError reporta ao backend de observabilidade.
  3. Use NEXT_RUNTIME para requerer módulos diferentes por runtime (Node.js vs Edge), evitando importar dependências incompatíveis.

Connects To

  • File-system conventions (ch111): índice das convenções.
  • instrumentation-client.js (ch117): contraparte client-side de instrumentação.
  • error.js (ch114): usa digest do mesmo jeito para correlacionar erro exibido ao usuário com log do servidor.