Set up comprehensive Node.js application monitoring with Prometheus metrics collection and Grafana dashboards. Configure alerting rules for performance issues, memory usage, and error tracking in production environments.
Prerequisites
- Root or sudo access
- Node.js application to monitor
- At least 2GB RAM
- Network connectivity for package installation
What this solves
Node.js applications in production need comprehensive monitoring to track performance, memory usage, response times, and error rates. This tutorial sets up Prometheus 2.45 to collect metrics from your Node.js applications using the prom-client library, creates Grafana dashboards for visualization, and implements alerting rules for proactive performance monitoring.
Step-by-step installation
Update system packages
Start by updating your package manager to ensure you get the latest versions of dependencies.
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget gnupg2 software-properties-common
Install Prometheus 2.45
Download and install Prometheus server to collect and store metrics from your Node.js applications.
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz
tar -xzf prometheus-2.45.0.linux-amd64.tar.gz
sudo mv prometheus-2.45.0.linux-amd64/prometheus /usr/local/bin/
sudo mv prometheus-2.45.0.linux-amd64/promtool /usr/local/bin/
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
Create Prometheus user and service
Create a dedicated user for Prometheus and set up the systemd service for automatic startup.
sudo useradd --no-create-home --shell /bin/false prometheus
sudo chown -R prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
Configure Prometheus
Create the main Prometheus configuration file to scrape Node.js application metrics.
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "nodejs_alerts.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'nodejs-app'
static_configs:
- targets: ['localhost:3000']
metrics_path: '/metrics'
scrape_interval: 5s
Create Prometheus systemd service
Set up systemd service file to manage Prometheus startup and enable automatic restart on failure.
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
Restart=on-failure
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus/ \
--web.console.templates=/etc/prometheus/consoles \
--web.console.libraries=/etc/prometheus/console_libraries \
--web.listen-address=0.0.0.0:9090 \
--web.enable-lifecycle
[Install]
WantedBy=multi-user.target
Install Node.js and npm
Install Node.js runtime and npm package manager if not already installed.
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
Create sample Node.js application with metrics
Create a sample Node.js application that exposes Prometheus metrics using the prom-client library.
mkdir -p /opt/nodejs-app
cd /opt/nodejs-app
npm init -y
npm install express prom-client
Implement Node.js metrics collection
Create the main application file with comprehensive Prometheus metrics including HTTP requests, memory usage, and custom business metrics.
const express = require('express');
const promClient = require('prom-client');
const app = express();
const port = 3000;
// Create a Registry to register the metrics
const register = new promClient.Registry();
// Add default system metrics
promClient.collectDefaultMetrics({
register,
timeout: 10000,
gcDurationBuckets: [0.001, 0.01, 0.1, 1, 2, 5],
});
// Custom metrics
const httpRequestCounter = new promClient.Counter({
name: 'nodejs_http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'route', 'status_code'],
registers: [register],
});
const httpRequestDuration = new promClient.Histogram({
name: 'nodejs_http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10],
registers: [register],
});
const activeConnections = new promClient.Gauge({
name: 'nodejs_active_connections',
help: 'Number of active connections',
registers: [register],
});
const businessMetric = new promClient.Counter({
name: 'nodejs_business_operations_total',
help: 'Total business operations performed',
labelNames: ['operation_type'],
registers: [register],
});
// Middleware to collect metrics
app.use((req, res, next) => {
const start = Date.now();
activeConnections.inc();
res.on('finish', () => {
const duration = (Date.now() - start) / 1000;
httpRequestCounter.inc({
method: req.method,
route: req.route ? req.route.path : req.path,
status_code: res.statusCode,
});
httpRequestDuration.observe(
{
method: req.method,
route: req.route ? req.route.path : req.path,
status_code: res.statusCode,
},
duration
);
activeConnections.dec();
});
next();
});
// Sample routes
app.get('/', (req, res) => {
businessMetric.inc({ operation_type: 'homepage_view' });
res.json({ message: 'Hello World!', timestamp: new Date().toISOString() });
});
app.get('/api/users', (req, res) => {
businessMetric.inc({ operation_type: 'user_list' });
// Simulate some processing time
setTimeout(() => {
res.json({
users: [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
],
});
}, Math.random() * 1000);
});
app.get('/api/error', (req, res) => {
businessMetric.inc({ operation_type: 'error_simulation' });
res.status(500).json({ error: 'Simulated error' });
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'healthy', uptime: process.uptime() });
});
// Metrics endpoint
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType);
const metrics = await register.metrics();
res.end(metrics);
});
app.listen(port, () => {
console.log(Node.js app listening at http://localhost:${port});
console.log(Metrics available at http://localhost:${port}/metrics);
});
Create Node.js application service
Set up systemd service for the Node.js application to ensure it starts automatically and restarts on failure.
[Unit]
Description=Node.js Monitoring Demo App
After=network.target
[Service]
Type=simple
User=nodejs
Group=nodejs
WorkingDirectory=/opt/nodejs-app
Environment=NODE_ENV=production
ExecStart=/usr/bin/node app.js
Restart=on-failure
RestartSec=10
KillMode=process
[Install]
WantedBy=multi-user.target
Create application user and set permissions
Create a dedicated user for the Node.js application and set proper file ownership and permissions.
sudo useradd --system --shell /bin/false nodejs
sudo chown -R nodejs:nodejs /opt/nodejs-app
sudo chmod 755 /opt/nodejs-app
sudo chmod 644 /opt/nodejs-app/*
Install Grafana
Install Grafana for creating dashboards and visualizing the Node.js metrics collected by Prometheus.
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
Configure Grafana data source
Configure Grafana to use Prometheus as a data source for Node.js metrics visualization.
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://localhost:9090
isDefault: true
jsonData:
timeInterval: 15s
queryTimeout: 60s
httpMethod: POST
editable: true
Create Node.js dashboard configuration
Create a comprehensive Grafana dashboard configuration for monitoring Node.js application performance.
{
"dashboard": {
"id": null,
"title": "Node.js Application Monitoring",
"tags": ["nodejs", "prometheus"],
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "HTTP Request Rate",
"type": "stat",
"targets": [
{
"expr": "rate(nodejs_http_requests_total[5m])",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}
},
{
"id": 2,
"title": "Response Time",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(nodejs_http_request_duration_seconds_bucket[5m]))",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}
},
{
"id": 3,
"title": "Memory Usage",
"type": "graph",
"targets": [
{
"expr": "process_resident_memory_bytes",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 8}
},
{
"id": 4,
"title": "Error Rate",
"type": "stat",
"targets": [
{
"expr": "rate(nodejs_http_requests_total{status_code=~\"5..\"}[5m])",
"refId": "A"
}
],
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 8}
}
],
"time": {
"from": "now-1h",
"to": "now"
},
"refresh": "5s"
}
}
Create alerting rules
Define Prometheus alerting rules for Node.js application performance monitoring and error detection.
groups:
- name: nodejs-alerts
rules:
- alert: NodejsHighErrorRate
expr: rate(nodejs_http_requests_total{status_code=~"5.."}[5m]) > 0.1
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate detected in Node.js application"
description: "Error rate is {{ $value }} errors per second"
- alert: NodejsHighResponseTime
expr: histogram_quantile(0.95, rate(nodejs_http_request_duration_seconds_bucket[5m])) > 1.0
for: 5m
labels:
severity: warning
annotations:
summary: "High response time in Node.js application"
description: "95th percentile response time is {{ $value }}s"
- alert: NodejsHighMemoryUsage
expr: process_resident_memory_bytes > 500000000
for: 10m
labels:
severity: warning
annotations:
summary: "High memory usage in Node.js application"
description: "Memory usage is {{ $value | humanize }}B"
- alert: NodejsApplicationDown
expr: up{job="nodejs-app"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Node.js application is down"
description: "Node.js application has been down for more than 1 minute"
Start and enable services
Start all services and enable them to start automatically on system boot.
sudo systemctl daemon-reload
sudo systemctl enable --now nodejs-app
sudo systemctl enable --now prometheus
sudo systemctl enable --now grafana-server
Configure firewall
Open necessary firewall ports for Prometheus, Grafana, and the Node.js application.
sudo ufw allow 3000/tcp comment 'Node.js app'
sudo ufw allow 9090/tcp comment 'Prometheus'
sudo ufw allow 3000/tcp comment 'Grafana'
sudo ufw --force enable
Verify your setup
Test that all components are working correctly and metrics are being collected.
sudo systemctl status nodejs-app prometheus grafana-server
curl http://localhost:3000/health
curl http://localhost:3000/metrics
curl http://localhost:9090/api/v1/targets
echo "Grafana available at: http://localhost:3000 (admin/admin)"
Generate test metrics
Create some sample traffic to populate your dashboards with meaningful data.
for i in {1..100}; do
curl -s http://localhost:3000/ > /dev/null
curl -s http://localhost:3000/api/users > /dev/null
curl -s http://localhost:3000/api/error > /dev/null
sleep 0.1
done
Advanced monitoring configuration
Add custom business metrics
Extend your Node.js application with custom business metrics for specific application events.
const promClient = require('prom-client');
class ApplicationMetrics {
constructor(register) {
this.register = register;
this.userRegistrations = new promClient.Counter({
name: 'nodejs_user_registrations_total',
help: 'Total number of user registrations',
labelNames: ['source'],
registers: [register],
});
this.orderValues = new promClient.Histogram({
name: 'nodejs_order_value_dollars',
help: 'Order values in dollars',
labelNames: ['product_category'],
buckets: [10, 50, 100, 500, 1000, 5000],
registers: [register],
});
this.cacheHits = new promClient.Counter({
name: 'nodejs_cache_hits_total',
help: 'Total cache hits',
labelNames: ['cache_type'],
registers: [register],
});
}
recordUserRegistration(source) {
this.userRegistrations.inc({ source });
}
recordOrder(value, category) {
this.orderValues.observe({ product_category: category }, value);
}
recordCacheHit(cacheType) {
this.cacheHits.inc({ cache_type: cacheType });
}
}
module.exports = ApplicationMetrics;
Set up log-based metrics
Configure log parsing to extract metrics from application logs using structured logging.
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({
filename: '/var/log/nodejs-app/error.log',
level: 'error'
}),
new winston.transports.File({
filename: '/var/log/nodejs-app/combined.log'
}),
new winston.transports.Console({
format: winston.format.simple()
})
],
});
module.exports = logger;
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Metrics endpoint returns 404 | prom-client not configured correctly | Check app.get('/metrics') route and ensure prom-client is installed |
| Prometheus can't scrape targets | Network connectivity or wrong port | Verify with curl http://localhost:3000/metrics |
| Grafana shows no data | Data source not configured | Check Prometheus connection in Grafana datasources |
| Alerts not firing | Alerting rules syntax error | Validate rules with promtool check rules /etc/prometheus/nodejs_alerts.yml |
| High memory usage from metrics | Too many metric labels | Reduce cardinality by limiting dynamic label values |
| Permission denied errors | Incorrect file ownership | Run sudo chown -R prometheus:prometheus /etc/prometheus |
Next steps
- Configure NGINX monitoring with Prometheus and Grafana dashboards for real-time web server performance metrics
- Implement Grafana advanced alerting with webhooks and notification channels
- Set up Prometheus Blackbox Exporter for uptime monitoring with SSL and alerting
- Configure Prometheus long-term storage with Thanos for unlimited data retention
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Configuration
PROMETHEUS_VERSION="2.45.0"
NODE_VERSION="20.x"
PROMETHEUS_USER="prometheus"
APP_DIR="/opt/nodejs-monitoring"
# Error handling
cleanup() {
echo -e "${RED}Installation failed. Cleaning up...${NC}"
systemctl stop prometheus 2>/dev/null || true
systemctl disable prometheus 2>/dev/null || true
userdel -r $PROMETHEUS_USER 2>/dev/null || true
rm -rf /usr/local/bin/prometheus /usr/local/bin/promtool
rm -rf /etc/prometheus /var/lib/prometheus
rm -rf $APP_DIR
rm -f /etc/systemd/system/prometheus.service
}
trap cleanup ERR
# Usage
usage() {
echo "Usage: $0 [APP_PORT] [PROMETHEUS_PORT]"
echo " APP_PORT: Node.js application port (default: 3000)"
echo " PROMETHEUS_PORT: Prometheus server port (default: 9090)"
exit 1
}
# Parse arguments
APP_PORT="${1:-3000}"
PROMETHEUS_PORT="${2:-9090}"
# Validate ports
if ! [[ "$APP_PORT" =~ ^[0-9]+$ ]] || [ "$APP_PORT" -lt 1024 ] || [ "$APP_PORT" -gt 65535 ]; then
echo -e "${RED}Error: APP_PORT must be a number between 1024-65535${NC}"
usage
fi
if ! [[ "$PROMETHEUS_PORT" =~ ^[0-9]+$ ]] || [ "$PROMETHEUS_PORT" -lt 1024 ] || [ "$PROMETHEUS_PORT" -gt 65535 ]; then
echo -e "${RED}Error: PROMETHEUS_PORT must be a number between 1024-65535${NC}"
usage
fi
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
# Detect distribution
echo -e "${YELLOW}[1/12] Detecting distribution...${NC}"
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update && apt upgrade -y"
PKG_INSTALL="apt install -y"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
;;
fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
else
echo -e "${RED}/etc/os-release not found. Cannot detect distribution.${NC}"
exit 1
fi
echo -e "${GREEN}Detected: $PRETTY_NAME${NC}"
# Update system packages
echo -e "${YELLOW}[2/12] Updating system packages...${NC}"
$PKG_UPDATE
# Install dependencies
echo -e "${YELLOW}[3/12] Installing dependencies...${NC}"
$PKG_INSTALL curl wget gnupg2 tar
# Install additional packages for Debian-based systems
if [ "$PKG_MGR" = "apt" ]; then
$PKG_INSTALL software-properties-common
fi
# Create prometheus user
echo -e "${YELLOW}[4/12] Creating Prometheus user...${NC}"
if ! id "$PROMETHEUS_USER" &>/dev/null; then
useradd --no-create-home --shell /bin/false $PROMETHEUS_USER
fi
# Download and install Prometheus
echo -e "${YELLOW}[5/12] Installing Prometheus ${PROMETHEUS_VERSION}...${NC}"
cd /tmp
wget -q "https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz"
tar -xzf "prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz"
# Move binaries
mv "prometheus-${PROMETHEUS_VERSION}.linux-amd64/prometheus" /usr/local/bin/
mv "prometheus-${PROMETHEUS_VERSION}.linux-amd64/promtool" /usr/local/bin/
chmod 755 /usr/local/bin/prometheus /usr/local/bin/promtool
# Create directories
mkdir -p /etc/prometheus /var/lib/prometheus
mkdir -p /etc/prometheus/consoles /etc/prometheus/console_libraries
# Copy console files if they exist
if [ -d "prometheus-${PROMETHEUS_VERSION}.linux-amd64/consoles" ]; then
cp -r "prometheus-${PROMETHEUS_VERSION}.linux-amd64/consoles/" /etc/prometheus/
fi
if [ -d "prometheus-${PROMETHEUS_VERSION}.linux-amd64/console_libraries" ]; then
cp -r "prometheus-${PROMETHEUS_VERSION}.linux-amd64/console_libraries/" /etc/prometheus/
fi
# Set ownership
chown -R $PROMETHEUS_USER:$PROMETHEUS_USER /etc/prometheus /var/lib/prometheus
# Create Prometheus configuration
echo -e "${YELLOW}[6/12] Creating Prometheus configuration...${NC}"
cat > /etc/prometheus/prometheus.yml << EOF
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "nodejs_alerts.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:${PROMETHEUS_PORT}']
- job_name: 'nodejs-app'
static_configs:
- targets: ['localhost:${APP_PORT}']
metrics_path: '/metrics'
scrape_interval: 5s
EOF
# Create alerting rules
cat > /etc/prometheus/nodejs_alerts.yml << 'EOF'
groups:
- name: nodejs_alerts
rules:
- alert: HighMemoryUsage
expr: nodejs_memory_heap_used_bytes / nodejs_memory_heap_total_bytes > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage detected"
description: "Node.js application memory usage is above 80%"
- alert: HighResponseTime
expr: nodejs_http_request_duration_seconds > 1
for: 2m
labels:
severity: critical
annotations:
summary: "High response time detected"
description: "HTTP response time is above 1 second"
EOF
chown -R $PROMETHEUS_USER:$PROMETHEUS_USER /etc/prometheus/
# Create systemd service
echo -e "${YELLOW}[7/12] Creating Prometheus systemd service...${NC}"
cat > /etc/systemd/system/prometheus.service << EOF
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/
After=network-online.target
[Service]
User=$PROMETHEUS_USER
Group=$PROMETHEUS_USER
Type=simple
Restart=on-failure
ExecStart=/usr/local/bin/prometheus \\
--config.file=/etc/prometheus/prometheus.yml \\
--storage.tsdb.path=/var/lib/prometheus/ \\
--web.console.templates=/etc/prometheus/consoles \\
--web.console.libraries=/etc/prometheus/console_libraries \\
--web.listen-address=0.0.0.0:${PROMETHEUS_PORT} \\
--web.enable-lifecycle
[Install]
WantedBy=multi-user.target
EOF
# Install Node.js
echo -e "${YELLOW}[8/12] Installing Node.js...${NC}"
if [ "$PKG_MGR" = "apt" ]; then
curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION} | bash -
$PKG_INSTALL nodejs
else
curl -fsSL https://rpm.nodesource.com/setup_${NODE_VERSION} | bash -
$PKG_INSTALL nodejs npm
fi
# Create Node.js monitoring application
echo -e "${YELLOW}[9/12] Creating Node.js monitoring application...${NC}"
mkdir -p $APP_DIR
cd $APP_DIR
# Create package.json
cat > package.json << EOF
{
"name": "nodejs-monitoring-app",
"version": "1.0.0",
"description": "Node.js application with Prometheus monitoring",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.18.2",
"prom-client": "^14.2.0"
}
}
EOF
# Install dependencies
npm install
# Create the monitoring application
cat > app.js << EOF
const express = require('express');
const promClient = require('prom-client');
const app = express();
const port = ${APP_PORT};
// Create a Registry to register the metrics
const register = new promClient.Registry();
// Add default system metrics
promClient.collectDefaultMetrics({
register,
timeout: 10000,
gcDurationBuckets: [0.001, 0.01, 0.1, 1, 2, 5],
});
// Custom metrics
const httpRequestCounter = new promClient.Counter({
name: 'nodejs_http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'route', 'status'],
registers: [register]
});
const httpRequestDuration = new promClient.Histogram({
name: 'nodejs_http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route'],
registers: [register]
});
// Middleware for metrics
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = (Date.now() - start) / 1000;
httpRequestCounter.inc({
method: req.method,
route: req.route ? req.route.path : req.path,
status: res.statusCode
});
httpRequestDuration.observe({
method: req.method,
route: req.route ? req.route.path : req.path
}, duration);
});
next();
});
// Routes
app.get('/', (req, res) => {
res.json({ message: 'Node.js Monitoring Application', status: 'running' });
});
app.get('/health', (req, res) => {
res.json({ status: 'healthy', timestamp: new Date().toISOString() });
});
app.get('/metrics', (req, res) => {
res.set('Content-Type', register.contentType);
register.metrics().then(metrics => res.send(metrics));
});
app.listen(port, () => {
console.log(\`Node.js monitoring app listening at http://localhost:\${port}\`);
});
EOF
# Create systemd service for Node.js app
echo -e "${YELLOW}[10/12] Creating Node.js application service...${NC}"
cat > /etc/systemd/system/nodejs-monitoring.service << EOF
[Unit]
Description=Node.js Monitoring Application
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=$APP_DIR
ExecStart=/usr/bin/node app.js
Restart=on-failure
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
EOF
# Enable and start services
echo -e "${YELLOW}[11/12] Starting services...${NC}"
systemctl daemon-reload
systemctl enable prometheus nodejs-monitoring
systemctl start nodejs-monitoring
sleep 3
systemctl start prometheus
# Configure firewall if present
echo -e "${YELLOW}[12/12] Configuring firewall...${NC}"
if command -v firewall-cmd &> /dev/null; then
firewall-cmd --permanent --add-port=${APP_PORT}/tcp
firewall-cmd --permanent --add-port=${PROMETHEUS_PORT}/tcp
firewall-cmd --reload
elif command -v ufw &> /dev/null; then
ufw allow ${APP_PORT}/tcp
ufw allow ${PROMETHEUS_PORT}/tcp
fi
# Verification
echo -e "${GREEN}Installation completed! Verifying services...${NC}"
sleep 5
if systemctl is-active --quiet nodejs-monitoring; then
echo -e "${GREEN}✓ Node.js application is running${NC}"
else
echo -e "${RED}✗ Node.js application failed to start${NC}"
fi
if systemctl is-active --quiet prometheus; then
echo -e "${GREEN}✓ Prometheus is running${NC}"
else
echo -e "${RED}✗ Prometheus failed to start${NC}"
fi
# Test endpoints
if curl -s "http://localhost:${APP_PORT}/health" > /dev/null; then
echo -e "${GREEN}✓ Node.js health endpoint responding${NC}"
else
echo -e "${RED}✗ Node.js health endpoint not responding${NC}"
fi
if curl -s "http://localhost:${PROMETHEUS_PORT}/-/healthy" > /dev/null; then
echo -e "${GREEN}✓ Prometheus health endpoint responding${NC}"
else
echo -e "${RED}✗ Prometheus health endpoint not responding${NC}"
fi
echo -e "${GREEN}Setup complete!${NC}"
echo -e "${YELLOW}Access points:${NC}"
echo "Node.js App: http://localhost:${APP_PORT}"
echo "Node.js Metrics: http://localhost:${APP_PORT}/metrics"
echo "Prometheus: http://localhost:${PROMETHEUS_PORT}"
echo ""
echo -e "${YELLOW}Service management:${NC}"
echo "systemctl status prometheus"
echo "systemctl status nodejs-monitoring"
echo "journalctl -u prometheus -f"
echo "journalctl -u nodejs-monitoring -f"
Review the script before running. Execute with: bash install.sh