Set up comprehensive Node.js application monitoring with Prometheus metrics collection, custom performance tracking, and Grafana dashboards for real-time observability and alerting.
Prerequisites
- Node.js application running
- Sudo access
- Port 3000, 9090, 9093 available
What this solves
Monitoring Node.js applications in production requires visibility into application performance, request rates, error counts, and resource usage. This tutorial sets up Prometheus metrics collection for Node.js applications and creates comprehensive Grafana dashboards for monitoring application health, performance bottlenecks, and setting up automated alerts.
Prerequisites
You'll need a Node.js application running on your server and sudo access to install monitoring components. This tutorial assumes you have a basic Express.js application, but the metrics collection patterns work with any Node.js framework.
Step-by-step configuration
Install Prometheus server
Download and install Prometheus to collect 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 cp prometheus-2.45.0.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-2.45.0.linux-amd64/promtool /usr/local/bin/
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo cp -r prometheus-2.45.0.linux-amd64/consoles /etc/prometheus
sudo cp -r prometheus-2.45.0.linux-amd64/console_libraries /etc/prometheus
Create Prometheus user and set permissions
Create a dedicated user for Prometheus and set correct ownership on configuration directories.
sudo useradd --no-create-home --shell /bin/false prometheus
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool
Configure Prometheus
Create the main Prometheus configuration file to scrape Node.js application metrics.
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "/etc/prometheus/rules/*.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- localhost:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-app'
static_configs:
- targets: ['localhost:3000']
metrics_path: '/metrics'
scrape_interval: 5s
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100']
Create Prometheus systemd service
Set up Prometheus to run as a system service with automatic startup.
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
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 Exporter
Install Node Exporter to collect system metrics alongside application metrics.
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz
tar xzf node_exporter-1.6.1.linux-amd64.tar.gz
sudo cp node_exporter-1.6.1.linux-amd64/node_exporter /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/node_exporter
Create Node Exporter systemd service
Configure Node Exporter as a system service for system metrics collection.
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
Install Prometheus client in Node.js application
Add the Prometheus client library to your Node.js application for metrics collection.
cd /path/to/your/node/app
npm install prom-client express-prometheus-middleware
Configure Node.js application metrics
Add Prometheus metrics collection to your Express.js application with custom performance tracking.
const express = require('express');
const client = require('prom-client');
const promMid = require('express-prometheus-middleware');
const app = express();
// Create a Registry which registers the metrics
const register = new client.Registry();
// Add a default label which is added to all metrics
register.setDefaultLabels({
app: 'my-node-app'
});
// Enable the collection of default metrics
client.collectDefaultMetrics({ register });
// Custom metrics
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status'],
buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10]
});
const httpRequestsTotal = new client.Counter({
name: 'http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'route', 'status']
});
const activeConnections = new client.Gauge({
name: 'active_connections',
help: 'Number of active connections'
});
const databaseConnections = new client.Gauge({
name: 'database_connections',
help: 'Number of database connections',
labelNames: ['database', 'state']
});
// Register custom metrics
register.registerMetric(httpRequestDuration);
register.registerMetric(httpRequestsTotal);
register.registerMetric(activeConnections);
register.registerMetric(databaseConnections);
// Middleware to track request metrics
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = (Date.now() - start) / 1000;
const route = req.route ? req.route.path : req.url;
httpRequestDuration
.labels(req.method, route, res.statusCode)
.observe(duration);
httpRequestsTotal
.labels(req.method, route, res.statusCode)
.inc();
});
next();
});
// Track active connections
app.use((req, res, next) => {
activeConnections.inc();
res.on('finish', () => activeConnections.dec());
next();
});
// Metrics endpoint
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType);
res.end(await register.metrics());
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'healthy', timestamp: new Date().toISOString() });
});
// Example route with custom metrics
app.get('/api/users', (req, res) => {
// Simulate database connection tracking
databaseConnections.labels('users_db', 'active').set(5);
databaseConnections.labels('users_db', 'idle').set(3);
res.json({ users: ['alice', 'bob', 'charlie'] });
});
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(Server running on port ${port});
console.log(Metrics available at http://localhost:${port}/metrics);
});
Install and configure Grafana
Install Grafana for creating dashboards and visualizing Prometheus metrics.
sudo apt update
sudo apt install -y software-properties-common
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
Start and enable services
Start all monitoring services and enable them to start automatically on boot.
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
sudo systemctl enable --now node_exporter
sudo systemctl enable --now grafana-server
Verify services are running
sudo systemctl status prometheus
sudo systemctl status node_exporter
sudo systemctl status grafana-server
Configure Grafana data source
Add Prometheus as a data source in Grafana for metrics visualization.
# Access Grafana web interface at http://your-server:3000
Default credentials: admin/admin
Add Prometheus data source via API
curl -X POST \
http://admin:admin@localhost:3000/api/datasources \
-H 'Content-Type: application/json' \
-d '{
"name": "Prometheus",
"type": "prometheus",
"url": "http://localhost:9090",
"access": "proxy",
"isDefault": true
}'
Create Node.js application dashboard
Import a comprehensive dashboard for Node.js application monitoring.
{
"dashboard": {
"id": null,
"title": "Node.js Application Monitoring",
"tags": ["nodejs", "prometheus"],
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "HTTP Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"legendFormat": "{{method}} {{route}}"
}
],
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}
},
{
"id": 2,
"title": "HTTP Request Duration",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
"legendFormat": "95th percentile"
},
{
"expr": "histogram_quantile(0.50, rate(http_request_duration_seconds_bucket[5m]))",
"legendFormat": "50th percentile"
}
],
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}
},
{
"id": 3,
"title": "Active Connections",
"type": "singlestat",
"targets": [
{
"expr": "active_connections",
"legendFormat": "Connections"
}
],
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 8}
},
{
"id": 4,
"title": "Memory Usage",
"type": "graph",
"targets": [
{
"expr": "process_resident_memory_bytes",
"legendFormat": "RSS Memory"
},
{
"expr": "nodejs_heap_size_used_bytes",
"legendFormat": "Heap Used"
}
],
"gridPos": {"h": 8, "w": 12, "x": 6, "y": 8}
}
],
"time": {"from": "now-1h", "to": "now"},
"refresh": "5s"
}
}
# Import dashboard via API
curl -X POST \
http://admin:admin@localhost:3000/api/dashboards/db \
-H 'Content-Type: application/json' \
-d @/tmp/nodejs-dashboard.json
Configure alerting rules
Set up Prometheus alerting rules for Node.js application monitoring.
sudo mkdir -p /etc/prometheus/rules
groups:
- name: nodejs_alerts
rules:
- alert: HighRequestLatency
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 0.5
for: 5m
labels:
severity: warning
annotations:
summary: "High request latency on Node.js application"
description: "95th percentile latency is {{ $value }}s for more than 5 minutes"
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.1
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate on Node.js application"
description: "Error rate is {{ $value }} errors per second"
- alert: MemoryUsageHigh
expr: process_resident_memory_bytes > 500000000
for: 5m
labels:
severity: warning
annotations:
summary: "High memory usage on Node.js application"
description: "Memory usage is {{ $value | humanize }}B"
- alert: NodeJSDown
expr: up{job="node-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"
Install and configure Alertmanager
Set up Alertmanager for handling and routing alerts from Prometheus.
cd /tmp
wget https://github.com/prometheus/alertmanager/releases/download/v0.25.0/alertmanager-0.25.0.linux-amd64.tar.gz
tar xzf alertmanager-0.25.0.linux-amd64.tar.gz
sudo cp alertmanager-0.25.0.linux-amd64/alertmanager /usr/local/bin/
sudo cp alertmanager-0.25.0.linux-amd64/amtool /usr/local/bin/
sudo mkdir -p /etc/alertmanager
sudo chown prometheus:prometheus /usr/local/bin/alertmanager /usr/local/bin/amtool /etc/alertmanager
Configure Alertmanager
Set up Alertmanager configuration for email and webhook notifications.
global:
smtp_smarthost: 'localhost:587'
smtp_from: 'alerts@example.com'
smtp_auth_username: 'alerts@example.com'
smtp_auth_password: 'your_email_password'
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'web.hook'
receivers:
- name: 'web.hook'
email_configs:
- to: 'admin@example.com'
subject: '[ALERT] {{ .GroupLabels.alertname }}'
body: |
{{ range .Alerts }}
Alert: {{ .Annotations.summary }}
Description: {{ .Annotations.description }}
Labels: {{ range .Labels.SortedPairs }}{{ .Name }}={{ .Value }} {{ end }}
{{ end }}
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
Create Alertmanager systemd service
Configure Alertmanager to run as a system service.
[Unit]
Description=Alertmanager
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/alertmanager \
--config.file=/etc/alertmanager/alertmanager.yml \
--storage.path=/var/lib/alertmanager/
[Install]
WantedBy=multi-user.target
Set up firewall rules
Configure firewall rules to allow access to monitoring services.
sudo ufw allow 9090/tcp comment 'Prometheus'
sudo ufw allow 3000/tcp comment 'Grafana'
sudo ufw allow 9093/tcp comment 'Alertmanager'
sudo ufw reload
Start Alertmanager and restart Prometheus
Enable Alertmanager and restart Prometheus to load the new alerting rules.
sudo mkdir -p /var/lib/alertmanager
sudo chown prometheus:prometheus /var/lib/alertmanager
sudo systemctl daemon-reload
sudo systemctl enable --now alertmanager
sudo systemctl restart prometheus
Verify services
sudo systemctl status alertmanager
sudo systemctl status prometheus
Verify your setup
Check that all monitoring components are working correctly and collecting metrics.
# Check Prometheus is collecting metrics
curl http://localhost:9090/api/v1/targets
Check Node.js application metrics
curl http://localhost:3000/metrics | grep http_requests_total
Check Grafana is accessible
curl -I http://localhost:3000/login
Check Alertmanager is running
curl http://localhost:9093/-/healthy
Test alert rules
prometheus --config.file=/etc/prometheus/prometheus.yml --web.listen-address=:9091 --dry-run
Access your monitoring stack:
- Prometheus:
http://your-server:9090 - Grafana:
http://your-server:3000(admin/admin) - Alertmanager:
http://your-server:9093 - Node.js metrics:
http://your-server:3000/metrics
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Prometheus can't scrape Node.js metrics | Wrong port or path configuration | Check scrape_configs in /etc/prometheus/prometheus.yml matches your app port |
| Grafana shows "No data" | Prometheus data source not configured | Add Prometheus as data source at http://localhost:9090 |
| Alerts not firing | Alert rules syntax error | Run promtool check rules /etc/prometheus/rules/*.yml |
| High memory usage | Too many metrics retained | Configure retention in Prometheus with --storage.tsdb.retention.time=15d |
| Node Exporter permission denied | Incorrect user permissions | Ensure prometheus user owns /usr/local/bin/node_exporter |
| Alertmanager not sending emails | SMTP configuration error | Test SMTP settings and check /etc/alertmanager/alertmanager.yml |
sudo chown -R prometheus:prometheus /var/lib/prometheus and chmod 755 for directories, chmod 644 for files.Next steps
Expand your monitoring setup with these advanced configurations:
- Configure Prometheus alerting with AlertManager notifications and webhook integration for advanced notification routing
- Monitor Node.js applications with Prometheus and Grafana for comprehensive performance metrics for additional application metrics
- Setup Prometheus Blackbox Exporter for endpoint monitoring with SSL and alerting for external endpoint monitoring
- Configure advanced Grafana dashboards and alerting with Prometheus integration for dashboard customization
- Implement Node.js clustering with PM2 and load balancing for scaling monitored applications
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration
PROMETHEUS_VERSION="2.45.0"
NODE_EXPORTER_VERSION="1.6.1"
GRAFANA_VERSION="10.2.2"
NODE_APP_PORT="${1:-3000}"
PROMETHEUS_PORT="9090"
GRAFANA_PORT="3000"
# Usage
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
echo "Usage: $0 [NODE_APP_PORT]"
echo " NODE_APP_PORT: Port where your Node.js app runs (default: 3000)"
exit 0
fi
# Error handling
cleanup() {
echo -e "${RED}Error occurred. Cleaning up...${NC}"
systemctl stop prometheus 2>/dev/null || true
systemctl stop node_exporter 2>/dev/null || true
systemctl stop grafana-server 2>/dev/null || true
rm -rf /tmp/prometheus-* /tmp/node_exporter-* /tmp/grafana-*
}
trap cleanup ERR
# Check prerequisites
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
# Detect distro
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
# Fallback to yum for older systems
if ! command -v dnf &> /dev/null; then
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
fi
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
;;
*)
echo -e "${RED}Unsupported distro: $ID${NC}"
exit 1
;;
esac
else
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
echo -e "${GREEN}Node.js Monitoring Setup - Prometheus + Grafana${NC}"
echo "Detected OS: $PRETTY_NAME"
echo "Package manager: $PKG_MGR"
# Update system
echo -e "${YELLOW}[1/12] Updating system packages...${NC}"
$PKG_UPDATE
# Install dependencies
echo -e "${YELLOW}[2/12] Installing dependencies...${NC}"
$PKG_INSTALL wget tar curl
# Create prometheus user
echo -e "${YELLOW}[3/12] Creating prometheus user...${NC}"
if ! id prometheus &>/dev/null; then
useradd --no-create-home --shell /bin/false prometheus
fi
# Install Prometheus
echo -e "${YELLOW}[4/12] Installing Prometheus...${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"
cp "prometheus-${PROMETHEUS_VERSION}.linux-amd64/prometheus" /usr/local/bin/
cp "prometheus-${PROMETHEUS_VERSION}.linux-amd64/promtool" /usr/local/bin/
mkdir -p /etc/prometheus /var/lib/prometheus /etc/prometheus/rules
cp -r "prometheus-${PROMETHEUS_VERSION}.linux-amd64/consoles" /etc/prometheus/
cp -r "prometheus-${PROMETHEUS_VERSION}.linux-amd64/console_libraries" /etc/prometheus/
chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool
chmod 755 /usr/local/bin/prometheus /usr/local/bin/promtool
# Configure Prometheus
echo -e "${YELLOW}[5/12] Configuring Prometheus...${NC}"
cat > /etc/prometheus/prometheus.yml << 'EOF'
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "/etc/prometheus/rules/*.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-app'
static_configs:
- targets: ['localhost:NODE_APP_PORT']
metrics_path: '/metrics'
scrape_interval: 5s
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100']
EOF
sed -i "s/NODE_APP_PORT/${NODE_APP_PORT}/g" /etc/prometheus/prometheus.yml
chown prometheus:prometheus /etc/prometheus/prometheus.yml
chmod 644 /etc/prometheus/prometheus.yml
# Create Prometheus systemd service
echo -e "${YELLOW}[6/12] Creating Prometheus service...${NC}"
cat > /etc/systemd/system/prometheus.service << 'EOF'
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
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
EOF
# Install Node Exporter
echo -e "${YELLOW}[7/12] Installing Node Exporter...${NC}"
cd /tmp
wget -q "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz"
tar xzf "node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz"
cp "node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter" /usr/local/bin/
chown prometheus:prometheus /usr/local/bin/node_exporter
chmod 755 /usr/local/bin/node_exporter
# Create Node Exporter systemd service
echo -e "${YELLOW}[8/12] Creating Node Exporter service...${NC}"
cat > /etc/systemd/system/node_exporter.service << 'EOF'
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
EOF
# Install Grafana
echo -e "${YELLOW}[9/12] Installing Grafana...${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL apt-transport-https software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" > /etc/apt/sources.list.d/grafana.list
apt update
$PKG_INSTALL grafana
else
cat > /etc/yum.repos.d/grafana.repo << 'EOF'
[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF
$PKG_INSTALL grafana
fi
# Configure firewall
echo -e "${YELLOW}[10/12] Configuring firewall...${NC}"
if command -v ufw &> /dev/null; then
ufw allow $PROMETHEUS_PORT/tcp
ufw allow 9100/tcp
ufw allow 3000/tcp
elif command -v firewall-cmd &> /dev/null; then
firewall-cmd --permanent --add-port=$PROMETHEUS_PORT/tcp
firewall-cmd --permanent --add-port=9100/tcp
firewall-cmd --permanent --add-port=3000/tcp
firewall-cmd --reload
fi
# Configure SELinux
if command -v setsebool &> /dev/null && getenforce 2>/dev/null | grep -q "Enforcing"; then
echo -e "${YELLOW}[11/12] Configuring SELinux...${NC}"
setsebool -P httpd_can_network_connect 1
fi
# Start and enable services
echo -e "${YELLOW}[12/12] Starting services...${NC}"
systemctl daemon-reload
systemctl enable prometheus node_exporter grafana-server
systemctl start prometheus node_exporter grafana-server
# Wait for services to start
sleep 5
# Verify installation
echo -e "${GREEN}Verifying installation...${NC}"
if systemctl is-active --quiet prometheus; then
echo -e "${GREEN}✓ Prometheus is running${NC}"
else
echo -e "${RED}✗ Prometheus failed to start${NC}"
exit 1
fi
if systemctl is-active --quiet node_exporter; then
echo -e "${GREEN}✓ Node Exporter is running${NC}"
else
echo -e "${RED}✗ Node Exporter failed to start${NC}"
exit 1
fi
if systemctl is-active --quiet grafana-server; then
echo -e "${GREEN}✓ Grafana is running${NC}"
else
echo -e "${RED}✗ Grafana failed to start${NC}"
exit 1
fi
# Cleanup temp files
rm -rf /tmp/prometheus-* /tmp/node_exporter-*
echo -e "${GREEN}Installation completed successfully!${NC}"
echo ""
echo "Access URLs:"
echo " Prometheus: http://localhost:$PROMETHEUS_PORT"
echo " Grafana: http://localhost:3000 (admin/admin)"
echo ""
echo "Add Prometheus data source in Grafana: http://localhost:$PROMETHEUS_PORT"
echo ""
echo "Don't forget to add metrics collection to your Node.js app using prom-client:"
echo " npm install prom-client"
Review the script before running. Execute with: bash install.sh