@regcheq/logger-backend
v1.2.1
Published
Unified logging + Datadog tracing helpers for Regcheq services
Readme
Regcheq Logger Backend
Librería interna para unificar logging + trazas de Datadog en servicios Node (LoopBack, Nest/Express y Lambdas).
Objetivos
- Logs JSON consistentes en stdout (consumidos por el agente de Datadog).
- Correlación automática con trazas (
dd.trace_id,dd.span_id). - Errores con
error.messageyerror.stackvisibles en Error Tracking. - Captura de request (y body con límites) cuando hay errores.
Instalación
npm i @regcheq/logger-backendRequisitos para desarrollo
El proyecto usa Node 22. Con nvm instalado:
nvm use
npm ciEl archivo .nvmrc fija la versión; nvm use cambia al Node correcto automáticamente.
Husky ejecuta antes de cada commit:
- pre-commit:
npm run lintynpm run test(no se permite commit si fallan). - commit-msg: commitlint para que los mensajes sigan Conventional Commits (ej.
feat:,fix:,chore:). Evita commits con mensajes mal formados.
Guía rápida: integrar en tu primera API (NestJS)
1. Instalar la dependencia
En el proyecto de tu API:
npm i @regcheq/logger-backend2. Inicializar tracing antes de todo (main.ts)
initTracing() debe ser lo primero que se ejecute, antes de crear la app Nest o cargar Express:
// src/main.ts
import { NestFactory } from '@nestjs/core';
import { initTracing, createLogger, httpMiddleware, errorMiddleware, NestPinoLogger, DatadogExceptionFilter } from '@regcheq/logger-backend';
import { HttpAdapterHost } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
initTracing(); // ← Primero
const logger = createLogger();
const app = await NestFactory.create(AppModule, { bufferLogs: true });
app.useLogger(new NestPinoLogger(logger));
app.use(httpMiddleware({ logger }));
app.use(errorMiddleware({ logger }));
const httpAdapterHost = app.get(HttpAdapterHost);
app.useGlobalFilters(new DatadogExceptionFilter(logger, { captureBody: 'errors' }, httpAdapterHost));
await app.listen(3000);
}
bootstrap();3. Variables de entorno
Copia las variables necesarias (por ejemplo desde .env.example de esta librería o define en tu API):
LOG_LEVEL=info
DD_ENV=dev
DD_SERVICE=mi-api
DD_VERSION=1.0.0
DD_LOGS_INJECTION=trueEn local, si no tienes agente Datadog, los logs seguirán saliendo por consola en JSON.
4. Usar el logger en tus servicios (opcional)
Si quieres loggear desde un servicio usando el mismo logger con trazas:
import { createLogger } from '@regcheq/logger-backend';
const logger = createLogger();
export class MiServicio {
hacerAlgo() {
logger.info({ userId: '123' }, 'Operación ejecutada');
}
}O inyecta el logger que pasaste a NestPinoLogger (por ejemplo con un módulo que provea Logger de Nest y lo reenvíe a Pino).
5. Resumen de pasos
| Paso | Acción |
|------|--------|
| 1 | npm i @regcheq/logger-backend |
| 2 | En main.ts: llamar initTracing() al inicio. |
| 3 | Crear logger con createLogger() y usarlo en httpMiddleware, errorMiddleware, NestPinoLogger y DatadogExceptionFilter. |
| 4 | Definir DD_SERVICE, DD_ENV, LOG_LEVEL (y opcionalmente DD_VERSION) en tu entorno. |
| 5 | Arrancar la API; los requests y errores se loguean en JSON con correlación de trazas. |
Uso básico (Node/Express)
import { initTracing, createLogger, httpMiddleware, errorMiddleware } from '@regcheq/logger-backend';
initTracing();
const logger = createLogger();
app.use(httpMiddleware({ logger }));
app.use(errorMiddleware({ logger }));Nota: initTracing() debe ejecutarse antes de cargar frameworks (Express, Nest, LoopBack) para que el auto-instrumentado funcione.
LoopBack
import { initTracing, createLogger, createLoopbackMiddleware } from '@regcheq/logger-backend';
initTracing();
const logger = createLogger();
// en tu app.use(...)
app.middleware(createLoopbackMiddleware({ logger }));Nest (Express)
Nest usa Express por defecto, así que puedes reutilizar los middlewares:
import { initTracing, createLogger, httpMiddleware, errorMiddleware } from '@regcheq/logger-backend';
initTracing();
const logger = createLogger();
app.use(httpMiddleware({ logger }));
app.use(errorMiddleware({ logger }));Opcional: adapters para Nest (LoggerService + ExceptionFilter):
import { initTracing, createLogger, NestPinoLogger, DatadogExceptionFilter } from '@regcheq/logger-backend';
import { HttpAdapterHost } from '@nestjs/core';
initTracing();
const logger = createLogger();
app.useLogger(new NestPinoLogger(logger));
const httpAdapterHost = app.get(HttpAdapterHost);
app.useGlobalFilters(new DatadogExceptionFilter(logger, { captureBody: 'errors' }, httpAdapterHost));Lambda
import { initTracing, createLogger, wrapLambda } from '@regcheq/logger-backend';
initTracing();
const logger = createLogger();
export const handler = wrapLambda(async (event) => {
// ...
}, { logger, captureBody: false });Opciones útiles
const logger = createLogger({
level: 'info',
service: process.env.DD_SERVICE,
env: process.env.DD_ENV,
version: process.env.DD_VERSION,
redact: ['req.headers.authorization', 'req.body.password']
});
app.use(httpMiddleware({
logger,
captureBody: 'errors', // none | errors | all
bodyMaxBytes: 2048,
includeHeaders: ['x-request-id', 'user-agent']
}));Versioning (SemVer)
Este paquete sigue SemVer:
PATCH: fixes internos sin cambios de API.MINOR: nuevas funcionalidades compatibles.MAJOR: cambios que rompen compatibilidad.
Commits (Conventional Commits)
El release automático usa Conventional Commits. Ejemplos:
feat: agrega middleware de auth→ MINORfix: corrige log de errores→ PATCHfeat!: cambia API→ MAJOR
O con breaking change explícito:
feat: agrega autenticacion
BREAKING CHANGE: cambia nombre de export en indexTipos comunes: feat, fix, chore, docs, refactor, test.
Guía de despliegue (k8s)
Requisitos mínimos:
- Datadog Agent (DaemonSet) con logs y tracing habilitados.
- Los logs deben ir a
stdout/stderr. - Variables de entorno (ver
.env.example).
Notas:
initTracing()debe ejecutarse antes de cargar Express/Nest/LoopBack.- En k8s recomendamos mantener
DD_LOGS_INJECTION=true. - Si usas el admission controller de Datadog, puedes pinnear versión de la lib con
admission.datadoghq.com/js-lib.version.
Si falla la conexión al Agent (ECONNREFUSED en 8126)
En muchos clusters el Datadog Agent (DaemonSet con hostNetwork: true) solo escucha en localhost y no en la IP del nodo. Si tu app usa DD_AGENT_HOST=status.hostIP, verás en logs:
Error: connect ECONNREFUSED 10.x.x.x:8126Solución: usar el socket Unix que el Agent expone (/var/run/datadog/apm.socket). No hace falta cambiar código: dd-trace (usado por esta librería) lee la variable DD_TRACE_AGENT_URL automáticamente.
En el Deployment de tu API (el YAML de Kubernetes):
Variable de entorno en el contenedor:
- name: DD_TRACE_AGENT_URL value: "unix:///var/run/datadog/apm.socket"Volume en
spec.template.spec(mismo nivel quecontainers):volumes: - name: datadog-socket hostPath: path: /var/run/datadog type: DirectoryOrCreateVolumeMount en el contenedor:
volumeMounts: - name: datadog-socket mountPath: /var/run/datadog
Puedes mantener el resto de env (DD_ENV, DD_SERVICE, DD_VERSION, DD_LOGS_INJECTION, etc.). Con esto el tracer usa el socket y deja de intentar TCP al puerto 8126.
Guía de despliegue (Lambda + Serverless)
Requisitos mínimos:
- Extensión/Layer de Datadog para Lambda o forwarder.
- Variables de entorno (ver
.env.example).
Notas:
- En Serverless, habilita el plugin de Datadog para inyectar extensión y trazas.
- Usa
wrapLambda()para asegurar logs de request y error con body (solo 4xx/5xx).
Nota sobre errores en Datadog
Para que el panel de errores no muestre “Missing error message and stack trace”:
- Siempre lanzar objetos
Error(no strings ni objetos planos). - Loggear errores como objeto
error(no en unmessagestring). - Usar
captureError(err)o elerrorMiddleware, que etiqueta el span activo.
Si solo se registran errores y no las respuestas 200
La librería ya registra requests y responses (incluidos 200) con httpMiddleware. Si en tu API solo ves logs de errores:
- Orden de middlewares:
httpMiddlewareyerrorMiddlewaredeben ir antes de las rutas (primerosapp.use(...)enmain.ts). - Ambos middlewares: hace falta tanto
app.use(httpMiddleware({ logger }))(para request + response) comoapp.use(errorMiddleware({ logger }))(para errores con detalle). - Opciones por defecto:
logRequestsylogResponsessontrue; no los pongas enfalsesi quieres ver los 200.
