Process monitoring
Basic Concepts of Process Monitoring
Process monitoring is an indispensable part of Node.js application development, helping developers keep track of the application's runtime status in real time and promptly detect and handle anomalies. Node.js provides various built-in modules and third-party tools to implement process monitoring, including features like performance metric collection, memory leak detection, and CPU usage monitoring.
Core Metrics for Process Monitoring
CPU Usage
CPU usage is one of the most direct performance metrics. Node.js's os
module can retrieve system CPU information:
const os = require('os');
function getCPUUsage() {
const cpus = os.cpus();
const totalIdle = cpus.reduce((acc, cpu) => acc + cpu.times.idle, 0);
const totalTick = cpus.reduce((acc, cpu) =>
acc + Object.values(cpu.times).reduce((a, b) => a + b), 0);
return 100 - (100 * totalIdle / totalTick);
}
setInterval(() => {
console.log(`CPU Usage: ${getCPUUsage().toFixed(2)}%`);
}, 1000);
Memory Monitoring
Node.js process memory usage can be obtained via process.memoryUsage()
:
setInterval(() => {
const memory = process.memoryUsage();
console.log(`
RSS: ${(memory.rss / 1024 / 1024).toFixed(2)} MB
Heap Total: ${(memory.heapTotal / 1024 / 1024).toFixed(2)} MB
Heap Used: ${(memory.heapUsed / 1024 / 1024).toFixed(2)} MB
External: ${(memory.external / 1024 / 1024).toFixed(2)} MB
`);
}, 5000);
Event Loop Monitoring
Event Loop Latency
Event loop latency is a key performance metric for Node.js and can be measured using the perf_hooks
module:
const { performance, monitorEventLoopDelay } = require('perf_hooks');
const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
setInterval(() => {
console.log(`Event Loop Delay (ms):
Min: ${h.min / 1e6}
Max: ${h.max / 1e6}
Mean: ${h.mean / 1e6}
Stddev: ${h.stddev / 1e6}
`);
h.reset();
}, 10000);
Process Exception Monitoring
Uncaught Exception Handling
Global exception catching is a critical part of process monitoring:
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err.stack);
// Perform necessary cleanup
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});
Advanced Monitoring Solutions
Using PM2 for Process Management
PM2 provides robust process monitoring capabilities:
# Install PM2
npm install pm2 -g
# Start the application with monitoring
pm2 start app.js --name "my-app" --watch
# View the monitoring dashboard
pm2 monit
Custom Health Check Endpoint
Add a health check route in an Express application:
const express = require('express');
const app = express();
app.get('/health', (req, res) => {
const memory = process.memoryUsage();
const uptime = process.uptime();
res.json({
status: 'healthy',
uptime: `${uptime.toFixed(2)} seconds`,
memory: {
rss: `${(memory.rss / 1024 / 1024).toFixed(2)} MB`,
heapTotal: `${(memory.heapTotal / 1024 / 1024).toFixed(2)} MB`,
heapUsed: `${(memory.heapUsed / 1024 / 1024).toFixed(2)} MB`
},
eventLoopDelay: `${h.mean / 1e6} ms`
});
});
app.listen(3000);
Logging and Alert Integration
Winston Logging Integration
Implement structured logging with Winston:
const winston = require('winston');
const { combine, timestamp, json } = winston.format;
const logger = winston.createLogger({
level: 'info',
format: combine(timestamp(), json()),
transports: [
new winston.transports.File({ filename: 'process-monitor.log' })
]
});
// Log memory usage
setInterval(() => {
const memory = process.memoryUsage();
logger.info('Memory usage', {
rss: memory.rss,
heapTotal: memory.heapTotal,
heapUsed: memory.heapUsed
});
}, 60000);
Alert Threshold Configuration
Implement a simple alert mechanism:
const ALERT_THRESHOLD = 80; // 80% CPU usage
setInterval(() => {
const cpuUsage = getCPUUsage();
if (cpuUsage > ALERT_THRESHOLD) {
logger.error('High CPU usage alert', {
cpuUsage,
threshold: ALERT_THRESHOLD
});
// Can integrate email/SMS notifications
}
}, 5000);
Process Monitoring in Distributed Environments
Using OpenTelemetry
Distributed tracing is a key component of modern monitoring:
const { NodeTracerProvider } = require('@opentelemetry/node');
const { SimpleSpanProcessor } = require('@opentelemetry/tracing');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const provider = new NodeTracerProvider();
provider.register();
const exporter = new JaegerExporter({
serviceName: 'node-process-monitor'
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
Performance Optimization Practices
Memory Leak Detection
Use the heapdump
module to capture heap snapshots:
const heapdump = require('heapdump');
// Generate a heap snapshot when memory exceeds 1GB
setInterval(() => {
if (process.memoryUsage().rss > 1024 * 1024 * 1024) {
const filename = `heapdump-${Date.now()}.heapsnapshot`;
heapdump.writeSnapshot(filename, (err) => {
if (err) console.error(err);
else console.log(`Heap snapshot written to ${filename}`);
});
}
}, 60000);
Event Loop Blocking Detection
Detect long-running synchronous code:
const { performance } = require('perf_hooks');
const threshold = 200; // 200ms threshold
let lastLoopTime = performance.now();
setInterval(() => {
const now = performance.now();
const delta = now - lastLoopTime;
if (delta > threshold) {
logger.warn('Event loop blocked', {
duration: delta,
threshold
});
}
lastLoopTime = now;
}, 1000);
Monitoring in Containerized Environments
Docker Health Check
Add a health check directive in the Dockerfile:
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:3000/health || exit 1
Kubernetes Probe Configuration
Liveness and readiness probes in Kubernetes deployments:
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
Visualization Dashboards
Using Grafana to Display Metrics
Create monitoring dashboards with Prometheus and Grafana:
const client = require('prom-client');
// Create metrics
const cpuGauge = new client.Gauge({
name: 'node_cpu_usage_percent',
help: 'Current CPU usage in percent'
});
const memoryGauge = new client.Gauge({
name: 'node_memory_usage_bytes',
help: 'Current memory usage in bytes',
labelNames: ['type']
});
// Update metrics
setInterval(() => {
cpuGauge.set(getCPUUsage());
const memory = process.memoryUsage();
memoryGauge.set({ type: 'rss' }, memory.rss);
memoryGauge.set({ type: 'heapTotal' }, memory.heapTotal);
memoryGauge.set({ type: 'heapUsed' }, memory.heapUsed);
}, 5000);
// Expose metrics endpoint
app.get('/metrics', async (req, res) => {
res.set('Content-Type', client.register.contentType);
res.end(await client.register.metrics());
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn