npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@itcoordinadora/fastify-request-logs

v2.0.1

Published

Una librería de logging para aplicaciones Fastify que registra automáticamente todas las peticiones HTTP de manera estructurada, con soporte opcional para Google Cloud Logging.

Readme

fastify-request-logs

Una librería de logging para aplicaciones Fastify que registra automáticamente todas las peticiones HTTP de manera estructurada, con soporte opcional para Google Cloud Logging.

🆕 Nuevo en v2.0.0: Uso Standalone

Ahora puedes usar la librería sin Fastify para casos como:

  • Procesamiento de mensajes de colas (PubSub, SQS, etc.)
  • Scripts de procesamiento por lotes
  • Trabajos cron
  • Cualquier aplicación que no sea un servidor HTTP

Uso Standalone

import { LoggerInstance, printLog, printError, runWithLoggerAsync } from '@itcoordinadora/fastify-request-logs';

const procesarMensaje = async (mensaje) => {
  const logger = new LoggerInstance(
    {
      url: `/pubsub/proceso/${mensaje.id}`,
      method: 'MENSAJE',
      body: mensaje.data?.toString(),
      params: { idMensaje: mensaje.id }
    },
    {
      only_errors: false,
      domain: 'procesador-mensajes',
      service: 'mi-servicio',
      colors: true
    }
  );

  try {
    await runWithLoggerAsync(logger, async () => {
      printLog('mensaje-recibido', mensaje.id);
      
      // Tu lógica de procesamiento aquí
      const datos = JSON.parse(mensaje.data.toString());
      await procesarDatos(datos);
      
      printLog('procesamiento-exitoso', true);
    });

    mensaje.ack(); // Confirmar mensaje
    logger.finish({ exitoso: true }, false, 200);

  } catch (error) {
    printError('error-procesamiento', error.message);
    
    if (esErrorRecuperable(error)) {
      mensaje.nack(); // Reintentar
    } else {
      mensaje.ack();  // Descartar mensaje inválido
    }
    
    logger.finish({ exitoso: false, error: error.message }, true, 500);
  }
};

// Funciones auxiliares pueden usar printLog sin parámetros
async function procesarDatos(datos) {
  printLog('procesando-datos', datos.length);
  
  for (const item of datos) {
    printLog('procesando-item', item.id);
    // ... tu lógica aquí
  }
  
  printLog('datos-procesados', true);
}

Instalación

npm install @itcoordinadora/fastify-request-logs

Uso básico

import fastify from 'fastify';
import { logger } from '@itcoordinadora/fastify-request-logs';

const app = fastify();

// Implementar el logger directamente
logger(app, {
  only_errors: false,
  domain: 'mi-api',
  service: 'usuarios',
  colors: true
});

app.get('/test', async (request, reply) => {
  // El logger está disponible automáticamente en cada request
  request.logger.add('custom-log', 'Este es un log personalizado');
  
  return { message: 'Hello World' };
});

Configuración

Opciones disponibles

interface LoggerOptions {
  only_errors: boolean;           // Solo registrar errores
  domain: string;                 // Dominio de la aplicación
  service: string;                // Nombre del servicio
  module?: string;                // Módulo específico (opcional)
  colors: boolean;                // Habilitar colores en consola
  useGCloudLogging?: boolean;     // Usar Google Cloud Logging
  gcloudProjectId?: string;       // ID del proyecto de Google Cloud
}

Google Cloud Logging

Configuración básica

Para usar Google Cloud Logging, configura las opciones así:

logger(app, {
  only_errors: false,
  domain: 'mi-api',
  service: 'usuarios',
  colors: true,
  useGCloudLogging: true,
  gcloudProjectId: 'mi-proyecto-gcp'
});

Requisitos previos

  1. Instalar las dependencias de Google Cloud:

    npm install @google-cloud/logging
  2. Configurar las credenciales de Google Cloud:

    Opción A: Variable de entorno (Recomendado para producción)

    export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"

    Opción B: SDK de Google Cloud (Desarrollo local)

    gcloud auth application-default login

    Opción C: Entornos de Google Cloud (Automático)

    • Google Kubernetes Engine (GKE)
    • Cloud Run
    • Compute Engine
    • App Engine
  3. Configurar el proyecto de Google Cloud:

    gcloud config set project YOUR_PROJECT_ID

Verificar configuración

Para verificar que todo está configurado correctamente:

# Verificar credenciales
gcloud auth application-default print-access-token

# Verificar proyecto activo
gcloud config get-value project

Características de Google Cloud Logging

Cuando useGCloudLogging está habilitado:

  • Logs estructurados: Los logs se envían con metadatos estructurados
  • Severidad automática: Se asigna automáticamente INFO o ERROR según el tipo de respuesta
  • Etiquetas: Se incluyen automáticamente las etiquetas de domain, service y module
  • HTTP Request metadata: Se incluye información de la petición HTTP (URL, método, status code)
  • Fallback seguro: Si hay errores con Google Cloud Logging, automáticamente regresa a console.log

Troubleshooting

❌ Error: "gcloudProjectId is required"

// ❌ Incorrecto
logger(app, {
  useGCloudLogging: true  // Falta gcloudProjectId
});

// ✅ Correcto
logger(app, {
  useGCloudLogging: true,
  gcloudProjectId: 'mi-proyecto-gcp'  // Requerido
});

❌ Error: "Error initializing Google Cloud Logging"

Causa común: Credenciales no configuradas

Solución:

# Para desarrollo local
gcloud auth application-default login

# Para producción
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"

❌ Error: "Failed to write to Google Cloud Logging"

Causas posibles:

  1. Permisos insuficientes: El service account necesita el rol roles/logging.logWriter
  2. Proyecto incorrecto: Verificar que el gcloudProjectId sea correcto
  3. API no habilitada: Habilitar Cloud Logging API

Soluciones:

# Habilitar la API de Cloud Logging
gcloud services enable logging.googleapis.com

# Verificar permisos del service account
gcloud projects get-iam-policy YOUR_PROJECT_ID

# Otorgar permisos de logging
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
  --member="serviceAccount:[email protected]" \
  --role="roles/logging.logWriter"

⚠️ Warning: "Google Cloud Logging is enabled but not properly initialized"

Esto indica que useGCloudLogging: true pero la inicialización falló. Revisa los mensajes de error anteriores para identificar la causa.

🔍 Verificar que los logs lleguen a Google Cloud

  1. Ir a Google Cloud ConsoleLoggingLogs Explorer
  2. Filtrar por:
    resource.type="global"
    logName="projects/YOUR_PROJECT_ID/logs/DOMAIN-SERVICE-logs"
  3. Buscar logs recientes de tu aplicación

Ejemplo de log en Google Cloud

{
  "severity": "INFO",
  "httpRequest": {
    "status": 200,
    "requestUrl": "/api/users",
    "requestMethod": "GET"
  },
  "labels": {
    "domain": "mi-api",
    "service": "usuarios",
    "module": "default"
  },
  "jsonPayload": {
    "INFO": {
      "__url": "/api/users",
      "__method": "GET",
      "__params": {},
      "__body": {},
      "domain": "mi-api",
      "service": "usuarios"
    },
    "LOGS": {
      "custom-log": "Este es un log personalizado"
    },
    "RESPONSE": {
      "message": "Hello World",
      "statusCode": 200
    }
  }
}

API de Logging

Logging personalizado

Método tradicional (sigue funcionando)

app.get('/ejemplo', async (request, reply) => {
  // Agregar logs personalizados
  request.logger.add('usuario-id', request.user?.id);
  request.logger.add('accion', 'consulta-datos');
  
  // Registrar errores específicos
  try {
    // ... código que puede fallar
  } catch (error) {
    request.logger.error('database-error', error.message, 'DB_001');
  }
  
  return { success: true };
});

Nuevo método con AsyncLocalStorage (✨ Recomendado)

import { printLog, printError, getRequestLogger } from '@itcoordinadora/fastify-request-logs';

// Funciones auxiliares que pueden hacer logging sin recibir parámetros
async function getUserData(userId) {
  printLog('function-called', 'getUserData');
  printLog('user-id', userId);
  
  if (!userId) {
    printError('validation-error', 'User ID is required', 'USER_001');
    throw new Error('User ID is required');
  }
  
  return { id: userId, name: 'John Doe' };
}

app.get('/ejemplo', async (request, reply) => {
  // ✅ Ahora puedes hacer logging desde cualquier función
  printLog('route-accessed', '/ejemplo');
  
  try {
    const userData = await getUserData(request.params.id);
    printLog('request-success', true);
    
    return userData;
  } catch (error) {
    // Los errores ya se registraron automáticamente
    reply.code(400);
    return { error: error.message, isError: true };
  }
});

Funciones de conveniencia disponibles

import { 
  printLog, 
  printError, 
  getRequestLogger, 
  hasRequestLogger,
  runWithLogger,
  runWithLoggerAsync,
  LoggerInstance,
  RequestContext 
} from '@itcoordinadora/fastify-request-logs';

// Funciones básicas (funcionan en Fastify y standalone)
printLog('key', 'value');                    // Retorna boolean
printError('error-type', 'Error message', 'ERR_001');  // Retorna boolean

// Verificar si hay contexto de logger
if (hasRequestLogger()) {
  printLog('hay-contexto', true);
}

// Obtener el logger completo
const logger = getRequestLogger();
logger.add('custom-log', 'value');

// Para uso standalone
const logger = new LoggerInstance(requestObj, options);
await runWithLoggerAsync(logger, async () => {
  // Tu código aquí puede usar printLog sin parámetros
});

// Acceso directo al contexto
const context = RequestContext.getInstance();

Nuevas exportaciones en v2.0.0

  • hasRequestLogger() - Verifica si hay contexto de logger
  • runWithLogger() - Ejecuta función en contexto (síncrono)
  • runWithLoggerAsync() - Ejecuta función en contexto (asíncrono)
  • LoggerInstance - Clase Logger para uso directo
  • RequestContext - Acceso directo al contexto AsyncLocalStorage

Cambios menores:

  • printLog() ahora retorna boolean (antes void)
  • printError() ahora retorna boolean (antes void)

Estos cambios son compatibles hacia atrás - tu código existente sigue funcionando sin modificaciones.

Soporte para Pub/Sub

La librería detecta automáticamente payloads de Google Cloud Pub/Sub y los decodifica:

// El body se decodifica automáticamente si es un mensaje de Pub/Sub
app.post('/webhook', async (request, reply) => {
  // request.logger capturará automáticamente el mensaje decodificado
  return { received: true };
});

Configuración de desarrollo vs producción

Desarrollo

logger(app, {
  only_errors: false,
  domain: 'dev-api',
  service: 'usuarios',
  colors: true,
  useGCloudLogging: false  // Usar console.log en desarrollo
});

Producción

logger(app, {
  only_errors: false,
  domain: 'prod-api',
  service: 'usuarios',
  colors: false,
  useGCloudLogging: true,
  gcloudProjectId: process.env.GOOGLE_CLOUD_PROJECT_ID
});

AsyncLocalStorage: Logging sin parámetros

Ventajas

Sin pasar parámetros: Puedes hacer logging desde cualquier función sin pasar request.logger
Agrupación automática: Todos los logs de una petición se agrupan automáticamente
Seguro para concurrencia: Compatible con múltiples réplicas y alta carga
Compatibilidad hacia atrás: El método tradicional sigue funcionando
Funciona con async/await: Mantiene el contexto a través de operaciones asíncronas

Cómo funciona

// Antes (incómodo)
async function processData(data, logger) {
  logger.add('processing-data', data);
  
  const result = await database.query(data);
  logger.add('query-result', result);
  
  return result;
}

// Después (elegante)
async function processData(data) {
  printLog('processing-data', data);
  
  const result = await database.query(data);
  printLog('query-result', result);
  
  return result;
}

Requisitos

  • Node.js 12.17.0+ (para AsyncLocalStorage)
  • Funciona en cualquier entorno: On-premise, Google Cloud, AWS, etc.
  • Compatible con clustering: Funciona con múltiples workers

Estructura de logs

Cada log incluye las siguientes secciones:

  • INFO: Información básica de la petición (URL, método, parámetros, body)
  • LOGS: Logs personalizados agregados con request.logger.add() o printLog()
  • RESPONSE: Respuesta exitosa del endpoint
  • ERROR_RESPONSE: Respuesta de error (si aplica)
  • ERRORS: Errores específicos registrados con request.logger.error() o printError()

Licencia

MIT