Monitoring JavaScript Applications: Metrics and Alerts from A to Z
\n\nIn the modern development world, it is not enough to simply write working code. It is critically important to understand how your application behaves in a production environment. Monitoring JavaScript applications (especially on Node.js) is not just a trend, but a necessity. It allows you to identify bottlenecks, prevent failures, and ensure high service availability. In this article, we will cover the full cycle: from collecting key metrics to setting up alerts, using a modern stack of tools.
\n\nWhy is Node.js Monitoring Important?
\nNode.js applications often operate asynchronously, processing thousands of requests per second. Without monitoring, you risk:
\n- \n
- Missing a memory leak that could crash the server. \n
- Not noticing an increase in response time (latency), which degrades the user experience. \n
- Losing data due to unhandled errors. \n
A monitoring system gives you visibility (observability) and allows you to make decisions based on data, not guesses.
\n\nKey Metrics for JavaScript Applications
\nAll metrics can be divided into three groups: infrastructure, business metrics, and application metrics. Let's look at them in detail.
\n\n1. Infrastructure Metrics (USE Method)
\nThese are basic server health indicators: CPU, memory, disk, network. For Node.js, memory (heap, non-heap) and the number of open file descriptors are especially important.
\n\n2. Application Metrics (RED Method)
\nThe RED method (Rate, Errors, Duration) is the gold standard for microservices:
\n- \n
- Rate: requests per second (RPS). \n
- Errors: percentage of requests that resulted in an error (4xx, 5xx). \n
- Duration: request execution time (p50, p95, p99 percentiles). \n
3. Business Metrics
\nSpecific to your product: number of registered users, completed orders, active sessions, etc.
\n\nCollecting Metrics with Prometheus and Node.js
\nPrometheus is the de facto standard for collecting metrics. For Node.js, we use the prom-client library. Let's look at a setup example.
Installation and Basic Setup
\nnpm install prom-client express\n\nLet's create a server with a /metrics endpoint:
const express = require('express');\nconst client = require('prom-client');\n\nconst app = express();\nconst port = 3000;\n\n// Create a metrics registry\nconst register = new client.Registry();\n\n// Add default Node.js metrics\nclient.collectDefaultMetrics({ register });\n\n// Create a custom histogram for response time\nconst httpRequestDuration = new client.Histogram({\n name: 'http_request_duration_seconds',\n help: 'Duration of HTTP requests in seconds',\n labelNames: ['method', 'route', 'status'],\n buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5]\n});\nregister.registerMetric(httpRequestDuration);\n\n// Middleware for measuring time\napp.use((req, res, next) => {\n const end = httpRequestDuration.startTimer();\n res.on('finish', () => {\n end({ method: req.method, route: req.route?.path || 'unknown', status: res.statusCode });\n });\n next();\n});\n\n// Endpoint for metrics\napp.get('/metrics', async (req, res) => {\n res.set('Content-Type', register.contentType);\n res.end(await register.metrics());\n});\n\napp.get('/', (req, res) => {\n res.send('Hello, monitoring!');\n});\n\napp.listen(port, () => {\n console.log(`App listening at http://localhost:${port}`);\n});\n\nCustom Counters
\nLet's add an error counter:
\nconst errorCounter = new client.Counter({\n name: 'app_errors_total',