Set up comprehensive monitoring for Apache Tomcat 11 using JMX Prometheus Java agent, configure Prometheus to scrape metrics, create detailed Grafana dashboards, and implement alerting rules for performance tracking and health monitoring.
Prerequisites
- Root or sudo access
- At least 4GB RAM
- Java 11 or higher
What this solves
Apache Tomcat serves millions of Java applications but lacks built-in monitoring dashboards. This tutorial integrates Tomcat 11 with Prometheus and Grafana to provide real-time visibility into JVM memory usage, thread pools, request throughput, and application health. You'll get production-ready dashboards and alerts that help you identify performance bottlenecks before they impact users.
Step-by-step configuration
Install required packages
Update your system and install Java 11 or higher, which is required for Tomcat 11.
sudo apt update
sudo apt install -y openjdk-11-jdk wget curl
sudo dnf update -y
sudo dnf install -y java-11-openjdk-devel wget curl
Download and install Apache Tomcat 11
Create a dedicated tomcat user and download the latest Tomcat 11 release.
sudo useradd -r -m -U -d /opt/tomcat -s /bin/false tomcat
cd /tmp
wget https://archive.apache.org/dist/tomcat/tomcat-11/v11.0.0/bin/apache-tomcat-11.0.0.tar.gz
sudo tar xf apache-tomcat-11.0.0.tar.gz -C /opt/tomcat --strip-components=1
sudo chown -R tomcat:tomcat /opt/tomcat
sudo chmod +x /opt/tomcat/bin/*.sh
Download JMX Prometheus Java agent
The JMX Prometheus Java agent exports JVM metrics in Prometheus format via HTTP endpoint.
cd /opt/tomcat/lib
sudo wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.20.0/jmx_prometheus_javaagent-0.20.0.jar
sudo chown tomcat:tomcat jmx_prometheus_javaagent-0.20.0.jar
Create JMX exporter configuration
Configure which JMX metrics to export and how to transform them for Prometheus.
rules:
# JVM Memory metrics
- pattern: 'java.lang
sudo chown tomcat:tomcat /opt/tomcat/conf/jmx-exporter-config.yml
Configure Tomcat to use JMX exporter
Add the JMX Prometheus agent to Tomcat's JVM startup options.
#!/bin/bash
CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/tomcat/lib/jmx_prometheus_javaagent-0.20.0.jar=8088:/opt/tomcat/conf/jmx-exporter-config.yml"
JAVA_OPTS="$JAVA_OPTS -Xmx2048m -Xms1024m -XX:+UseG1GC"
sudo chown tomcat:tomcat /opt/tomcat/bin/setenv.sh
sudo chmod +x /opt/tomcat/bin/setenv.sh
Create systemd service for Tomcat
Configure Tomcat to start automatically and run as the tomcat user.
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
Environment="JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
RestartSec=10
Restart=always
[Install]
WantedBy=multi-user.target
Start Tomcat and verify JMX exporter
Enable and start the Tomcat service, then verify the metrics endpoint is working.
sudo systemctl daemon-reload
sudo systemctl enable --now tomcat
sudo systemctl status tomcat
curl http://localhost:8088/metrics | head -20
Install Prometheus
Download and install Prometheus to scrape metrics from Tomcat.
sudo useradd -r -M -s /bin/false prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.48.0/prometheus-2.48.0.linux-amd64.tar.gz
tar xf prometheus-2.48.0.linux-amd64.tar.gz
sudo cp prometheus-2.48.0.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-2.48.0.linux-amd64/promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
Configure Prometheus to scrape Tomcat metrics
Set up Prometheus configuration to collect metrics from the Tomcat JMX exporter.
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "tomcat_alerts.yml"
alerting:
alertmanagers:
- static_configs:
- targets: []
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'tomcat'
static_configs:
- targets: ['localhost:8088']
scrape_interval: 5s
metrics_path: '/metrics'
scrape_timeout: 5s
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml
Create Prometheus alerting rules
Define alert conditions for Tomcat performance and health monitoring.
groups:
- name: tomcat_alerts
rules:
- alert: TomcatDown
expr: up{job="tomcat"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Tomcat instance is down"
description: "Tomcat metrics endpoint has been unreachable for more than 1 minute."
- alert: TomcatHighMemoryUsage
expr: (jvm_memory_heap_bytes{area="heap"} / jvm_memory_heap_max_bytes{area="heap"}) * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "Tomcat high heap memory usage"
description: "Tomcat heap memory usage is above 85% for more than 5 minutes. Current usage: {{ $value }}%"
- alert: TomcatHighThreadUsage
expr: (tomcat_threads_busy / tomcat_threads_max) * 100 > 80
for: 3m
labels:
severity: warning
annotations:
summary: "Tomcat high thread pool usage"
description: "Tomcat thread pool usage is above 80% for connector {{ $labels.connector }}. Current usage: {{ $value }}%"
- alert: TomcatHighResponseTime
expr: rate(tomcat_processing_time_milliseconds_total[5m]) / rate(tomcat_requests_total[5m]) > 5000
for: 2m
labels:
severity: warning
annotations:
summary: "Tomcat high response time"
description: "Average response time for connector {{ $labels.connector }} is above 5 seconds: {{ $value }}ms"
- alert: TomcatHighGCTime
expr: rate(jvm_gc_collection_time_milliseconds_total[5m]) > 100
for: 3m
labels:
severity: warning
annotations:
summary: "Tomcat high garbage collection time"
description: "Garbage collection time rate is high for collector {{ $labels.gc }}: {{ $value }}ms/sec"
- alert: TomcatNoActiveThreads
expr: tomcat_threads_current - tomcat_threads_busy < 5
for: 1m
labels:
severity: critical
annotations:
summary: "Tomcat low available threads"
description: "Less than 5 threads available for connector {{ $labels.connector }}"
- alert: TomcatHighErrorRate
expr: rate(tomcat_servlet_errors_total[5m]) / rate(tomcat_requests_total[5m]) * 100 > 5
for: 2m
labels:
severity: warning
annotations:
summary: "Tomcat high error rate"
description: "Error rate is above 5% for the last 5 minutes: {{ $value }}%"
sudo chown prometheus:prometheus /etc/prometheus/tomcat_alerts.yml
Create Prometheus systemd service
Configure Prometheus to start automatically on system boot.
[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
Restart=always
[Install]
WantedBy=multi-user.target
Start Prometheus service
Enable and start Prometheus, then verify it's collecting Tomcat metrics.
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
sudo systemctl status prometheus
Install Grafana
Add Grafana repository and install the latest version for dashboard visualization.
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
sudo tee /etc/yum.repos.d/grafana.repo <
Configure Grafana datasource
Add Prometheus as a data source for Grafana dashboards.
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://localhost:9090
isDefault: true
editable: true
Create Tomcat dashboard configuration
Set up a comprehensive Grafana dashboard for Tomcat monitoring.
{
"dashboard": {
"id": null,
"title": "Apache Tomcat Performance Dashboard",
"tags": ["tomcat", "jvm", "performance"],
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "Tomcat Status",
"type": "stat",
"targets": [
{
"expr": "up{job=\"tomcat\"}",
"legendFormat": "Status"
}
],
"fieldConfig": {
"defaults": {
"mappings": [
{
"options": {
"0": {"text": "DOWN", "color": "red"},
"1": {"text": "UP", "color": "green"}
},
"type": "value"
}
],
"thresholds": {
"steps": [
{"color": "red", "value": 0},
{"color": "green", "value": 1}
]
}
}
},
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}
},
{
"id": 2,
"title": "Heap Memory Usage",
"type": "timeseries",
"targets": [
{
"expr": "jvm_memory_heap_bytes{area=\"heap\"}",
"legendFormat": "Used Heap Memory"
},
{
"expr": "jvm_memory_heap_max_bytes{area=\"heap\"}",
"legendFormat": "Max Heap Memory"
}
],
"fieldConfig": {
"defaults": {
"unit": "bytes",
"custom": {
"drawStyle": "line",
"lineInterpolation": "linear",
"barAlignment": 0,
"lineWidth": 1,
"fillOpacity": 10,
"gradientMode": "none",
"spanNulls": false,
"insertNulls": false,
"showPoints": "never",
"pointSize": 5,
"stacking": {"mode": "none", "group": "A"},
"axisPlacement": "auto",
"axisLabel": "",
"axisColorMode": "text",
"scaleDistribution": {"type": "linear"},
"axisCenteredZero": false,
"hideFrom": {"legend": false, "tooltip": false, "vis": false},
"thresholdsStyle": {"mode": "off"}
}
}
},
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}
},
{
"id": 3,
"title": "Thread Pool Usage",
"type": "timeseries",
"targets": [
{
"expr": "tomcat_threads_current",
"legendFormat": "Current Threads - {{connector}}"
},
{
"expr": "tomcat_threads_busy",
"legendFormat": "Busy Threads - {{connector}}"
},
{
"expr": "tomcat_threads_max",
"legendFormat": "Max Threads - {{connector}}"
}
],
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 8}
},
{
"id": 4,
"title": "Request Rate",
"type": "timeseries",
"targets": [
{
"expr": "rate(tomcat_requests_total[5m])",
"legendFormat": "Requests/sec - {{connector}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "reqps"
}
},
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 8}
},
{
"id": 5,
"title": "Average Response Time",
"type": "timeseries",
"targets": [
{
"expr": "rate(tomcat_processing_time_milliseconds_total[5m]) / rate(tomcat_requests_total[5m])",
"legendFormat": "Avg Response Time - {{connector}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "ms"
}
},
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 16}
},
{
"id": 6,
"title": "GC Activity",
"type": "timeseries",
"targets": [
{
"expr": "rate(jvm_gc_collection_time_milliseconds_total[5m])",
"legendFormat": "GC Time/sec - {{gc}}"
}
],
"fieldConfig": {
"defaults": {
"unit": "ms"
}
},
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 16}
}
],
"time": {
"from": "now-1h",
"to": "now"
},
"refresh": "5s",
"version": 1
}
}
Enable dashboard provisioning
Configure Grafana to automatically load the Tomcat dashboard.
apiVersion: 1
providers:
- name: 'tomcat-dashboards'
orgId: 1
folder: 'Tomcat'
type: file
disableDeletion: false
updateIntervalSeconds: 10
allowUiUpdates: true
options:
path: /etc/grafana/provisioning/dashboards
Start Grafana service
Enable and start Grafana to access the monitoring dashboard.
sudo systemctl enable --now grafana-server
sudo systemctl status grafana-server
Configure firewall rules
Allow access to Graf
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'
# Configuration
TOMCAT_VERSION="11.0.0"
PROMETHEUS_JMX_VERSION="0.20.0"
PROMETHEUS_VERSION="2.45.0"
GRAFANA_VERSION="10.0.0"
# Function to print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Usage message
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -h, --help Show this help message"
echo " --metrics-port Port for JMX metrics (default: 9090)"
echo ""
echo "Example: $0 --metrics-port 9091"
exit 1
}
# Parse arguments
METRICS_PORT=9090
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
;;
--metrics-port)
METRICS_PORT="$2"
shift 2
;;
*)
echo "Unknown option: $1"
usage
;;
esac
done
# Cleanup function
cleanup() {
print_error "Installation failed. Cleaning up..."
systemctl stop tomcat 2>/dev/null || true
systemctl stop prometheus 2>/dev/null || true
systemctl stop grafana-server 2>/dev/null || true
rm -rf /opt/tomcat /opt/prometheus /tmp/tomcat-install-*
}
trap cleanup ERR
# Check if running as root
if [[ $EUID -ne 0 ]]; then
print_error "This script must be run as root"
exit 1
fi
print_status "[1/12] Detecting distribution and package manager..."
# Auto-detect distro
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
JAVA_PACKAGE="openjdk-11-jdk"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
JAVA_PACKAGE="java-11-openjdk-devel"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
JAVA_PACKAGE="java-11-amazon-corretto-devel"
;;
*)
print_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
print_error "Cannot detect distribution"
exit 1
fi
print_status "Detected: $PRETTY_NAME using $PKG_MGR"
print_status "[2/12] Updating system packages..."
$PKG_UPDATE
print_status "[3/12] Installing required packages..."
$PKG_INSTALL $JAVA_PACKAGE wget curl tar
print_status "[4/12] Creating tomcat user..."
if ! id tomcat &>/dev/null; then
useradd -r -m -U -d /opt/tomcat -s /bin/false tomcat
fi
print_status "[5/12] Downloading and installing Apache Tomcat $TOMCAT_VERSION..."
cd /tmp
TOMCAT_TARBALL="apache-tomcat-${TOMCAT_VERSION}.tar.gz"
if [ ! -f "$TOMCAT_TARBALL" ]; then
wget "https://archive.apache.org/dist/tomcat/tomcat-11/v${TOMCAT_VERSION}/bin/${TOMCAT_TARBALL}"
fi
mkdir -p /opt/tomcat
tar xf "$TOMCAT_TARBALL" -C /opt/tomcat --strip-components=1
chown -R tomcat:tomcat /opt/tomcat
chmod +x /opt/tomcat/bin/*.sh
print_status "[6/12] Downloading JMX Prometheus Java agent..."
cd /opt/tomcat/lib
wget -O jmx_prometheus_javaagent-${PROMETHEUS_JMX_VERSION}.jar \
"https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/${PROMETHEUS_JMX_VERSION}/jmx_prometheus_javaagent-${PROMETHEUS_JMX_VERSION}.jar"
chown tomcat:tomcat jmx_prometheus_javaagent-${PROMETHEUS_JMX_VERSION}.jar
print_status "[7/12] Creating JMX exporter configuration..."
cat > /opt/tomcat/conf/jmx-config.yml << 'EOF'
rules:
# JVM Memory metrics
- pattern: 'java.lang<type=Memory><HeapMemoryUsage>(\w+)'
name: jvm_memory_heap_bytes
type: GAUGE
labels:
area: "heap"
type: "$1"
# Thread metrics
- pattern: 'java.lang<type=Threading><>ThreadCount'
name: jvm_threads_current
type: GAUGE
# GC metrics
- pattern: 'java.lang<type=GarbageCollector, name=(\w+)><>CollectionCount'
name: jvm_gc_collections_total
type: COUNTER
labels:
gc: "$1"
# Tomcat connector metrics
- pattern: 'Catalina<type=ThreadPool, name="([^"]+)"><>currentThreadCount'
name: tomcat_threads_current
type: GAUGE
labels:
connector: "$1"
- pattern: 'Catalina<type=GlobalRequestProcessor, name="([^"]+)"><>requestCount'
name: tomcat_requests_total
type: COUNTER
labels:
connector: "$1"
EOF
chown tomcat:tomcat /opt/tomcat/conf/jmx-config.yml
chmod 644 /opt/tomcat/conf/jmx-config.yml
print_status "[8/12] Configuring Tomcat with JMX agent..."
cat > /opt/tomcat/bin/setenv.sh << EOF
CATALINA_OPTS="\$CATALINA_OPTS -javaagent:/opt/tomcat/lib/jmx_prometheus_javaagent-${PROMETHEUS_JMX_VERSION}.jar=${METRICS_PORT}:/opt/tomcat/conf/jmx-config.yml"
CATALINA_OPTS="\$CATALINA_OPTS -Dcom.sun.management.jmxremote"
CATALINA_OPTS="\$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=9999"
CATALINA_OPTS="\$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
CATALINA_OPTS="\$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
EOF
chown tomcat:tomcat /opt/tomcat/bin/setenv.sh
chmod 755 /opt/tomcat/bin/setenv.sh
print_status "[9/12] Creating Tomcat systemd service..."
cat > /etc/systemd/system/tomcat.service << EOF
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk
Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
Environment='CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC'
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom'
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
User=tomcat
Group=tomcat
UMask=0007
RestartSec=10
Restart=always
[Install]
WantedBy=multi-user.target
EOF
print_status "[10/12] Installing Prometheus..."
cd /tmp
PROMETHEUS_TARBALL="prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz"
if [ ! -f "$PROMETHEUS_TARBALL" ]; then
wget "https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/${PROMETHEUS_TARBALL}"
fi
useradd -r -s /bin/false prometheus 2>/dev/null || true
mkdir -p /opt/prometheus /var/lib/prometheus
tar xf "$PROMETHEUS_TARBALL" -C /opt/prometheus --strip-components=1
chown -R prometheus:prometheus /opt/prometheus /var/lib/prometheus
print_status "[11/12] Configuring Prometheus..."
cat > /opt/prometheus/prometheus.yml << EOF
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'tomcat'
static_configs:
- targets: ['localhost:${METRICS_PORT}']
scrape_interval: 5s
metrics_path: /metrics
EOF
chown prometheus:prometheus /opt/prometheus/prometheus.yml
# Create Prometheus systemd service
cat > /etc/systemd/system/prometheus.service << EOF
[Unit]
Description=Prometheus
After=network.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/opt/prometheus/prometheus --config.file=/opt/prometheus/prometheus.yml --storage.tsdb.path=/var/lib/prometheus --web.console.templates=/opt/prometheus/consoles --web.console.libraries=/opt/prometheus/console_libraries --web.listen-address=0.0.0.0:9091
[Install]
WantedBy=multi-user.target
EOF
print_status "[12/12] Installing Grafana..."
case "$ID" in
ubuntu|debian)
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
apt install -y grafana
;;
*)
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
;;
esac
# Configure firewall
if command -v firewall-cmd &> /dev/null; then
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --add-port=${METRICS_PORT}/tcp
firewall-cmd --permanent --add-port=9091/tcp
firewall-cmd --permanent --add-port=3000/tcp
firewall-cmd --reload
elif command -v ufw &> /dev/null; then
ufw allow 8080/tcp
ufw allow ${METRICS_PORT}/tcp
ufw allow 9091/tcp
ufw allow 3000/tcp
fi
# Start services
systemctl daemon-reload
systemctl enable tomcat prometheus grafana-server
systemctl start tomcat
sleep 5
systemctl start prometheus
systemctl start grafana-server
print_status "Installation completed successfully!"
print_status "Services:"
print_status " Tomcat: http://localhost:8080"
print_status " Tomcat Metrics: http://localhost:${METRICS_PORT}/metrics"
print_status " Prometheus: http://localhost:9091"
print_status " Grafana: http://localhost:3000 (admin/admin)"
print_warning "Please change the default Grafana password on first login"
# Verification
sleep 10
if curl -s http://localhost:${METRICS_PORT}/metrics > /dev/null; then
print_status "✓ Tomcat metrics endpoint is responding"
else
print_error "✗ Tomcat metrics endpoint is not responding"
fi
if curl -s http://localhost:9091/-/healthy > /dev/null; then
print_status "✓ Prometheus is healthy"
else
print_error "✗ Prometheus is not responding"
fi
if curl -s http://localhost:3000/api/health > /dev/null; then
print_status "✓ Grafana is responding"
else
print_error "✗ Grafana is not responding"
fi
Review the script before running. Execute with: bash install.sh