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

Vengala Vinay

Having 9+ Years of Experience in Software Development

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

Server Monitoring Best Practices: Keeping Your Ruby App and MySQL Clusters Alive on Linode

Proactive MySQL Cluster Health Checks with `pt-heartbeat`

Maintaining the health and replication status of MySQL clusters, especially in a distributed environment like Linode, is paramount. Manual checks are error-prone and time-consuming. The Percona Toolkit offers a robust solution with `pt-heartbeat`, a tool designed to monitor replication lag by writing timestamps to a dedicated table and comparing them across replicas.

First, ensure Percona Toolkit is installed on all your MySQL nodes. On Debian/Ubuntu systems, this is typically:

sudo apt-get update
sudo apt-get install percona-toolkit

Next, create a dedicated database and table on your MySQL primary (and ensure it’s replicated to all secondaries) to store the heartbeat information. This table should be replicated to ensure consistency.

-- On your MySQL primary
CREATE DATABASE IF NOT EXISTS heartbeat;
USE heartbeat;
CREATE TABLE IF NOT EXISTS ping (
  id INT AUTO_INCREMENT PRIMARY KEY,
  server_id INT UNSIGNED NOT NULL,
  ts DATETIME(6) NOT NULL
) ENGINE=InnoDB;

Now, configure `pt-heartbeat` to run periodically on your primary node. This script will write a new timestamp to the `heartbeat.ping` table. The frequency should be tuned to your replication requirements; every 10-30 seconds is a common starting point.

# On your MySQL primary node
pt-heartbeat --host=127.0.0.1 --port=3306 --user=your_monitor_user --password=your_monitor_password --database=heartbeat --table=ping --update-primary

Replace your_monitor_user and your_monitor_password with credentials for a user that has `INSERT`, `UPDATE`, and `SELECT` privileges on the `heartbeat.ping` table. The --update-primary flag is crucial for this setup.

On each of your MySQL replicas, you’ll run `pt-heartbeat` to check the lag against the primary. This command will output the replication lag in seconds. You can then pipe this output to a monitoring system (like Prometheus, Nagios, or simply log it).

# On each MySQL replica node
pt-heartbeat --host=127.0.0.1 --port=3306 --user=your_monitor_user --password=your_monitor_password --database=heartbeat --table=ping --monitor

To automate this, create a systemd service or a cron job for the replica check. For example, a cron job entry to run every minute:

# In crontab for the user running the check
* * * * * pt-heartbeat --host=127.0.0.1 --port=3306 --user=your_monitor_user --password=your_monitor_password --database=heartbeat --table=ping --monitor >> /var/log/pt-heartbeat.log 2>&1

You can then set up alerts based on the lag reported in the log file or by integrating with a time-series database and alerting engine. A lag exceeding a predefined threshold (e.g., 60 seconds) should trigger an alert.

Ruby Application Performance Monitoring with New Relic

For Ruby applications hosted on Linode, comprehensive performance monitoring is essential for identifying bottlenecks, errors, and slow transactions. New Relic is a powerful Application Performance Monitoring (APM) solution that provides deep insights into your application’s behavior.

The first step is to install the New Relic Ruby agent. This is typically done by adding the `newrelic_rpm` gem to your application’s `Gemfile`.

# Gemfile
gem 'newrelic_rpm'

After adding the gem, run `bundle install`.

Next, you need to configure the agent. Create a `newrelic.yml` file in the root of your application. You’ll need your New Relic license key, which can be found in your New Relic account settings.

# newrelic.yml
common: &common
  license_key: YOUR_NEW_RELIC_LICENSE_KEY
  app_name: YourAppName

development:
  <<: *common

production:
  <<: *common
  # You can override settings for production here if needed
  # For example, to disable SSL verification (not recommended for production):
  # ssl: false

Ensure your Linode server has the correct environment variables set for New Relic to pick up the configuration. For a typical Rails application, this might involve setting the `RAILS_ENV` variable.

To ensure the agent is loaded correctly, you might need to modify your application's entry point. For Rails, this is often done in `config/application.rb` or `config/boot.rb`.

# config/application.rb (or similar)
require 'newrelic_rpm'

Once deployed, New Relic will automatically start collecting data on your Ruby application's performance, including:

  • Transaction traces: Identifying slow database queries, external service calls, and Ruby code execution.
  • Error reporting: Capturing and categorizing exceptions.
  • Throughput and response time metrics.
  • Database monitoring: Performance of your MySQL queries.
  • Background job monitoring.

You can then set up alerts within the New Relic UI for critical metrics like high error rates, slow response times, or excessive database query times. For example, an alert could be configured to fire if the average response time for a critical endpoint exceeds 500ms for 5 minutes.

System-Level Monitoring with Prometheus and Node Exporter

While APM tools like New Relic are excellent for application-level insights, robust system-level monitoring is crucial for understanding the underlying infrastructure health on your Linode servers. Prometheus, combined with Node Exporter, provides a powerful and flexible solution for collecting and querying system metrics.

First, set up a Prometheus server. This can be a dedicated Linode instance or a container. The easiest way to get started is often with Docker.

# prometheus.yml (basic configuration)
global:
  scrape_interval: 15s # How often to scrape targets

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node'
    static_configs:
      - targets: ['your_linode_ip_1:9100', 'your_linode_ip_2:9100'] # Replace with your Linode IPs

On each Linode server that hosts your Ruby app or MySQL cluster, install and run Node Exporter. This exposes a wide range of hardware and OS metrics.

# On each Linode server
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
sudo mv node_exporter /usr/local/bin/
sudo groupadd --system node_exporter
sudo useradd --system -g node_exporter node_exporter

# Create a systemd service file
sudo tee /etc/systemd/system/node_exporter.service <<EOF
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target
EOF

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

Ensure that port 9100 is open in your Linode firewall for incoming connections from your Prometheus server. After starting Node Exporter, you should be able to access its metrics endpoint at http://your_linode_ip:9100/metrics.

Configure your Prometheus server to scrape these Node Exporter instances by adding them to the `prometheus.yml` file as shown above. Restart Prometheus for the changes to take effect.

With Prometheus collecting metrics, you can use Grafana for visualization and alerting. Key metrics to monitor include:

  • CPU Usage (node_cpu_seconds_total)
  • Memory Usage (node_memory_MemAvailable_bytes, node_memory_MemTotal_bytes)
  • Disk I/O (node_disk_io_time_seconds_total)
  • Network Traffic (node_network_receive_bytes_total, node_network_transmit_bytes_total)
  • System Load (node_load1, node_load5, node_load15)

For MySQL, you can use the mysqld_exporter, which works similarly to Node Exporter but targets MySQL metrics. Configure Prometheus to scrape this exporter as well. Alerts can be set up in Prometheus's Alertmanager or within Grafana based on thresholds for these metrics. For instance, an alert could trigger if CPU usage consistently exceeds 90% for more than 10 minutes, or if available memory drops below 5%.

Log Aggregation and Analysis with ELK Stack (Elasticsearch, Logstash, Kibana)

Centralized logging is indispensable for debugging complex issues across distributed systems. The ELK stack (now often referred to as the Elastic Stack) provides a powerful solution for collecting, processing, and analyzing logs from your Ruby applications and MySQL clusters on Linode.

The typical setup involves:

  • Logstash: Installed on each Linode server (or a dedicated log forwarder instance) to collect logs.
  • Elasticsearch: A central cluster for storing and indexing logs.
  • Kibana: A web interface for searching, visualizing, and analyzing logs.

On your Ruby application servers, configure Logstash to tail your application logs (e.g., Rails logs). You'll need a Logstash input plugin (like `file`) and an output plugin (like `elasticsearch`).

# Example Logstash configuration (logstash.conf)
input {
  file {
    path => "/path/to/your/rails/log/production.log"
    start_position => "beginning"
    sincedb_path => "/dev/null" # For simplicity, re-reads file on restart. Adjust for production.
  }
}

filter {
  # Add any necessary parsing or grok filters here
  # e.g., to parse JSON logs
  json {
    source => "message"
  }
}

output {
  elasticsearch {
    hosts => ["your_elasticsearch_host:9200"]
    index => "rails-logs-%{+YYYY.MM.dd}"
  }
}

For MySQL, you can use tools like mysqldumpslow to analyze slow query logs and then feed the output into Logstash, or configure Logstash to directly read MySQL error logs if they are structured.

# Example Logstash config for MySQL slow query logs
input {
  exec {
    type => "mysql_slow_query"
    command => "tail -F /var/log/mysql/mysql-slow.log" # Adjust path as needed
    interval => 5
    codec => "line"
  }
}

filter {
  if [type] == "mysql_slow_query" {
    grok {
      match => { "message" => "# User@Host: %{DATA:user}\@%{DATA:host} \[%{TIMESTAMP_ISO8601:timestamp}\] Id: %{NUMBER:query_id}" }
      # Add more grok patterns to extract relevant fields like query, time, rows_sent, etc.
    }
    date {
      match => ["timestamp", "ISO8601"]
    }
  }
}

output {
  elasticsearch {
    hosts => ["your_elasticsearch_host:9200"]
    index => "mysql-slow-logs-%{+YYYY.MM.dd}"
  }
}

On your Elasticsearch and Kibana servers, ensure they are properly configured and accessible. You can deploy these using Docker, native packages, or managed services.

In Kibana, you can create dashboards to visualize:

  • Error rates and types from your Ruby application.
  • Slow query counts and patterns from MySQL.
  • System-level events and warnings.
  • Traffic patterns and request volumes.

Alerting can be configured within Kibana (e.g., using Watcher or ElastAlert) to notify you when specific log patterns emerge, such as a sudden spike in application errors or a high volume of slow queries.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Step-by-Step: Diagnosing indexing lock conflicts and high CPU during bulk stock updates on DigitalOcean Servers
  • How to Debug and Fix memory leaks and socket exhaustion in daemon processes in Modern C++ Applications
  • Infrastructure as Code: Provisioning Secure PHP Clusters on DigitalOcean Using Terraform
  • Fixing Slow Largest Contentful Paint (LCP) caused by unoptimized database queries in Legacy Laravel Codebases Without Breaking API Contracts
  • An Auditor’s Checklist for Securing Laravel Backends on Google Cloud

Copyright © 2026 · Vinay Vengala