• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Server Monitoring Best Practices: Keeping Your Laravel App and Redis Clusters Alive on Linode

Server Monitoring Best Practices: Keeping Your Laravel App and Redis Clusters Alive on Linode

Establishing a Robust Monitoring Foundation with Prometheus and Grafana

For any production Laravel application, especially those leveraging Redis for caching and session management, a comprehensive monitoring strategy is non-negotiable. This isn’t about basic uptime checks; it’s about deep visibility into resource utilization, application performance, and the health of critical dependencies like Redis. We’ll focus on a Prometheus and Grafana stack, deployed on Linode, as our primary telemetry and visualization tools.

Node Exporter: System-Level Metrics for Laravel Servers

The first layer of monitoring involves gathering system-level metrics from your Linode instances. The Prometheus Node Exporter is the de facto standard for this. It exposes a wide array of hardware and OS metrics, including CPU usage, memory consumption, disk I/O, and network traffic.

Installation on a typical Ubuntu Linode:

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
sudo mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false prometheus
sudo chown prometheus:prometheus /usr/local/bin/node_exporter

Next, configure Node Exporter as a systemd service to ensure it runs automatically and can be managed easily.

[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

Save this content as /etc/systemd/system/node_exporter.service. Then, enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporter
sudo systemctl status node_exporter

By default, Node Exporter listens on port 9100. You’ll need to configure Prometheus to scrape this endpoint. In your prometheus.yml configuration file, add a scrape job:

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['YOUR_LINODE_IP_1:9100', 'YOUR_LINODE_IP_2:9100'] # Replace with your Linode IPs

Redis Exporter: Deep Dive into Redis Cluster Health

Monitoring Redis requires specific metrics beyond what Node Exporter provides. The Redis Exporter is essential for understanding Redis performance, memory usage, command latency, and cluster status. For a Redis cluster, you’ll typically run one Redis Exporter instance per Redis node, or a single instance configured to connect to your cluster.

Download and install Redis Exporter:

wget https://github.com/oliver006/redis_exporter/releases/download/v1.57.0/redis_exporter-v1.57.0.linux-amd64.tar.gz
tar xvfz redis_exporter-v1.57.0.linux-amd64.tar.gz
sudo mv redis_exporter-v1.57.0.linux-amd64/redis_exporter /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/redis_exporter

Create a systemd service for Redis Exporter. This example assumes Redis is running on the default port 6379 and is accessible locally. For a cluster, you might need to adjust the --redis.addr flag or use a sentinel configuration.

[Unit]
Description=Redis Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/redis_exporter --redis.addr=redis://localhost:6379 --namespace=redis_cluster_node1 # Adjust namespace per node

[Install]
WantedBy=multi-user.target

Save this as /etc/systemd/system/redis_exporter.service and enable/start it:

sudo systemctl daemon-reload
sudo systemctl enable redis_exporter
sudo systemctl start redis_exporter
sudo systemctl status redis_exporter

Add a scrape job to your prometheus.yml for Redis Exporter. If you have multiple Redis nodes, you’ll have multiple scrape targets, each potentially with a distinct namespace for clarity in Grafana.

scrape_configs:
  - job_name: 'redis'
    static_configs:
      - targets: ['YOUR_REDIS_NODE_IP_1:9121', 'YOUR_REDIS_NODE_IP_2:9121'] # Default port for redis_exporter

Laravel Application Metrics with Prometheus Client

To gain insight into your Laravel application’s performance, integrate the Prometheus PHP client. This allows you to expose custom metrics directly from your application, such as request counts, response times, and queue lengths.

First, install the client via Composer:

composer require promphp/prometheus_client_php

Create a metrics endpoint in your Laravel application. A common practice is to create a dedicated controller or route.

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Prometheus\CollectorRegistry;
use Prometheus\Render\RenderTextFormat;
use Prometheus\Storage\InMemory;

class MetricsController extends Controller
{
    public function index()
    {
        // Use Redis for persistence if needed, otherwise InMemory is fine for simple cases
        $adapter = new InMemory();
        $registry = new CollectorRegistry($adapter);

        // Example: Request Counter
        $counter = $registry->registerCounter(
            'app', 'requests_total', 'Total number of requests', ['method', 'uri']
        );
        // In a middleware or controller method, you'd increment this:
        // $counter->inc(['GET', '/api/users']);

        // Example: Response Time Histogram
        $histogram = $registry->registerHistogram(
            'app', 'request_duration_seconds', 'Duration of HTTP requests in seconds', ['method', 'uri']
        );
        // In a middleware or controller method, you'd observe this:
        // $startTime = microtime(true);
        // ... process request ...
        // $duration = microtime(true) - $startTime;
        // $histogram->observe($duration, ['GET', '/api/users']);

        // Example: Queue Size Gauge (requires custom logic to fetch from Redis)
        // $queueSize = $registry->registerGauge('app', 'queue_size', 'Current number of jobs in the queue');
        // $queueSize->set(Redis::llen('your_queue_name'));

        $renderer = new RenderTextFormat();
        header('Content-Type: ' . RenderTextFormat::MIME_TYPE);
        echo $renderer->render($registry->getMetricFamilySamples());
        exit;
    }
}

Register this in your routes/web.php or routes/api.php:

use App\Http\Controllers\MetricsController;

Route::get('/metrics', [MetricsController::class, 'index']);

Finally, configure Prometheus to scrape your application’s metrics endpoint:

scrape_configs:
  - job_name: 'laravel_app'
    static_configs:
      - targets: ['YOUR_LARAVEL_APP_IP:80'] # Or the specific IP/port your app is served on

Grafana Dashboards: Visualizing Your Data

Grafana is where you’ll visualize the metrics collected by Prometheus. Install Grafana on a separate server or on one of your existing Linode instances (ensure proper firewall rules).

Add Prometheus as a data source in Grafana. Navigate to Configuration -> Data Sources -> Add data source -> Prometheus. Enter the URL of your Prometheus server (e.g., http://YOUR_PROMETHEUS_IP:9090).

Import pre-built dashboards for Node Exporter and Redis Exporter. You can find excellent community dashboards on Grafana.com. Search for “Node Exporter Full” (Dashboard ID: 1860) and “Redis” (Dashboard ID: 763).

For your custom Laravel application metrics, you’ll need to create your own dashboard panels. Here are some essential queries:

Total Requests (Laravel App):

sum(rate(app_requests_total[5m])) by (method, uri)

Average Request Duration (Laravel App):

sum(rate(app_request_duration_seconds_sum[5m])) by (method, uri)
/
sum(rate(app_request_duration_seconds_count[5m])) by (method, uri)

Redis Memory Usage (per node):

redis_memory_used_bytes

Redis Command Latency (average per second):

avg(rate(redis_commands_duration_seconds_sum[5m])) by (command)
/
avg(rate(redis_commands_duration_seconds_count[5m])) by (command)

CPU Usage (per Linode):

100 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100

Alerting with Alertmanager

Effective monitoring isn’t complete without proactive alerting. Prometheus integrates with Alertmanager to handle alerts generated by Prometheus rules.

Set up Alertmanager similarly to Prometheus and Node Exporter, including a systemd service. Configure Prometheus to send alerts to Alertmanager in its prometheus.yml:

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['YOUR_ALERTMANAGER_IP:9093'] # Replace with your Alertmanager address

Define alerting rules in Prometheus. For example, to alert if a Redis node is unreachable or if CPU usage is consistently high:

groups:
- name: redis_alerts
  rules:
  - alert: RedisDown
    expr: up{job="redis"} == 0
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "Redis instance {{ $labels.instance }} is down."
      description: "Prometheus could not scrape Redis at {{ $labels.instance }} for 5 minutes."

- name: node_alerts
  rules:
  - alert: HighCpuUsage
    expr: 100 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 > 90
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "High CPU usage on {{ $labels.instance }}"
      description: "CPU usage on {{ $labels.instance }} is above 90% for 10 minutes."

Configure Alertmanager’s alertmanager.yml to define receivers (e.g., Slack, PagerDuty, email) and routing rules. This ensures critical alerts reach the right people promptly.

Linode Specific Considerations

Firewall Rules: Ensure your Linode firewall (or UFW) allows traffic on the necessary ports: Prometheus (9090), Grafana (3000), Node Exporter (9100), Redis Exporter (9121), and Alertmanager (9093). Restrict access to these ports to only trusted IP addresses (e.g., your monitoring server, your office IP).

Resource Allocation: Monitoring components themselves consume resources. For busy applications, Prometheus can become resource-intensive. Allocate sufficient CPU, RAM, and disk space to your Prometheus and Grafana instances. Consider using a dedicated Linode for your monitoring stack as your application scales.

Persistent Storage: Prometheus stores time-series data. Ensure the disk where Prometheus writes its data has enough capacity and is backed by reliable storage. For long-term retention, configure Prometheus’s remote write capabilities to send data to a long-term storage solution like Thanos or VictoriaMetrics.

Redis Cluster Topology: When monitoring a Redis cluster, ensure your Redis Exporter configuration correctly targets all master and replica nodes. If using Redis Sentinel, configure the exporter to connect via Sentinel for high availability.

By implementing this layered monitoring approach, you gain deep visibility into your Laravel application and Redis cluster’s health and performance on Linode, enabling proactive issue detection and resolution.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala