IDs de Correlação de Requisição
Rastreie uma única requisição de usuário através de logs e serviços com x-request-id - aceite IDs de entrada, gere quando ausente e encaminhe para chamadas downstream.
Busque em todas as páginas da documentação
Rastreie uma única requisição de usuário através de logs e serviços com x-request-id - aceite IDs de entrada, gere quando ausente e encaminhe para chamadas downstream.
Cartão de receita de referência rápida - pronto para copiar e colar.
import { randomUUID } from "node:crypto";
function getRequestId(header: string | string[] | undefined): string {
const raw = Array.isArray(header) ? header[0] : header;
return raw && raw.length <= 128 ? raw : randomUUID();
}
// Middleware
app.use((req, res, next) => {
const requestId = getRequestId(req.headers["x-request-id"]);
req.headers["x-request-id"] = requestId;
res.setHeader("x-request-id", requestId);
req.log = logger.child({ requestId });
next();
});Quando usar isso:
import express from "express";
import pino from "pino";
import { randomUUID } from "node:crypto";
const logger = pino({ level: "info" });
const app = express();
app.use(express.json());
app.use((req, res, next) => {
const incoming = req.headers["x-request-id"];
const requestId = typeof incoming === "string" && incoming.length <= 128
? incoming
: randomUUID();
res.setHeader("x-request-id", requestId);
(req as express.Request & { log: pino.Logger; requestId: string }).log =
logger.child({ requestId });
(req as express.Request & { requestId: string }).requestId = requestId;
req.log.info({ event: "request_start", method: req.method, path: req.path });
next();
});
async function fetchBillingProfile(requestId: string, userId: string) {
const res = await fetch(`https://billing.internal/users/${userId}`, {
headers: { "x-request-id": requestId },
signal: AbortSignal.timeout(3_000),
});
return res.json();
}
app.get("/users/:id/summary", async (req, res) => {
const billing = await fetchBillingProfile(req.requestId, req.params.id);
req.log.info({ event: "summary_built", billingStatus: billing.status });
res.json({ userId: req.params.id, billing });
});
app.listen(3000);O que isso demonstra:
x-request-id de entrada preservado quando presente e limitado (128 caracteres).fetch de saída encaminha o ID para serviços internos.requestId via logger filho.x-request-id primeiro.trace_id do OpenTelemetry pode coexistir - muitas equipes mapeiam x-request-id para a raiz do trace ou baggage.| Cabeçalho | Uso |
|---|---|
x-request-id | Padrão de fato para APIs HTTP |
traceparent | Contexto de trace W3C (OTel) |
x-correlation-id | Sistemas corporativos legados |
Escolha um ID principal nos logs; suporte ambos os cabeçalhos na borda durante a migração.
const app = Fastify({
genReqId: (req) => req.headers["x-request-id"] as string ?? randomUUID(),
requestIdHeader: "x-request-id",
requestIdLogLabel: "requestId",
});req.id e req.log integrados - menos boilerplate de middleware.await queue.add("send-email", payload, {
headers: { "x-request-id": req.requestId },
});res.setHeader("x-request-id", id).req.log.setImmediate perde req. Correção: AsyncLocalStorage ou capture o ID no closure.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| x-request-id | Correlação simples de logs | Precisa de tempo pai/filho de span |
| OpenTelemetry trace_id | Rastreamento distribuído completo | API MVP mínima |
| AWS X-Ray trace header | Pilha nativa da AWS | Padrão OTel multi-nuvem |
| Cabeçalho personalizado por organização | Mandato corporativo legado | API pública Greenfield |
ULIDs são ordenáveis por tempo - úteis em índices de log. UUID v4 é universalmente reconhecido. Qualquer um funciona se documentado.
Gateway, se presente - consistente entre microsserviços. O aplicativo gera quando o gateway não o faz.
Registre ambos durante a migração OTel: logger.child({ requestId, trace_id }) do contexto de span ativo.
Mesmo middleware - um ID por requisição HTTP, independentemente da contagem de consultas.
Mesmo x-request-id em todos os fetches paralelos de uma requisição de entrada. Spans filhos se diferenciam em OTel.
nestjs-pino suporta genReqId. Ou middleware + CLS (continuation-local-storage).
requestId:"abc-123" em Datadog/Loki - o campo deve ser uma chave JSON de nível superior em cada linha.
Ainda é bom gerar - baixo volume. Ou pular o registro de integridade completamente.
Versões da Stack: Esta página foi escrita para Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 e NestJS 11.
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026