Jaeger no Node.js permite visualizar traces distribuídos, entender o caminho de uma requisição entre serviços e localizar onde a latência ou erro foi introduzido. Em arquiteturas com APIs, filas, bancos e chamadas externas, um log isolado mostra apenas parte do fluxo. Um trace conecta operações relacionadas por meio de trace ID, spans e relações de parentesco.
A integração moderna deve usar OpenTelemetry para instrumentar a aplicação e exportar dados via OTLP. Jaeger recebe, armazena e apresenta os traces em uma interface que mostra timeline, duração, tags, eventos, status e dependências.
Neste guia, você aprenderá a executar Jaeger, configurar OpenTelemetry no Node.js, usar instrumentação automática e spans manuais, propagar contexto, aplicar sampling, proteger dados e analisar gargalos.
O que é Jaeger?
Jaeger é uma plataforma open source de distributed tracing. A documentação atual de Getting Started do Jaeger recomenda instrumentar aplicações com OpenTelemetry e enviar dados pelos protocolos suportados.
Os componentes principais incluem:
- Collector: recebe spans;
- Query: oferece API e interface de consulta;
- Storage: persiste traces;
- UI: permite buscar e analisar;
- OTLP endpoints: recebem OpenTelemetry por gRPC ou HTTP.
Trace, span e contexto
Um trace representa uma operação completa, como criar um pedido. Cada etapa é um span:
- requisição HTTP recebida;
- validação;
- consulta PostgreSQL;
- chamada ao pagamento;
- publicação em fila;
- resposta ao cliente.
Spans possuem nome, início, duração, status, atributos e eventos. O contexto contém trace ID e span ID propagados entre processos.
Para fundamentos e pacotes, consulte OpenTelemetry no Node.js.
Executando Jaeger localmente
docker run --rm --name jaeger \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
cr.jaegertracing.io/jaegertracing/jaeger:2.20.0A interface fica em http://localhost:16686. A configuração all-in-one usa armazenamento transitório e é adequada para desenvolvimento, não para produção.
Instalando OpenTelemetry
npm install \
@opentelemetry/sdk-node \
@opentelemetry/api \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-proto \
@opentelemetry/resources \
@opentelemetry/semantic-conventionsFixe versões compatíveis e teste a inicialização antes de atualizar o runtime.
Arquivo de instrumentação
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
const sdk = new NodeSDK({
resource: resourceFromAttributes({
[ATTR_SERVICE_NAME]: 'orders-api',
[ATTR_SERVICE_VERSION]: process.env.APP_VERSION ?? 'dev',
'deployment.environment.name': process.env.NODE_ENV ?? 'development'
}),
traceExporter: new OTLPTraceExporter({
url: 'http://localhost:4318/v1/traces'
}),
instrumentations: [getNodeAutoInstrumentations()]
});
sdk.start();
process.once('SIGTERM', async () => {
await sdk.shutdown();
});Carregue antes da aplicação
A instrumentação precisa ser inicializada antes de importar frameworks e clientes:
node --import ./instrumentation.js server.jsSe Express, HTTP ou banco forem carregados primeiro, a instrumentação automática pode não aplicar os patches.
Variáveis OTEL
Também é possível configurar por ambiente:
OTEL_SERVICE_NAME=orders-api
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=productionEvite colocar segredos em atributos.
Instrumentação automática
O pacote contrib pode instrumentar HTTP, Express, Fastify, bancos e outras bibliotecas. Revise quais instrumentações estão habilitadas e o volume gerado.
getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-fs': {
enabled: false
}
})Desative módulos ruidosos ou sem valor para o diagnóstico.
Span manual
import { trace, SpanStatusCode } from '@opentelemetry/api';
const tracer = trace.getTracer('orders-domain');
export async function createOrder(input) {
return tracer.startActiveSpan('order.create', async span => {
try {
span.setAttributes({
'order.items_count': input.items.length,
'order.channel': input.channel
});
const order = await service.execute(input);
span.setAttribute('order.status', order.status);
return order;
} catch (error) {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
throw error;
} finally {
span.end();
}
});
}Use nomes estáveis e orientados à operação. Não inclua IDs no nome do span.
Atributos seguros
Bons atributos possuem baixa cardinalidade:
- método HTTP;
- rota normalizada;
- status;
- nome da dependência;
- tipo da operação;
- ambiente e versão;
- resultado de negócio categorizado.
Evite:
- senhas;
- tokens;
- corpo completo;
- e-mail;
- cartão;
- SQL com valores;
- headers sensíveis.
Eventos dentro do span
span.addEvent('inventory_reserved', {
'inventory.items_count': items.length
});Eventos marcam momentos relevantes sem criar spans desnecessários.
Propagação HTTP
OpenTelemetry usa headers W3C Trace Context, como traceparent. A instrumentação automática de HTTP injeta e extrai o contexto. Proxies e gateways devem preservar headers permitidos.
Filas e mensagens
Em RabbitMQ, Kafka, NATS ou Redis Streams, propague contexto nos headers da mensagem. Não dependa de AsyncLocalStorage atravessar processos.
Para mensageria, consulte Kafka com Node.js e NATS no Node.js.
Jobs assíncronos
Um consumidor pode iniciar span ligado ao contexto recebido. Se o processamento ocorre muito depois, avalie links em vez de uma relação pai-filho longa. Isso representa causalidade sem distorcer a timeline.
Sampling
Registrar todos os traces pode ser caro. Estratégias comuns:
- sempre em desenvolvimento;
- probabilístico em produção;
- parent-based para respeitar decisão anterior;
- tail sampling no collector para manter erros e traces lentos.
Sampling no início não sabe se o trace terminará com erro. Tail sampling analisa o trace completo, mas exige collector com memória e capacidade adequadas.
Collector intermediário
Em produção, envie OTLP para um OpenTelemetry Collector ou Grafana Alloy, não diretamente de todos os serviços ao backend. O collector oferece:
- batch;
- retry;
- fila persistente;
- sampling;
- redação;
- roteamento;
- autenticação;
- telemetria do pipeline.
Timeout e falha do exporter
Tracing não deve bloquear a requisição. Exporters usam batch e envio assíncrono. Defina limites e monitore spans descartados. Se o collector estiver indisponível, a aplicação deve continuar operando dentro da política estabelecida.
Analisando um trace
Na UI do Jaeger, observe:
- duração total;
- span crítico mais longo;
- operações em série;
- gaps sem instrumentação;
- erros registrados;
- retries;
- fan-out excessivo;
- dependências lentas.
Caminho crítico
Nem todo span longo determina a duração final. Dois spans podem executar em paralelo. O caminho crítico é a sequência que define o tempo total. Analise relações e sobreposição na timeline.
Exemplo de consultas sequenciais
Se três consultas independentes aparecem em sequência, considere paralelizar:
const [customer, inventory, pricing] = await Promise.all([
customers.findById(customerId),
inventory.get(items),
pricing.calculate(items)
]);Confirme limites do pool e tratamento de falhas antes da mudança.
Correlação com logs
Inclua trace ID nos logs:
import { trace } from '@opentelemetry/api';
const span = trace.getActiveSpan();
const context = span?.spanContext();
logger.info({
traceId: context?.traceId,
spanId: context?.spanId
}, 'Pedido processado');Veja Grafana Loki no Node.js.
Service Performance Monitoring
Jaeger pode derivar métricas RED — taxa, erros e duração — a partir de spans quando o pipeline está configurado. Essas métricas ajudam a navegar do dashboard para traces exemplares.
Armazenamento
O modo all-in-one usa memória. Produção requer backend persistente e dimensionado, como Elasticsearch, OpenSearch ou outro suportado pela versão. Defina retenção, índices, replicação e backup.
Consulte Elasticsearch no Node.js para integração de busca, lembrando que o backend do Jaeger é uma responsabilidade operacional separada.
Segurança
- Use TLS para OTLP.
- Autentique collectors.
- Não exponha a UI publicamente.
- Restrinja acesso por ambiente.
- Redija atributos.
- Separe tenants quando necessário.
- Audite consultas.
Kubernetes
Em Kubernetes, execute collectors próximos às aplicações e componentes Jaeger conforme o modo de deployment escolhido. Configure requests, limits, readiness, storage e autoscaling.
Veja Probes Kubernetes em Node.js.
Shutdown
Finalize o SDK para exportar spans pendentes:
await sdk.shutdown();Integre ao graceful shutdown sem prolongar indefinidamente. Defina timeout para telemetria.
Testes
Em testes unitários, use exporter em memória e verifique:
- nome do span;
- atributos esperados;
- status de erro;
- propagação;
- ausência de dados sensíveis.
Não torne testes dependentes de timestamps exatos.
Overhead
Instrumentação, atributos e exportação consomem CPU e memória. Meça com carga real. Reduza spans redundantes, atributos grandes e instrumentações sem valor.
Erros comuns
- Carregar SDK tarde: instrumentação automática não funciona.
- Nome com ID: busca fica fragmentada.
- Dados sensíveis: trace vira fonte de vazamento.
- Sem propagação em filas: trace quebra.
- Exportar direto sem collector: resiliência diminui.
- Amostrar demais: custo cresce.
- Amostrar de menos: incidentes não aparecem.
- All-in-one em produção: dados são perdidos.
Conclusão
Jaeger no Node.js transforma operações distribuídas em timelines conectadas. Com OpenTelemetry, cada serviço produz spans padronizados e exporta por OTLP, enquanto Jaeger oferece busca, visualização e análise do caminho crítico.
Comece com instrumentação automática, adicione spans manuais apenas em operações de negócio importantes, propague contexto por HTTP e mensagens, e controle sampling e dados sensíveis. Com collector, storage e segurança adequados, Jaeger ajuda a encontrar latência e falhas que seriam difíceis de reconstruir apenas com logs.



