Quando uma aplicação Node.js trava, consome memória demais ou encerra sem explicação clara, logs comuns podem não conter contexto suficiente. O recurso de Diagnostic Report no Node.js gera um arquivo detalhado com informações do processo, sistema operacional, versões, stacks, heap, handles e eventos que ajudam a investigar falhas difíceis.
O relatório pode ser criado manualmente, por sinal, em exceções não tratadas ou quando ocorre um erro fatal. Como o arquivo pode incluir caminhos, argumentos, variáveis e detalhes internos, ele precisa ser armazenado e compartilhado com o mesmo cuidado usado para dumps e snapshots.
Neste guia, você aprenderá a habilitar relatórios pela linha de comando, usar process.report, definir diretório e nome, gerar arquivos em eventos específicos, interpretar as seções, trabalhar com containers, correlacionar com logs e proteger dados sensíveis.
O que é um Diagnostic Report?
É um documento, normalmente em JSON, que descreve o estado do processo no momento da captura. A documentação oficial de Diagnostic Report explica as opções e a API. O material oficial de diagnóstico do Node.js complementa a análise de memória e incidentes.
Para compreender propriedades do processo, veja Objeto Process no Node.js. Para capturas de heap e perfis de CPU, consulte Inspector no Node.js.
Gerando um relatório manualmente
const filename = process.report.writeReport();
console.log('Relatório criado:', filename);O método retorna o caminho do arquivo criado. O nome padrão inclui informações que ajudam a evitar colisões, mas em ambientes concorrentes é melhor definir um padrão explícito.
Definindo o nome
const path = require('node:path');
const filename = path.join(
'/var/diagnostics',
`report-${process.pid}-${Date.now()}.json`
);
process.report.writeReport(filename);Use um diretório com espaço controlado, permissões restritas e política de limpeza. O processo precisa ter permissão de escrita.
Obtendo o relatório em memória
const report = process.report.getReport();
console.log({
event: report.header?.event,
pid: report.header?.processId,
nodeVersion: report.header?.nodejsVersion
});getReport() retorna um objeto. Evite serializar ou registrar tudo em stdout, porque o conteúdo pode ser grande e sensível.
Relatório em exceção não tratada
node --report-uncaught-exception server.jsEssa opção solicita um relatório quando uma exceção não tratada encerra o processo. Ela é útil em ambientes onde o supervisor reinicia a aplicação, mas o arquivo precisa persistir fora do container efêmero.
Relatório em erro fatal
node --report-on-fatalerror server.jsErros fatais do runtime são diferentes de exceções JavaScript comuns. Um relatório pode registrar informações antes do encerramento, embora nem toda falha permita concluir a gravação.
Relatório por sinal
node --report-on-signal server.jsEm sistemas compatíveis, um sinal pode acionar a captura. A opção e o sinal padrão dependem da plataforma e da versão. Consulte a documentação do runtime usado.
Configurando o sinal
node \
--report-on-signal \
--report-signal=SIGUSR2 \
server.jsNão use um sinal já reservado pela sua aplicação ou pelo gerenciador de processos. Documente a operação para a equipe de suporte.
Diretório de saída
node \
--report-directory=/var/diagnostics \
server.jsO diretório deve existir, ter permissões corretas e possuir limite de armazenamento. Em Kubernetes, use um volume temporário ou persistente conforme a necessidade de investigação.
Padrão do nome
node \
--report-filename=incident-report.json \
server.jsUm nome fixo pode sobrescrever capturas anteriores. Inclua PID, timestamp ou identificador de instância quando várias execuções compartilham o diretório.
Configuração pela API
process.report.directory = '/var/diagnostics';
process.report.filename = '';
process.report.reportOnFatalError = true;
process.report.reportOnUncaughtException = true;Propriedades disponíveis variam conforme a versão. Valide durante a inicialização e registre apenas a configuração não sensível.
Seções do relatório
Um relatório costuma conter:
- cabeçalho e motivo da captura;
- versões do Node.js e componentes;
- informações do sistema operacional;
- stack JavaScript;
- stack nativa;
- estatísticas de heap;
- uso de recursos;
- handles e requisições ativas;
- informações de threads;
- variáveis de ambiente, conforme configuração e versão.
A estrutura pode mudar. Crie parsers defensivos e não dependa de todos os campos.
Cabeçalho
O cabeçalho ajuda a responder:
- qual evento gerou o arquivo;
- quando ocorreu;
- qual era o PID;
- qual versão do Node.js estava em uso;
- qual plataforma e arquitetura;
- qual diretório de trabalho;
- quais argumentos iniciaram o processo.
Argumentos podem conter segredos quando a aplicação recebe tokens pela linha de comando. Evite esse padrão.
Stacks JavaScript e nativas
A stack JavaScript mostra o caminho de execução conhecido no momento da captura. A stack nativa pode ajudar em falhas do runtime, addons ou bibliotecas nativas.
Stacks não provam a causa por si só. Compare com logs, versão, carga e outros incidentes.
Heap
O relatório inclui estatísticas agregadas de memória, mas não substitui um heap snapshot. Ele ajuda a observar heap usado, limites e espaços do V8.
Para análise detalhada de objetos e referências, use Módulo V8 no Node.js e o Inspector. Capturas de heap possuem custo e risco maiores.
Handles ativos
Handles podem explicar por que o processo não termina:
- servidores;
- sockets;
- timers;
- pipes;
- watchers;
- requisições de filesystem;
- conexões IPC.
Um handle ativo pode ser legítimo. Compare com a arquitetura e com o momento do shutdown.
Investigando processo que não encerra
Durante um Graceful Shutdown no Node.js, capture um relatório se o prazo máximo for ultrapassado:
const shutdownTimeout = setTimeout(() => {
const filename = process.report.writeReport();
emergencyLogger.error('shutdown_timeout', { filename });
process.exitCode = 1;
}, 30000);Use esse mecanismo apenas para diagnóstico. O relatório não substitui fechamento correto de recursos.
Investigando crescimento de memória
Capture relatórios em intervalos espaçados quando o RSS ultrapassar limites:
function maybeCaptureReport() {
const { rss } = process.memoryUsage();
const limit = 1_500_000_000;
if (rss > limit && canCapture()) {
process.report.writeReport();
}
}Implemente cooldown para impedir milhares de arquivos durante um incidente.
Relatórios e Trace Events
O relatório é uma fotografia do estado. Trace Events no Node.js oferece uma linha do tempo. Use o relatório para contexto geral e trace events para entender a sequência temporal antes do problema.
Relatórios e OpenTelemetry
O OpenTelemetry no Node.js ajuda a identificar a instância com erro e a operação afetada. Registre o identificador do incidente e associe ao nome do relatório sem incluir o arquivo inteiro nos spans.
Containers
O filesystem de um container pode desaparecer após reinício. Grave relatórios em volume montado ou envie o arquivo para armazenamento seguro antes da remoção do pod.
Não bloqueie o encerramento por tempo indefinido esperando upload. Prefira um sidecar, agente ou volume coletado pela plataforma.
Cluster
Cada worker cria seu próprio relatório. Inclua PID e worker ID no nome. Um arquivo do processo primário não contém necessariamente o estado completo de todos os workers.
Em incidentes, capture primeiro o worker afetado para reduzir volume.
Worker Threads
Relatórios podem conter informações sobre threads, mas detalhes dependem da versão. Tarefas em Worker Threads ainda compartilham o processo e podem afetar RSS e CPU totais.
Automação em produção
Uma automação segura precisa de:
- limite de capturas por período;
- espaço máximo de disco;
- nome único;
- permissões restritas;
- remoção programada;
- registro do motivo;
- monitoramento do tempo de gravação;
- alerta para falha de captura.
Dados sensíveis
Relatórios podem incluir:
- argumentos da linha de comando;
- caminhos internos;
- nomes de host;
- interfaces de rede;
- variáveis de ambiente;
- stacks com nomes de funções;
- detalhes de módulos nativos.
Não anexe o arquivo a tickets públicos. Use controle de acesso, criptografia e prazo de retenção.
Sanitização
Sanitizar um relatório depois da captura é difícil porque o formato é extenso. A melhor estratégia é evitar segredos em argumentos e ambiente, restringir acesso e analisar em local seguro.
Se for necessário compartilhar, crie uma cópia revisada e mantenha o original protegido.
Custo da captura
Gerar o arquivo consome CPU, memória e I/O. Em uma aplicação sobrecarregada, a operação pode aumentar latência. Faça testes com tamanho de heap e carga representativos.
Testando relatórios
Em homologação, valide:
- criação manual;
- diretório e nome;
- permissões;
- captura por sinal;
- captura em exceção;
- rotação e remoção;
- abertura do JSON;
- ausência de segredos óbvios;
- persistência após reinício do container.
Parser simples
const fs = require('node:fs/promises');
async function summarizeReport(filename) {
const data = JSON.parse(await fs.readFile(filename, 'utf8'));
return {
event: data.header?.event,
pid: data.header?.processId,
version: data.header?.nodejsVersion,
heapUsed: data.javascriptHeap?.usedMemory,
rss: data.resourceUsage?.rss
};
}Campos podem ser ausentes. Trate valores opcionalmente e preserve o arquivo original.
Erros comuns
- Usar nome fixo: capturas anteriores são sobrescritas.
- Gravar no container efêmero: o arquivo desaparece.
- Capturar sem cooldown: o disco é preenchido.
- Publicar em ticket: detalhes internos ficam expostos.
- Tratar relatório como heap snapshot: faltam referências de objetos.
- Ignorar custo de I/O: a latência piora durante o incidente.
- Depender de campos fixos: versões podem mudar a estrutura.
Boas práticas
- Defina diretório controlado.
- Use nomes únicos.
- Aplique cooldown.
- Limite o espaço em disco.
- Proteja acesso e transporte.
- Associe o arquivo a logs e alertas.
- Teste em containers.
- Evite segredos em argumentos.
- Remova arquivos antigos.
- Combine com profiling e métricas.
Conclusão
O Diagnostic Report no Node.js oferece uma fotografia detalhada do processo e ajuda a investigar exceções, erros fatais, consumo de memória, handles ativos e encerramentos problemáticos.
O recurso é mais útil quando preparado antes do incidente: diretório persistente, nome único, limites, cooldown e acesso restrito. Com relatórios correlacionados a logs, métricas, Trace Events e Inspector, a equipe consegue reconstruir o contexto de falhas difíceis sem depender apenas de mensagens incompletas.




