Server Monitoring Best Practices: Keeping Your Laravel App and MongoDB Clusters Alive on Linode
Establishing a Robust Monitoring Foundation with Linode and Prometheus
Maintaining the health and performance of a Laravel application, especially when backed by a MongoDB cluster, requires a proactive and multi-layered monitoring strategy. On Linode, this often translates to leveraging a combination of system-level metrics, application-specific insights, and database cluster health. Prometheus, with its powerful time-series data collection and alerting capabilities, forms an excellent backbone for this. We’ll focus on setting up Prometheus to scrape key metrics from your Laravel application instances and MongoDB nodes.
Deploying Prometheus and Node Exporter on Linode Instances
The first step is to deploy Prometheus itself and the Node Exporter on each Linode instance that hosts either your Laravel application or MongoDB. Node Exporter provides a comprehensive set of hardware and OS metrics.
Prometheus Installation
We’ll install Prometheus directly on a dedicated Linode instance or one of your application servers. For simplicity, we’ll use binary downloads.
Download and Extract Prometheus
Fetch the latest stable release. Always check the official Prometheus releases page for the most current version.
wget https://github.com/prometheus-community/prometheus/releases/download/v2.48.0/prometheus-2.48.0.linux-amd64.tar.gz tar xvfz prometheus-2.48.0.linux-amd64.tar.gz cd prometheus-2.48.0.linux-amd64
Configure Prometheus
The core configuration is in prometheus.yml. We need to define scrape targets for Node Exporter and potentially the Laravel application itself (using a custom exporter or Blackbox Exporter).
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
evaluation_interval: 15s # By default, run rules every 15 seconds.
scrape_configs:
# Scrape Prometheus itself
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# Scrape Node Exporter on all application and database servers
- job_name: 'node_exporter'
static_configs:
- targets:
- '192.168.1.10:9100' # Replace with your Linode IPs
- '192.168.1.11:9100'
- '192.168.1.12:9100'
- '192.168.1.13:9100' # MongoDB node 1
- '192.168.1.14:9100' # MongoDB node 2
- '192.168.1.15:9100' # MongoDB node 3
# Example: Scrape MongoDB exporter (if deployed)
- job_name: 'mongodb_exporter'
static_configs:
- targets:
- '192.168.1.13:9274' # Assuming MongoDB exporter on port 9274
- '192.168.1.14:9274'
- '192.168.1.15:9274'
# Example: Scrape Laravel application metrics via Blackbox Exporter
- job_name: 'laravel_app_http'
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- http://your-laravel-app.com:80
- https://your-laravel-app.com:443
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
regex: (https?://)(.*)
target_label: __address__
replacement: blackbox_exporter_ip:9115 # Replace with your Blackbox Exporter IP and port
- target_label: __param_module
regex: .*
replacement: http_2xx # Or other modules like tcp_connect, dns, etc.
Run Prometheus
Start Prometheus. For production, you’ll want to set this up as a systemd service.
./prometheus --config.file=prometheus.yml
Node Exporter Installation
Install Node Exporter on every Linode instance you want to monitor system metrics from.
Download and Extract Node Exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz tar xvfz node_exporter-1.7.0.linux-amd64.tar.gz cd node_exporter-1.7.0.linux-amd64
Run Node Exporter
Node Exporter typically runs on port 9100. Again, for production, use systemd.
./node_exporter
Monitoring MongoDB Clusters with Prometheus
Monitoring a MongoDB replica set or sharded cluster requires specific exporters that can query MongoDB’s internal metrics. The most common and effective is the mongodb_exporter.
Deploying MongoDB Exporter
You can deploy the MongoDB Exporter on a dedicated Linode instance or on one of your MongoDB nodes. It needs to connect to your MongoDB instances.
Installation (Docker Example)
Using Docker simplifies deployment and dependency management. Ensure your MongoDB instances are accessible from where you run the exporter.
docker run -d --name mongodb_exporter \ --network="host" \ -e "MONGODB_URI=mongodb://user:password@mongodb-node-1:27017,mongodb-node-2:27017,mongodb-node-3:27017/?replicaSet=rs0" \ prom/mongodb-exporter:latest
Note: Replace user, password, and the MongoDB node addresses with your actual credentials and cluster configuration. The --network="host" option is convenient but consider network segmentation for production. If not using host network, ensure the exporter can reach MongoDB on its port (default 27017).
Configuration for Prometheus
Add the MongoDB Exporter to your prometheus.yml as shown in the Prometheus installation section. Ensure the IP address and port (default 9274) are correct.
Application-Level Monitoring for Laravel
Monitoring the Laravel application itself goes beyond system metrics. We need to track request latency, error rates, queue lengths, and more. There are several approaches:
1. Blackbox Exporter for HTTP/S Probes
This is a simple way to check if your Laravel application is reachable and responding with expected status codes. It doesn’t provide deep application insights but is crucial for uptime monitoring.
Deployment and Configuration
Deploy the Blackbox Exporter similarly to Node Exporter. Configure Prometheus to scrape it, targeting your Laravel application’s URL. The example in the Prometheus configuration section demonstrates this.
2. Custom Metrics with Prometheus Client Libraries
For granular application metrics, integrate a Prometheus client library into your Laravel application. The php-prometheus-client is a good choice.
Installation
composer require prometheusclient/prometheus_client
Implementation Example
Create a route that exposes metrics, typically under an endpoint like /metrics. This route will collect and render metrics.
use Prometheus\CollectorRegistry;
use Prometheus\Render\RenderTextFormat;
use Prometheus\Storage\InMemory; // Or Redis, APCu for production
// Initialize registry and storage
$registry = new CollectorRegistry(new InMemory()); // Use Redis for production
// Example: Counter for total requests
$counter = $registry->registerCounter('laravel_requests_total', 'Total number of requests', ['method', 'endpoint']);
// Example: Gauge for current active users (simplified)
$gauge = $registry->registerGauge('laravel_active_users', 'Number of currently active users');
// Example: Histogram for request duration
$histogram = $registry->registerHistogram('laravel_request_duration_seconds', 'Request duration in seconds', ['method', 'endpoint']);
// --- In your middleware or controller ---
// Increment total requests counter
$method = request()->method();
$endpoint = request()->path(); // Or a more specific route name
$counter->incBy(1, [$method, $endpoint]);
// Update active users gauge (e.g., based on session data)
// $gauge->set(count(Session::all()), []); // Simplified
// Measure request duration
$startTime = microtime(true);
// ... your application logic ...
$duration = microtime(true) - $startTime;
$histogram->observe($duration, [$method, $endpoint]);
// --- Route definition (e.g., in routes/web.php or routes/api.php) ---
use Illuminate\Support\Facades\Route;
use Prometheus\CollectorRegistry;
use Prometheus\Render\RenderTextFormat;
use Prometheus\Storage\InMemory; // Or Redis
Route::get('/metrics', function () use ($registry) {
$renderer = new RenderTextFormat();
header('Content-Type: ' . RenderTextFormat::MIME_TYPE);
echo $renderer->render($registry->getMetricFamilySamples());
exit;
});
Production Storage: For production, replace InMemory with a persistent storage adapter like Redis (Prometheus\Storage\Redis) to avoid losing metrics across application restarts and to allow multiple application instances to share metrics.
Prometheus Configuration for Custom Metrics
Add a scrape job to your prometheus.yml to collect metrics from your Laravel application’s /metrics endpoint.
- job_name: 'laravel_app_metrics'
static_configs:
- targets: ['your-laravel-app-ip:80'] # Or the IP of the Linode running your app
metrics_path: /metrics
Alerting with Alertmanager
Collecting metrics is only half the battle; you need to be notified when things go wrong. Alertmanager handles alerts sent by Prometheus.
Deployment and Configuration
Deploy Alertmanager similarly to Prometheus. Its configuration defines how alerts are grouped, routed, and sent to receivers (e.g., email, Slack, PagerDuty).
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'default-receiver' # Default receiver
receivers:
- name: 'default-receiver'
slack_configs:
- api_url: 'YOUR_SLACK_WEBHOOK_URL'
channel: '#alerts'
send_resolved: true
- name: 'critical-receiver'
email_configs:
- to: '[email protected]'
send_resolved: true
inhibit_rules:
- target_match:
severity: 'critical'
equal: ['alertname', 'cluster', 'service']
# Define specific routes for different services or severities
# routes:
# - receiver: 'critical-receiver'
# matchers:
# - severity="critical"
# continue: true
Prometheus Configuration for Alertmanager
Tell Prometheus where to send alerts.
alerting:
alertmanagers:
- static_configs:
- targets:
- 'alertmanager-ip:9093' # Replace with your Alertmanager IP and port
Example Alerting Rules
Create rule files (e.g., rules.yml) and point Prometheus to them.
groups:
- name: node_alerts
rules:
- alert: HighCpuLoad
expr: node_load1 > 5
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU load on {{ $labels.instance }}"
description: "Node {{ $labels.instance }} has a load average of {{ $value }} for more than 5 minutes."
- alert: LowDiskSpace
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
for: 10m
labels:
severity: critical
annotations:
summary: "Low disk space on {{ $labels.instance }}"
description: "Node {{ $labels.instance }} has less than 10% disk space remaining on /."
- name: mongodb_alerts
rules:
- alert: MongoDBReplicaSetDown
expr: mongodb_up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "MongoDB replica set member down on {{ $labels.instance }}"
description: "MongoDB instance {{ $labels.instance }} is reporting as down."
- alert: HighMongoDBConnections
expr: mongodb_connections_current > 500 # Adjust threshold based on your setup
for: 5m
labels:
severity: warning
annotations:
summary: "High MongoDB connection count on {{ $labels.instance }}"
description: "MongoDB instance {{ $labels.instance }} has {{ $value }} current connections."
- name: laravel_alerts
rules:
- alert: LaravelAppUnreachable
expr: probe_success{job="laravel_app_http"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Laravel application is unreachable"
description: "The Laravel application at {{ $labels.instance }} is not responding correctly."
- alert: HighLaravelRequestLatency
expr: histogram_quantile(0.95, sum(rate(laravel_request_duration_seconds_bucket[5m])) by (le, endpoint, method)) > 2 # 95th percentile latency > 2 seconds
for: 5m
labels:
severity: warning
annotations:
summary: "High Laravel request latency for {{ $labels.endpoint }}"
description: "95th percentile request latency for {{ $labels.method }} {{ $labels.endpoint }} is {{ $value }}s."
Grafana for Visualization
While Prometheus provides the data and Alertmanager handles notifications, Grafana is essential for visualizing this data and gaining actionable insights.
Setup and Configuration
Install Grafana on a Linode instance. Add Prometheus as a data source. You can then import pre-built dashboards for Node Exporter, MongoDB, and even create custom ones for your Laravel application metrics.
Adding Prometheus Data Source
In Grafana, navigate to Configuration -> Data Sources -> Add data source. Select Prometheus and enter the URL of your Prometheus server (e.g., http://your-prometheus-ip:9090).
Importing Dashboards
Grafana.com hosts a vast library of community dashboards. Search for “Node Exporter Full” (ID: 1860), “MongoDB” (ID: 742), and others relevant to your stack. Import them and select your Prometheus data source.
Conclusion: A Proactive Monitoring Stack
By combining Prometheus for metric collection, Node Exporter for system health, MongoDB Exporter for database cluster status, Blackbox Exporter and custom metrics for application reachability and performance, Alertmanager for notifications, and Grafana for visualization, you establish a comprehensive and proactive monitoring strategy. This stack provides the visibility needed to keep your Laravel applications and MongoDB clusters on Linode running smoothly and to quickly address any issues before they impact your users.