Monitoring JavaScript Applications: Metrics and Alerts at an Advanced Level

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Advanced Monitoring is a Necessity for Node.js

\n

In modern web development, monitoring has gone beyond simple error logging. For critical Node.js applications — from microservices to high-load APIs — proactive metric collection, intelligent alerts, and data visualization are required. At an advanced level, we are talking not just about "the application is alive," but about its performance, bottlenecks, and failure prediction.

\n

In this article, we will break down how to build a full-fledged monitoring system for a JavaScript (Node.js) application: from collecting custom metrics to setting up alerts via Prometheus and Grafana. You will learn how to use the built-in capabilities of Node.js and modern libraries for proactive service health tracking.

\n\n

1. Collecting Advanced Metrics: From Event Loop to Custom Counters

\n

A basic metric is server response time. An advanced one is Event Loop delay, the number of active handles, and garbage collection frequency. Let's look at how to collect this data using process and the prom-client library (a client for Prometheus).

\n\n

1.1. Event Loop Metrics and System Resources

\n

Node.js is single-threaded, so Event Loop delay is critical. We measure it via process.hrtime() and export it as a histogram.

\n
const client = require('prom-client');\nconst eventLoopDelay = new client.Histogram({\n    name: 'nodejs_event_loop_delay_seconds',\n    help: 'Event Loop delay in seconds',\n    buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1]\n});\n\nfunction measureEventLoop() {\n    const start = process.hrtime.bigint();\n    setImmediate(() => {\n        const duration = Number(process.hrtime.bigint() - start) / 1e9;\n        eventLoopDelay.observe(duration);\n    });\n}\nsetInterval(measureEventLoop, 5000);
\n\n

1.2. Custom Business Logic Metrics

\n

In addition to system metrics, track business indicators: the number of processed orders, validation errors, and execution time of external requests.

\n
const orderCounter = new client.Counter({\n    name: 'app_orders_total',\n    help: 'Total number of processed orders',\n    labelNames: ['status'] // success, failed\n});\n\n// Example usage in a handler\napp.post('/api/order', async (req, res) => {\n    try {\n        await processOrder(req.body);\n        orderCounter.inc({ status: 'success' });\n        res.send('OK');\n    } catch (err) {\n        orderCounter.inc({ status: 'failed' });\n        res.status(500).send('Error');\n    }\n});
\n\n

2. Exporting Metrics and Integration with Prometheus

\n

For Prometheus to collect metrics, you need to create a /metrics endpoint. We use the standard prom-client registry.

\n\n

2.1. Creating an Endpoint for Collection

\n
const express = require('express');\nconst app = express();\nconst client = require('prom-client');\n\n// Collect default Node.js metrics\nclient.collectDefaultMetrics({ timeout: 5000 });\n\napp.get('/metrics', async (req, res) => {\n    res.set('Content-Type', client.register.contentType);\n    res.end(await client.register.metrics());\n});\n\napp.listen(3000, () => console.log('Metrics server on :3000'));
\n\n

2.2. Prometheus Configuration

\n

In the prometheus.yml file, add a target for your application:

\n
scrape_configs:\n  - job_name: 'nodejs-app'\n    static_configs:\n      - targets: ['localhost:3000']
\n

After restarting Prometheus, metrics will be collected every 15 seconds by default.

\n\n

3. Setting Up Alerts: From Simple Thresholds to Anomaly Analysis

\n

Alerts are a reaction to metrics going outside the normal range. At an advanced level, we use PromQL for complex conditions and configure rules in Alertmanager.

\n\n

3.1. Basic Alert Rules

\n

Create a file alerts.yml:

\n

Blogs

Book Recommendations