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

@merncloud/nodejs-monitoring

v1.0.0

Published

A comprehensive monitoring service for Node.js applications with built-in health probes and metrics collection

Readme

Node.js Monitoring Service

A comprehensive monitoring service for Node.js applications with built-in health probes, metrics collection, and real-time monitoring capabilities. Similar to New Relic but lightweight and easy to integrate.

Features

  • 🚀 Easy Integration - One-line setup for Express applications
  • 📊 Built-in Metrics - Memory, CPU, uptime, request tracking
  • 🔍 Health Probes - Customizable health checks with thresholds
  • 📈 Real-time Monitoring - Live metrics collection and history
  • Performance Tracking - Request/response time monitoring
  • 🛡️ Error Monitoring - Automatic error tracking and alerting
  • 🎯 Custom Probes - Add your own health checks
  • 📱 REST API - Built-in endpoints for health and metrics

Installation

npm install @merncloud/nodejs-monitoring

Quick Start

Basic Setup

import express from "express";
import { setupMonitoring } from "@merncloud/nodejs-monitoring";

const app = express();

// Setup monitoring with one line
const monitoring = setupMonitoring(app);

// Your routes
app.get("/api/users", (req, res) => {
  res.json({ users: [] });
});

app.listen(3000, () => {
  console.log("Server running on port 3000");
  console.log("Health check: http://localhost:3000/health");
});

Advanced Configuration

import express from "express";
import {
  setupMonitoring,
  MonitoringService,
} from "@merncloud/nodejs-monitoring";

const app = express();

// Advanced configuration
const monitoring = setupMonitoring(app, {
  healthRoutePath: "/api/health",
  metricsInterval: 15000, // Collect metrics every 15 seconds
  enableRequestTracking: true,
  enableErrorTracking: true,
  alertThresholds: {
    memoryUsage: 85, // Alert when memory > 85%
    cpuUsage: 90, // Alert when CPU > 90%
    responseTime: 2000, // Alert when response time > 2s
    errorRate: 5, // Alert when error rate > 5/min
  },
});

// Add custom health probe
monitoring.addProbe({
  name: "database_connection",
  check: async () => {
    try {
      await database.ping();
      return {
        status: "healthy",
        message: "Database connection successful",
      };
    } catch (error) {
      return {
        status: "critical",
        message: `Database connection failed: ${error.message}`,
      };
    }
  },
  interval: 30000, // Check every 30 seconds
});

// Add Redis health check
monitoring.addProbe({
  name: "redis_connection",
  check: async () => {
    try {
      const result = await redisClient.ping();
      return {
        status: "healthy",
        message: "Redis is responding",
        value: result === "PONG" ? 1 : 0,
      };
    } catch (error) {
      return {
        status: "critical",
        message: `Redis connection failed: ${error.message}`,
      };
    }
  },
});

app.listen(3000);

API Endpoints

Once integrated, your application will have the following endpoints:

Health Check

GET /health

Returns comprehensive health information:

{
  "status": "healthy",
  "timestamp": 1640995200000,
  "uptime": 3600,
  "metrics": {
    "timestamp": 1640995200000,
    "uptime": 3600,
    "memory": {
      "used": 45,
      "total": 1024,
      "percentage": 4,
      "heap": {
        "used": 25,
        "total": 30,
        "percentage": 83
      }
    },
    "cpu": {
      "usage": 15.5,
      "loadAverage": [0.5, 0.3, 0.2]
    },
    "process": {
      "pid": 12345,
      "version": "v18.17.0",
      "platform": "linux",
      "arch": "x64"
    },
    "requests": {
      "total": 150,
      "active": 2,
      "averageResponseTime": 120
    },
    "errors": {
      "total": 5,
      "rate": 0.2
    }
  },
  "probes": {
    "memory_usage": {
      "status": "healthy",
      "message": "Memory usage is 4%",
      "value": 4
    },
    "cpu_usage": {
      "status": "healthy",
      "message": "CPU usage is 15.5%",
      "value": 15.5
    },
    "database_connection": {
      "status": "healthy",
      "message": "Database connection successful"
    }
  },
  "version": "1.0.0"
}

Metrics History

GET /health/metrics?limit=50

Returns historical metrics data:

{
  "metrics": [...],
  "count": 50,
  "latest": { ... }
}

Custom Probes

Create custom health checks for your specific needs:

import { CustomProbe, ProbeResult } from "@merncloud/nodejs-monitoring";

// Simple probe
const customProbe: CustomProbe = {
  name: "external_api_check",
  check: async (): Promise<ProbeResult> => {
    try {
      const response = await fetch("https://api.example.com/health");
      const isHealthy = response.ok;

      return {
        status: isHealthy ? "healthy" : "critical",
        message: `External API responded with ${response.status}`,
        value: response.status,
        metadata: {
          responseTime: Date.now() - startTime,
          url: "https://api.example.com/health",
        },
      };
    } catch (error) {
      return {
        status: "critical",
        message: `External API unreachable: ${error.message}`,
      };
    }
  },
  interval: 60000, // Check every minute
};

// Add the probe
monitoring.addProbe(customProbe);

// Complex probe with multiple checks
const complexProbe: CustomProbe = {
  name: "service_dependencies",
  check: async (): Promise<ProbeResult> => {
    const checks = await Promise.allSettled([
      checkDatabase(),
      checkRedis(),
      checkMessageQueue(),
      checkExternalAPI(),
    ]);

    const failed = checks.filter((c) => c.status === "rejected").length;
    const total = checks.length;

    if (failed === 0) {
      return {
        status: "healthy",
        message: `All ${total} dependencies are operational`,
        metadata: { passed: total, failed: 0 },
      };
    } else if (failed <= total / 2) {
      return {
        status: "warning",
        message: `${failed}/${total} dependencies failed`,
        metadata: { passed: total - failed, failed },
      };
    } else {
      return {
        status: "critical",
        message: `${failed}/${total} dependencies failed`,
        metadata: { passed: total - failed, failed },
      };
    }
  },
};

Built-in Probes

The service comes with several built-in probes:

Memory Usage Probe

  • Monitors system and heap memory usage
  • Configurable threshold (default: 80%)
  • Status: healthy → warning → critical

CPU Usage Probe

  • Monitors CPU usage percentage
  • Configurable threshold (default: 80%)
  • Includes load average information

Uptime Probe

  • Tracks application uptime
  • Always returns healthy status
  • Useful for monitoring application restarts

Disk Space Probe

  • Basic disk accessibility check
  • Monitors current working directory access

Configuration Options

interface MonitoringConfig {
  enableHealthRoute?: boolean; // Enable /health endpoint (default: true)
  healthRoutePath?: string; // Health route path (default: '/health')
  enableMetricsCollection?: boolean; // Enable metrics collection (default: true)
  metricsInterval?: number; // Metrics collection interval (default: 30000ms)
  enableRequestTracking?: boolean; // Track HTTP requests (default: true)
  enableErrorTracking?: boolean; // Track HTTP errors (default: true)
  customProbes?: CustomProbe[]; // Additional custom probes
  alertThresholds?: AlertThresholds; // Custom alert thresholds
}

interface AlertThresholds {
  memoryUsage?: number; // Memory usage threshold percentage
  cpuUsage?: number; // CPU usage threshold percentage
  responseTime?: number; // Response time threshold in ms
  errorRate?: number; // Error rate threshold per minute
}

Manual Usage (Without Express)

You can also use the monitoring service manually without Express:

import { MonitoringService } from "@merncloud/nodejs-monitoring";

// Initialize monitoring service
const monitoring = MonitoringService.getInstance({
  enableHealthRoute: false, // We'll handle routes manually
  metricsInterval: 15000,
});

// Get current metrics
const metrics = monitoring.getCurrentMetrics();
console.log("Current metrics:", metrics);

// Get probe results
const probes = monitoring.getProbeResults();
console.log("Probe results:", probes);

// Add custom probe
monitoring.addProbe({
  name: "custom_check",
  check: async () => {
    // Your custom logic here
    return { status: "healthy", message: "All good!" };
  },
});

Integration Examples

Express.js with TypeScript

import express from "express";
import { setupMonitoring } from "@merncloud/nodejs-monitoring";

const app = express();

// Setup monitoring
const monitoring = setupMonitoring(app, {
  healthRoutePath: "/api/health",
  alertThresholds: {
    memoryUsage: 85,
    cpuUsage: 90,
  },
});

// Add database probe
monitoring.addProbe({
  name: "postgres_connection",
  check: async () => {
    try {
      const client = await pool.connect();
      await client.query("SELECT NOW()");
      client.release();
      return { status: "healthy", message: "PostgreSQL connected" };
    } catch (error) {
      return {
        status: "critical",
        message: `PostgreSQL error: ${error.message}`,
      };
    }
  },
});

export default app;

NestJS Integration

import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { setupMonitoring } from "@merncloud/nodejs-monitoring";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Setup monitoring
  const monitoring = setupMonitoring(app.getHttpAdapter().getInstance(), {
    healthRoutePath: "/health",
    metricsInterval: 20000,
  });

  // Add custom probe for NestJS app
  monitoring.addProbe({
    name: "nestjs_modules",
    check: async () => {
      try {
        const moduleRef = app.get(AppModule);
        return {
          status: "healthy",
          message: "NestJS modules loaded successfully",
          metadata: { moduleRef: !!moduleRef },
        };
      } catch (error) {
        return { status: "critical", message: "NestJS module error" };
      }
    },
  });

  await app.listen(3000);
}

bootstrap();

Koa.js Integration

import Koa from "koa";
import { MonitoringService } from "@merncloud/nodejs-monitoring";

const app = new Koa();

// Initialize monitoring
const monitoring = MonitoringService.getInstance({
  enableHealthRoute: false, // We'll add routes manually
});

// Add request tracking middleware
app.use(async (ctx, next) => {
  const startTime = Date.now();
  const requestId = monitoring.requestTracker.startRequest();

  try {
    await next();
    monitoring.requestTracker.endRequest(requestId, startTime);
  } catch (error) {
    monitoring.requestTracker.recordError();
    throw error;
  }
});

// Add health route
app.use(async (ctx, next) => {
  if (ctx.path === "/health") {
    const metrics = monitoring.getCurrentMetrics();
    const probes = monitoring.getProbeResults();

    ctx.body = {
      status: "healthy",
      timestamp: Date.now(),
      metrics,
      probes,
    };
  } else {
    await next();
  }
});

app.listen(3000);

Monitoring Dashboard

The service provides JSON endpoints that can be consumed by monitoring dashboards:

Grafana Integration

Use the /health/metrics endpoint to create time-series graphs in Grafana.

Custom Dashboard

Create a simple monitoring dashboard:

<!DOCTYPE html>
<html>
  <head>
    <title>App Monitoring Dashboard</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  </head>
  <body>
    <div>
      <canvas id="memoryChart"></canvas>
      <canvas id="cpuChart"></canvas>
    </div>

    <script>
      async function updateCharts() {
        try {
          const response = await fetch("/health/metrics?limit=20");
          const data = await response.json();

          // Update charts with metrics data
          updateMemoryChart(data.metrics);
          updateCpuChart(data.metrics);
        } catch (error) {
          console.error("Failed to fetch metrics:", error);
        }
      }

      // Update every 30 seconds
      setInterval(updateCharts, 30000);
      updateCharts(); // Initial load
    </script>
  </body>
</html>

Production Considerations

Security

  • Consider adding authentication to health endpoints in production
  • Limit access to sensitive metrics data
  • Use HTTPS for metrics transmission

Performance

  • Adjust metricsInterval based on your needs (longer intervals = less overhead)
  • Be cautious with custom probe intervals
  • Monitor the monitoring service's own resource usage

Alerting

  • Integrate with external alerting systems (PagerDuty, Slack, etc.)
  • Set up automated responses to critical alerts
  • Consider implementing circuit breakers based on health status

Example Production Setup

import { setupMonitoring } from "@merncloud/nodejs-monitoring";

const monitoring = setupMonitoring(app, {
  healthRoutePath: process.env.HEALTH_ENDPOINT || "/internal/health",
  metricsInterval: parseInt(process.env.METRICS_INTERVAL) || 60000,
  alertThresholds: {
    memoryUsage: parseInt(process.env.MEMORY_THRESHOLD) || 90,
    cpuUsage: parseInt(process.env.CPU_THRESHOLD) || 95,
    responseTime: parseInt(process.env.RESPONSE_TIME_THRESHOLD) || 5000,
    errorRate: parseInt(process.env.ERROR_RATE_THRESHOLD) || 10,
  },
});

// Add environment-specific probes
if (process.env.DATABASE_URL) {
  monitoring.addProbe({
    name: "database_connection",
    check: async () => {
      // Database check implementation
    },
  });
}

Testing

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run with coverage
npm test -- --coverage

API Reference

MonitoringService

Methods

  • getInstance(config?: MonitoringConfig): MonitoringService - Get singleton instance
  • addProbe(probe: CustomProbe): void - Add custom health probe
  • getCurrentMetrics(): HealthMetrics - Get current system metrics
  • getProbeResults(): Record<string, ProbeResult> - Get all probe results
  • requestTrackingMiddleware() - Express middleware for request tracking
  • healthCheckHandler() - Express route handler for health endpoint
  • metricsHistoryHandler() - Express route handler for metrics history

Helper Functions

  • setupMonitoring(app, config?) - Quick setup for Express applications

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Run the test suite
  6. Submit a pull request

License

MIT License - see LICENSE file for details.

Support