Skip to main content

PM2 Monitoring Integration (Metrics + Logs)

This document outlines how to enable full observability for PM2-managed Node.js applications using Prometheus metrics and Loki logs, integrated via Grafana Alloy.


1. Install and Run PM2 Prometheus Exporter​

The PM2 Prometheus exporter exposes metrics such as CPU usage, memory, uptime, and restarts per process, which can be scraped by Grafana Alloy and visualized in Grafana Cloud.

Installation Steps​

cd ~
mkdir pm2-exporter
cd pm2-exporter

# Initialize Node.js project
npm init -y

# Install PM2 Prometheus Exporter
npm install pm2-prometheus-exporter

Start the Exporter​

Run the exporter under PM2 so it restarts automatically on reboot:

pm2 start ./node_modules/pm2-prometheus-exporter/exporter.js --name pm2-exporter -- --port 9209

This will expose metrics at http://localhost:9209/metrics.

You can verify it’s working with:

curl http://localhost:9209/metrics | head

You should see metrics like pm2_up, pm2_cpu, pm2_memory, and pm2_restart_count.


2. Scrape PM2 Metrics via Grafana Alloy​

Add the following block to your Alloy configuration file (/etc/alloy/config.alloy):

prometheus.scrape "pm2_exporter" {
targets = [
{ __address__ = "127.0.0.1:9209" },
]
job_name = "pm2_exporter"
metrics_path = "/metrics"
scrape_interval = "15s"
forward_to = [prometheus.relabel.metrics_instance.receiver]
}

This ensures Alloy scrapes the PM2 exporter every 15 seconds and forwards the data to Grafana Cloud via Prometheus Remote Write.

After saving the configuration, restart Alloy:

sudo systemctl restart alloy
sudo systemctl status alloy

3. Monitor PM2 Logs in Grafana (via Loki)​

To collect PM2 process logs, Alloy can tail the .pm2/logs directory and forward them to Grafana Cloud Loki.

Add the following to your Alloy configuration:

local.file_match "pm2_logs" {
path_targets = [
{ __path__ = "/home/<user>/.pm2/logs/*.log" },
]
sync_period = "5s"
}

loki.source.file "pm2_logs" {
targets = local.file_match.pm2_logs.targets
tail_from_end = true
forward_to = [loki.relabel.pm2_labels.receiver]
}

loki.relabel "pm2_labels" {
forward_to = [loki.write.grafana_cloud_loki.receiver]

rule {
action = "replace"
target_label = "job"
replacement = "pm2"
}
rule {
action = "replace"
target_label = "service"
replacement = "pm2"
}
rule {
action = "replace"
target_label = "env"
replacement = "prod"
}
rule {
action = "replace"
target_label = "instance"
replacement = constants.hostname
}
}

This configuration:

  • Tails all .log files in /home/<user>/.pm2/logs/
  • Assigns standardized labels (job, service, env, and instance)
  • Sends the logs directly to Grafana Cloud Loki

4. Verify Logs in Grafana​

In Grafana → Explore → Loki, run this query to confirm log ingestion:

{job="pm2"} | logfmt

You should see live PM2 process logs. Use filters like:

  • {job="pm2"} |= "Error" → only errors
  • {job="pm2"} |= "backoffice" → logs from a specific app