Conceptos básicos de registro
8 ejemplos para empezar a usar Logging para backends de Node.js: 6 básicos y 2 intermedios.
Busca en todas las páginas de la documentación
8 ejemplos para empezar a usar Logging para backends de Node.js: 6 básicos y 2 intermedios.
npm install pino
npm install -D pino-pretty typescript@5.6 tsxLos servicios de producción en Node 24.18.0 deben emitir JSON estructurado a stdout; los agregadores (Datadog, Loki, CloudWatch) analizan un objeto por línea.
Las máquinas analizan campos; los humanos buscan level y requestId.
import pino from "pino";
const logger = pino({ level: "info" });
logger.info({ userId: "u_123", action: "login_success" }, "user logged in");
// {"level":30,"userId":"u_123","action":"login_success","msg":"user logged in",...}`User ${id} logged in` pierden campos buscables.level 30 es info en el mapeo numérico de Pino.Relacionado: pino - loggers hijos y redacción
Elige el nivel que coincida con la respuesta del operador, no con el estado de ánimo del desarrollador.
logger.fatal({ err }, "database unreachable at boot");
logger.error({ err, orderId }, "payment capture failed");
logger.warn({ retryCount: 3 }, "downstream timeout, retrying");
logger.info({ requestId }, "request completed");
logger.debug({ query }, "sql executed");error - necesita investigación o impacto en el usuario.warn - degradado pero recuperándose (reintentos, alternativas).info - eventos normales del ciclo de vida del negocio y de la solicitud.debug - solo desarrollo o muestreado en producción.Relacionado: Mejores prácticas de registro - política de nivel de registro de producción
errEl serializador estándar de Pino captura los seguimientos de pila.
try {
await chargeCard(orderId);
} catch (err) {
logger.error({ err, orderId }, "charge failed");
}{ err } activa pino.stdSerializers.err - la pila y el tipo se conservan.logger.error(err) sin el envoltorio de objeto pierde la estructura del campo.Relacionado: Estándares de respuesta de error - detalle del cliente vs. registro
console.log en el código de la aplicaciónLas líneas no estructuradas rompen las tuberías de registro solo JSON.
// eslint no-console: error
import pino from "pino";
const log = pino();
log.info({ event: "worker_started" });console.log omite los filtros de nivel y la redacción.no-console en src/ con excepción para scripts CLI.pino.destination({ sync: true }) para la captura.Relacionado: Registro con Pino en Fastify - integración de framework
El método, la ruta, el estado y la duración impulsan los paneles de SLO.
logger.info({
event: "request_complete",
method: "GET",
path: "/users",
statusCode: 200,
durationMs: 42,
requestId: "req_abc",
});requestId, no reqId en una aplicación y rid en otra).reply.elapsedTime (Fastify) o temporización de middleware (Express).Relacionado: IDs de correlación de solicitud -
x-request-id
Crea en el ámbito del módulo; evita pino() por solicitud.
// src/logger.ts
import pino from "pino";
export const logger = pino({
level: process.env.LOG_LEVEL ?? "info",
base: { service: "orders-api", version: process.env.APP_VERSION },
});base aparecen en cada línea - nombre del servicio para índices de registro multi-inquilino.logger a los workers a través de importación, no mutación global.Relacionado: pino - opciones de configuración
Vincula requestId una vez; todos los registros posteriores lo heredan.
const child = logger.child({ requestId: "req_abc", tenantId: "t_1" });
child.info({ action: "fetch_order" });
child.info({ action: "send_receipt" });
// ambas líneas incluyen requestId y tenantIdonRequest de Fastify.req.log = req.log.child({ userId: user.id }).Relacionado: AsyncLocalStorage para el contexto - workers no HTTP
Mantén las contraseñas y los tokens fuera del almacenamiento de registros.
const logger = pino({
redact: {
paths: ["req.headers.authorization", "req.body.password", "email"],
censor: "[REDACTED]",
},
});Relacionado: Redacción de PII y cumplimiento - políticas de retención
Versiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS activa), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.
Revisado por Chris St. John·Última actualización: 16 jul 2026