• 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 Magento 2 App and Elasticsearch Clusters Alive on DigitalOcean

Server Monitoring Best Practices: Keeping Your Magento 2 App and Elasticsearch Clusters Alive on DigitalOcean

Essential Metrics for Magento 2 and Elasticsearch on DigitalOcean

Maintaining a high-performance Magento 2 e-commerce platform, especially when leveraging Elasticsearch for search, demands a granular understanding of underlying infrastructure health. On DigitalOcean, this translates to monitoring not just CPU and RAM, but also specific application and service-level indicators. For Magento 2, key metrics include PHP-FPM process count, request latency, error rates, and cache hit ratios. For Elasticsearch, critical indicators are JVM heap usage, indexing throughput, search latency, shard status, and disk I/O. Neglecting any of these can lead to cascading failures, impacting user experience and revenue.

Proactive PHP-FPM Monitoring for Magento 2

PHP-FPM is the workhorse for Magento 2. Overloaded FPM pools or insufficient worker processes directly translate to slow page loads and timeouts. We’ll use `pm.status_path` to expose FPM’s internal metrics and scrape them with Prometheus.

First, ensure your PHP-FPM configuration (typically in /etc/php/X.Y/fpm/pool.d/www.conf) has the status page enabled:

; Ensure this is uncommented and accessible
pm.status_path = /fpm_status

; For security, consider restricting access to localhost or a specific monitoring IP
; listen.acl_users = www-data, nginx
; listen.acl_groups = www-data
; listen.owner = www-data
; listen.group = www-data
; listen.mode = 0660

Next, configure Nginx to proxy requests to this status page. This is crucial if your FPM socket isn’t directly accessible from your monitoring agent’s network.

# In your Magento 2 Nginx site configuration
location ~ ^/fpm_status$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/phpX.Y-fpm.sock; # Adjust to your PHP-FPM socket path
    internal; # Only allow internal access
}

# For Prometheus to scrape, you might need a separate location or adjust access controls
# Example for Prometheus scraping (assuming Prometheus is on a trusted network)
location /fpm_status {
    allow 192.168.1.0/24; # Replace with your Prometheus server's IP/subnet
    deny all;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/phpX.Y-fpm.sock; # Adjust to your PHP-FPM socket path
}

With Prometheus configured to scrape http://your-magento-server-ip/fpm_status, you can then use the php_fpm_exporter (or similar) to parse these metrics. Key Prometheus metrics to alert on include:

  • php_fpm_process_active: Number of active PHP-FPM processes. Alert if consistently high, indicating potential bottlenecks.
  • php_fpm_process_idle: Number of idle PHP-FPM processes. Alert if consistently low, suggesting insufficient pool size.
  • php_fpm_request_duration_seconds_sum and php_fpm_request_duration_seconds_count: To calculate average request latency.
  • php_fpm_accepted_connections: Rate of new connections.

Elasticsearch Cluster Health and Performance

Elasticsearch performance is paramount for search functionality. We’ll use the official elasticsearch_exporter for Prometheus to gather vital statistics.

First, deploy the elasticsearch_exporter on a node that can reach your Elasticsearch cluster. Configure it to connect to your Elasticsearch instance. A common setup involves running it as a systemd service.

# Download and install the exporter
wget https://github.com/prometheus-community/elasticsearch_exporter/releases/download/vX.Y.Z/elasticsearch_exporter-X.Y.Z.linux-amd64.tar.gz
tar xvfz elasticsearch_exporter-X.Y.Z.linux-amd64.tar.gz
sudo mv elasticsearch_exporter-X.Y.Z.linux-amd64/elasticsearch_exporter /usr/local/bin/

# Create a systemd service file
sudo nano /etc/systemd/system/elasticsearch_exporter.service
[Unit]
Description=Prometheus Elasticsearch Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus # Create a dedicated user if needed
Group=prometheus
ExecStart=/usr/local/bin/elasticsearch_exporter \
  --es.uri=http://localhost:9200 \ # Adjust if Elasticsearch is on another node
  --es.timeout=5m \
  --web.listen-address=":9114" \
  --es.indices=magento* # Monitor only Magento-related indices

[Install]
WantedBy=multi-user.target

Start and enable the service:

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

Add the exporter to your Prometheus configuration (prometheus.yml):

scrape_configs:
  - job_name: 'elasticsearch'
    static_configs:
      - targets: ['localhost:9114'] # Or the IP of the exporter host

Critical Elasticsearch metrics to monitor and alert on:

  • elasticsearch_jvm_memory_used_bytes and elasticsearch_jvm_memory_max_bytes: Monitor JVM heap usage. Alert if it exceeds 80-90% of max.
  • elasticsearch_indices_indexing_total: Rate of indexing operations. Sudden drops can indicate issues.
  • elasticsearch_search_request_total: Rate of search requests.
  • elasticsearch_cluster_health_status: Should always be 0 (green). Alert on 1 (yellow) or 2 (red).
  • elasticsearch_nodes_count: Ensure all expected nodes are present.
  • elasticsearch_shard_stats_unassigned_shards: Should always be 0.
  • elasticsearch_thread_pool_search_rejected and elasticsearch_thread_pool_index_rejected: High rejection rates indicate overloaded thread pools.

DigitalOcean Droplet Resource Monitoring

While application-specific metrics are key, fundamental Droplet resource utilization cannot be ignored. We’ll use the standard node_exporter for system-level metrics.

Deploying node_exporter is straightforward. Download the latest release, extract it, and run it. A systemd service is recommended for production.

# Download and install
wget https://github.com/prometheus-nodeexporter/nodeexporter/releases/download/vX.Y.Z/node_exporter-X.Y.Z.linux-amd64.tar.gz
tar xvfz node_exporter-X.Y.Z.linux-amd64.tar.gz
sudo mv node_exporter-X.Y.Z.linux-amd64/node_exporter /usr/local/bin/

# Create systemd service
sudo nano /etc/systemd/system/node_exporter.service
[Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus # Or a dedicated user
Group=prometheus
ExecStart=/usr/local/bin/node_exporter \
  --collector.diskstats \
  --collector.filesystem \
  --collector.loadavg \
  --collector.meminfo \
  --collector.netdev \
  --collector.stat \
  --collector.time \
  --web.listen-address=":9100"

[Install]
WantedBy=multi-user.target

Start and enable the service:

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

Configure Prometheus to scrape your Droplets:

scrape_configs:
  - job_name: 'node_exporter'
    static_configs:
      - targets: ['droplet1_ip:9100', 'droplet2_ip:9100', ...] # List all your Droplet IPs

Essential Droplet metrics for alerting:

  • node_cpu_seconds_total: Monitor CPU utilization (e.g., `100 – avg by (instance) (rate(node_cpu_seconds_total{mode=”idle”}[5m])) * 100`). Alert on sustained high CPU (>90%).
  • node_memory_MemAvailable_bytes: Available memory. Alert if critically low (e.g., less than 500MB).
  • node_filesystem_avail_bytes: Filesystem free space. Alert on low disk space (e.g., <10% free).
  • node_network_receive_errs_total and node_network_transmit_errs_total: Network errors. Any increase is suspicious.
  • node_load1, node_load5, node_load15: System load average. Compare against the number of CPU cores.

Alerting Strategy with Alertmanager

Collecting metrics is only half the battle; actionable alerts are crucial. Prometheus integrates with Alertmanager to deduplicate, group, and route alerts to appropriate channels (Slack, PagerDuty, email).

A basic Alertmanager configuration (alertmanager.yml) might look like this:

global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'job']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'default-receiver'

receivers:
  - name: 'default-receiver'
    slack_configs:
      - api_url: ''
        channel: '#alerts'
        send_resolved: true

# Example specific route for critical Elasticsearch alerts
# routes:
#   - receiver: 'critical-pager'
#     matchers:
#       - severity="critical"
#       - job="elasticsearch"
#     continue: true # Allows further routing if needed

# Define your alert rules in Prometheus's rule files (e.g., rules.yml)
# Example rule:
# - alert: HighElasticsearchHeapUsage
#   expr: |
#     (elasticsearch_jvm_memory_used_bytes / elasticsearch_jvm_memory_max_bytes) * 100 > 85
#   for: 5m
#   labels:
#     severity: warning
#   annotations:
#     summary: "Elasticsearch JVM heap usage is high on {{ $labels.instance }}"
#     description: "Elasticsearch JVM heap usage is {{ $value | printf \"%.2f\" }}% on {{ $labels.instance }}, exceeding the 85% threshold."

Deploy Alertmanager as a service and configure Prometheus to send alerts to it.

# In prometheus.yml
alerting:
  alertmanagers:
    - static_configs:
        - targets: ['alertmanager_ip:9093'] # Address of your Alertmanager instance

Log Aggregation and Analysis

While metrics provide a high-level view, logs are essential for deep-diving into issues. A centralized logging solution like Loki, paired with Promtail for log collection and Grafana for visualization, is a powerful combination.

Configure Promtail on each Droplet to tail Magento, PHP-FPM, Nginx, and Elasticsearch logs, forwarding them to your Loki instance. Use labels effectively to filter and query logs by instance, application, etc.

# Example promtail-local-config.yaml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://your-loki-ip:3100/loki/api/v1/push

scrape_configs:
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: varlogs
          host: {{ .Node.Hostname }} # Dynamically add hostname
    pipeline_stages:
      - match:
          selector: '{job="varlogs"}'
          stages:
            - regex:
                expression: "^(?P<time>\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) (?P<level>\\w+) (?P<message>.*)$"
            - timestamp:
                source: time
                format: "2006-01-02 15:04:05"
            - labels:
                level:

  - job_name: nginx-magento
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx
          host: {{ .Node.Hostname }}
    pipeline_stages:
      - match:
          selector: '{job="nginx"}'
          stages:
            - regex:
                expression: "^(?P<ip>\\S+) \\S+ \\S+ \\[(?P<time>.*?)\\] \\\"(?P<method>\\S+) (?P<path>\\S+) (?P<protocol>\\S+)\\\" (?P<status>\\d{3}) (?P<size>\\d+|-).*$"
            - timestamp:
                source: time
                format: "DD/Mon/YYYY:HH:MM:SS +0000" # Adjust timezone if needed
            - labels:
                status:
                method:
                path:

  - job_name: php-fpm-magento
    static_configs:
      - targets:
          - localhost
        labels:
          job: php-fpm
          host: {{ .Node.Hostname }}
    pipeline_stages:
      - match:
          selector: '{job="php-fpm"}'
          stages:
            - regex:
                expression: "^(?P<time>\\d{2}/[A-Za-z]{3}/\\d{4}:\\d{2}:\\d{2}:\\d{2}) (?P<level>\\w+) \\[(?P<pid>\\d+):(?P<tid>\\d+)\\] \\d+\\.\\d+ \\d+\\.\\d+ \\\"(?P<request>.*?)\\\" (?P<status>\\d+) (?P<duration>\\d+)$"
            - timestamp:
                source: time
                format: "02/Jan/2006:15:04:05 -0700" # Adjust timezone
            - labels:
                pid:
                tid:
                status:
                request:

  - job_name: elasticsearch-magento
    static_configs:
      - targets:
          - localhost
        labels:
          job: elasticsearch
          host: {{ .Node.Hostname }}
    pipeline_stages:
      - match:
          selector: '{job="elasticsearch"}'
          stages:
            - json:
                expressions:
                  message:
                  level:
                  timestamp:
            - timestamp:
                source: timestamp
                format: RFC3339Nano # Adjust based on Elasticsearch log format

In Grafana, create dashboards that query Loki using LogQL. Filter for specific error codes (e.g., Nginx 5xx, PHP errors), trace requests across services, and correlate log events with metric spikes.

Automated Deployments and Configuration Management

Manual configuration is error-prone. Tools like Ansible, Chef, or Puppet are essential for automating the deployment and configuration of these monitoring agents and services across your DigitalOcean Droplets. This ensures consistency and reduces the operational burden.

For instance, an Ansible playbook can install Prometheus, node_exporter, elasticsearch_exporter, Promtail, and configure their respective systemd services and Prometheus scrape targets. This drastically simplifies onboarding new servers and maintaining a uniform monitoring stack.

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