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

@jamx-framework/metrics

v1.0.0

Published

JAMX Framework — Performance metrics

Readme

@jamx-framework/metrics

Descripción

Módulo de métricas y monitoreo de salud para JAMX Framework. Proporciona una API para recolectar, agregar y exponer métricas de aplicación (latencia, throughput, errores, uso de recursos) y health checks. Soporta múltiples backends de almacenamiento (Prometheus, StatsD, CloudWatch) y puede exponer endpoints HTTP para scrapers de métricas.

Cómo funciona

El módulo implementa un sistema de observabilidad:

  1. Metrics: Clase principal que registra contadores, gauges, histogramas y timers
  2. Health: Sistema de health checks que evalúa el estado de dependencias (DB, cache, colas)
  3. Middleware: Middleware HTTP que automáticamente registra métricas de requests
  4. Exporters: Exportadores a formatos estándar (Prometheus, OpenTelemetry)

Componentes principales

  • src/metrics.ts: Clase Metrics que gestiona contadores, gauges, histogramas
  • src/health.ts: Clase Health que ejecuta y agrupa health checks
  • src/middleware.ts: Middleware HTTP para registrar métricas de requests
  • src/types.ts: Tipos compartidos (Metric, HealthCheck, etc.)
  • src/index.ts: Punto de exportación

Uso básico

import { Metrics, Health } from '@jamx-framework/metrics';

// Crear instancia
const metrics = new Metrics();
const health = new Health();

// Registrar contador
const requestsCounter = metrics.counter('http_requests_total', {
  help: 'Total HTTP requests',
  labels: ['method', 'path', 'status'],
});

// Incrementar contador
requestsCounter.increment({ method: 'GET', path: '/api/users', status: 200 });

// Registrar gauge (valor que sube/baja)
const activeConnections = metrics.gauge('active_connections', {
  help: 'Current active connections',
});
activeConnections.set(42);

// Registrar timer (latencia)
const requestDuration = metrics.histogram('http_request_duration_seconds', {
  help: 'HTTP request duration',
  buckets: [0.1, 0.5, 1, 2, 5],
});
requestDuration.observe(0.234);

// Health checks
health.register('database', async () => {
  const ok = await db.ping();
  return { status: ok ? 'healthy' : 'unhealthy', details: { latency: '10ms' } };
});

health.register('redis', async () => {
  const ok = await cache.ping();
  return { status: ok ? 'healthy' : 'unhealthy' };
});

// Ejecutar todos los health checks
const result = await health.checkAll();
console.log('Estado general:', result.status); // 'healthy' | 'degraded' | 'unhealthy'

Ejemplos

Middleware HTTP automático

import { MetricsMiddleware } from '@jamx-framework/metrics';
import { Server } from '@jamx-framework/server';

const server = new Server();

// Añadir middleware de métricas
server.use(MetricsMiddleware(metrics, {
  // Configuración opcional
  durationMetric: 'http_request_duration_seconds',
  countMetric: 'http_requests_total',
  labels: {
    method: true,   // incluir método HTTP
    path: true,     // incluir path (cuidado con cardinalidad alta)
    status: true,   // incluir código de estado
    userAgent: false, // no incluir user-agent
  },
}));

// Las métricas se registran automáticamente en cada request

Exportar a Prometheus

import { Metrics } from '@jamx-framework/metrics';
import * as promClient from 'prom-client';

const metrics = new Metrics();

// Registrar métricas personalizadas
metrics.counter('custom_requests', { labels: ['endpoint'] });
metrics.gauge('queue_size', { labels: ['queue'] });

// Exponer endpoint /metrics
server.get('/metrics', async (req, res) => {
  const registry = promClient.register;
  
  // Convertir métricas JAMX a formato Prometheus
  for (const metric of metrics.getAll()) {
    // Lógica de conversión...
  }
  
  res.text(await registry.metrics());
});

Health checks compuestos

import { Health } from '@jamx-framework/metrics';

const health = new Health();

// Check de base de datos
health.register('database', {
  check: async () => {
    try {
      await db.ping();
      return { status: 'healthy', details: { version: db.version } };
    } catch (error) {
      return { status: 'unhealthy', details: { error: error.message } };
    }
  },
  timeout: 5000, // 5 segundos timeout
  dependencies: ['redis'], // depende de que redis esté healthy
});

// Check de Redis
health.register('redis', {
  check: async () => {
    const pong = await cache.ping();
    return { status: pong === 'PONG' ? 'healthy' : 'unhealthy' };
  },
});

// Check de disco
health.register('disk', {
  check: async () => {
    const stats = await fs.statvfs('/');
    const freePercent = (stats.f_bavail / stats.f_blocks) * 100;
    return {
      status: freePercent > 10 ? 'healthy' : 'unhealthy',
      details: { freePercent },
    };
  },
});

// Endpoint de health
server.get('/health', async (req, res) => {
  const result = await health.checkAll();
  const status = result.status === 'healthy' ? 200 : 503;
  res.json(result, status);
});

Timers y contextos

import { Metrics } from '@jamx-framework/metrics';

const metrics = new Metrics();
const timer = metrics.timer('function_execution_seconds', {
  labels: ['function_name'],
});

async function processOrder(orderId: string) {
  const stop = timer.start({ function_name: 'processOrder' });
  
  try {
    // Lógica de procesamiento
    await orderService.process(orderId);
    stop(); // Registrar duración
  } catch (error) {
    stop(); // Registrar duración incluso en error
    throw error;
  }
}

Métricas personalizadas con etiquetas

const ordersCreated = metrics.counter('orders_created_total', {
  labels: ['payment_method', 'country'],
});

// Incrementar con etiquetas específicas
ordersCreated.increment({
  payment_method: 'credit_card',
  country: 'US',
});

// Consultar métrica actual
const current = ordersCreated.getValue({
  payment_method: 'credit_card',
  country: 'US',
});
console.log('Órdenes con tarjeta en US:', current);

Uso con inyección de dependencias

import { Container } from '@jamx-framework/core';
import { Metrics, Health } from '@jamx-framework/metrics';

// Registrar en contenedor
Container.registerSingleton('metrics', () => new Metrics());
Container.registerSingleton('health', () => new Health());

// Resolver y usar
const metrics = Container.resolve<Metrics>('metrics');
const health = Container.resolve<Health>('health');

// Registrar métrica
const apiCalls = metrics.counter('api_calls_total');
apiCalls.increment();

// Verificar salud
const status = await health.check('database');

Flujo interno

  1. Inicialización: Se crean instancias de Metrics y Health
  2. Registro: Se registran contadores, gauges, histogramas con nombres y etiquetas
  3. Recolección: Durante la ejecución, se invoca .increment(), .set(), .observe()
  4. Agregación: Las métricas se agregan por etiquetas en memoria
  5. Exportación: Se pueden exportar a Prometheus, StatsD, CloudWatch, etc.
  6. Health checks: Se ejecutan checks registrados (DB, cache, disco) y se agrupan resultados
  7. Middleware: El middleware HTTP automáticamente registra duración y conteo de requests

API Reference (Resumen)

Metrics

  • counter(name, options): Crea un contador (solo incrementa)
  • gauge(name, options): Crea un gauge (setea valor)
  • histogram(name, options): Crea un histograma (distribución de valores)
  • timer(name, options): Crea un timer (mide duración)
  • getAll(): Metric[]: Obtiene todas las métricas registradas
  • reset(): Limpia todas las métricas

Health

  • register(name, check): Registra un health check
  • check(name?): Ejecuta check específico o todos
  • checkAll(): Promise<HealthResult>: Ejecuta todos y agrupa
  • getStatus(): 'healthy' | 'degraded' | 'unhealthy'

Metric (interface)

  • name: string
  • type: 'counter' | 'gauge' | 'histogram' | 'timer'
  • help?: string
  • labels?: string[]
  • value: number | Map<string, number>

HealthCheck (interface)

  • name: string
  • check: () => Promise<HealthStatus>
  • timeout?: number
  • dependencies?: string[]

Performance Considerations

  • In-memory aggregation: Las métricas se agregan en memoria, sin I/O en cada registro
  • Lock-free: Usa estructuras atómicas cuando es posible
  • Sampling: Se puede configurar sampling para alto volumen
  • Batch export: Exportación en batch para reducir overhead
  • Histogram buckets: Elegir buckets apropiados para no gastar memoria

Configuration Options

const metrics = new Metrics({
  // Configuración global
  prefix: 'jamx_',        // prefijo para nombres de métricas
  defaultLabels: { env: 'production' }, // labels por defecto
  sampling: 1.0,          // 1.0 = 100%, 0.1 = 10%
  autoFlush: true,       // flush automático a backend
  flushInterval: 5000,   // ms entre flushes
});

const health = new Health({
  timeout: 10000,        // timeout por defecto para checks
  parallel: true,        // ejecutar checks en paralelo
  cacheDuration: 30000,  // cachear resultados por 30s
});

Testing

Tests en packages/metrics/tests/unit/:

pnpm test

Cubre:

  • Creación de contadores, gauges, histogramas
  • Incrementos y observaciones
  • Health checks simples y compuestos
  • Middleware HTTP
  • Exportación a formatos

Compatibility

  • Compatible con Node.js 18+
  • Exporta a Prometheus text format
  • Integra con OpenTelemetry (opcional)
  • Funciona en Windows, macOS, Linux

CLI Integration

  • jamx metrics:export <format>: Exporta métricas a formato específico
  • jamx health:check: Ejecuta health checks y muestra resultado
  • jamx metrics:reset: Limpia métricas acumuladas
  • jamx metrics:tail: Muestra métricas en tiempo real (como top)

Best Practices

  1. Usar nombres consistentes: http_requests_total, db_query_duration_seconds
  2. Limitar cardinalidad: Evitar etiquetas con alta cardinalidad (user_id, session_id)
  3. Health checks rápidos: Los checks deben terminar en segundos, no minutos
  4. Dependencias claras: Documentar dependencias entre health checks
  5. Alertas basadas en métricas: Configurar alertas en Prometheus/Grafana
  6. Métricas de negocio: Además de técnicas, registrar métricas de negocio (signups, purchases)
  7. Sampling en producción: Para alto tráfico, usar sampling para reducir overhead

This metrics module provides comprehensive observability for JAMX applications, enabling developers to monitor performance, detect issues, and understand application behavior in production environments.