De console.log a logs estructurados
En desarrollo console.log("usuario logueado", id) es cómodo. En producción
los logs los lee una máquina (un agregador como Datadog, Loki o CloudWatch),
no una persona mirando la terminal. Por eso los logs deben ser estructurados:
cada línea es un objeto JSON con campos consistentes.
// Mal: texto libre, imposible de filtrar o agregar.
console.log("Error al guardar el pedido 42 del usuario 7");
// Bien: JSON con campos. Se puede filtrar por nivel, buscar por usuarioId...
console.log(JSON.stringify({
nivel: "error",
mensaje: "Error al guardar el pedido",
pedidoId: 42,
usuarioId: 7,
ts: "2026-06-22T10:00:00Z",
}));
Niveles de log
Cada entrada lleva un nivel de severidad, para poder filtrar:
info: eventos normales ("servidor arrancado", "petición recibida").warn: algo inesperado pero recuperable ("reintentando conexión").error: un fallo que requiere atención (excepción, petición fallida).
En producción se suele bajar el "ruido" mostrando solo warn y error, mientras
que en desarrollo se ve todo. Librerías como pino o winston dan esto hecho.
function crearLog(nivel, mensaje) {
return { nivel, mensaje, ts: new Date().toISOString() };
}
Métricas
Los logs cuentan qué pasó; las métricas miden cuánto y cómo de rápido: peticiones por segundo, latencia (p95, p99), uso de memoria y CPU, tasa de errores. Se exponen (p. ej. en formato Prometheus) y se grafican en paneles (Grafana) con alertas cuando algo se sale de rango.
Health checks
Un health check es un endpoint sencillo, normalmente GET /health, que
responde 200 y un cuerpo como { status: "ok" } si el servicio está vivo.
No lo llama un humano: lo consultan el balanceador de carga, el orquestador
(Kubernetes) o el process manager para decidir si la instancia debe recibir
tráfico o ser reiniciada.
function health(req, res) {
res.status(200).json({ status: "ok" });
}
A veces se distingue liveness (¿el proceso está vivo?) de readiness (¿está listo para recibir tráfico, p. ej. con la BD conectada?).
Trazabilidad
Cuando una petición atraviesa varios servicios, se le asocia un identificador de correlación (request id / trace id) que se propaga y se incluye en todos los logs de esa petición. Así puedes reconstruir el recorrido completo de una sola petición a través de todo el sistema. Es la base del distributed tracing (OpenTelemetry).
Ejemplos
Logger estructurado con niveles, emitido como JSON
function crearLog(nivel, mensaje, extra) {
return Object.assign({ nivel, mensaje, ts: new Date().toISOString() }, extra || {});
}
console.log(JSON.stringify(crearLog("info", "Servidor arrancado", { puerto: 3000 })));
console.log(JSON.stringify(crearLog("error", "Conexión perdida")));