Rails: Measuring Server Latency/Ping time

Wajeeh Ahsan
4 min readAug 10, 2022

Latency/Ping time is the time it takes for data to pass from one point on a network to another. Suppose Server A in New York sends a data packet to Server B in London. Server A sends the packet at 04:38:00.000 GMT and Server B receives it at 04:38:00.145 GMT. The amount of latency on this path is the difference between these two times: 0.145 seconds or 145 milliseconds.

Most often, latency is measured between a user’s device (the “client” device) and a data centre. This measurement helps developers understand how quickly a webpage or application will load for users.

In this blog, we will try to add a ping time measurement tool in rails app. We will do this following a specific “recipe” format (Problem, Solution, Discussion).

Problem

We’re going to add a tool in rails app that will calculate latency/ping time for requests in the app. To achieve this, we will be using

  • Rails with webpecker
  • Stimulus
  • Hotwire
  • Trubo Rails
  • Redis

Solution

Let’s go step by step as follow

Create a Rails App

If you want to add this tool in en existing rails app, move to the next section.

In this section we will create a simple rails app with following command:

rails new webapp --webpack

In your Gemfile, add the webpecker gem and then run bundle to download Webpacker into your project

gem 'webpacker'

And then run

bundle

Now, running the following installs Webpacker in your application.

bundle exec rails webpacker:install

That’s it. The Ruby on Rails project is now completely functional with Webpacker.

Add Stimulus

Run this command to add stimulus

yarn add stimulus

Now we need to import stimulus to the application using webpack . First, in javascript directory, create controllers folder and then add index.js there. This index.js file should have the following code.

import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"

const application = Application.start()
const context = require.context(".", true, /\.js$/)
application.load(definitionsFromContext(context))

Then reference this folder inside application.js. This file should have the following code:

import Rails from "@rails/ujs"import Turbolinks from "turbolinks"import * as ActiveStorage from "@rails/activestorage"import "channels"import "controllers"import "@hotwired/turbo-railsRails.start()Turbolinks.start()ActiveStorage.start()

Add turbo and redis

Add turbo-rails with following command

bundle add turbo-rails

Then install with

rails turbo:install

Now we need to install redis as well

rails turbo:install:redis

We’re done with setup.

Add Ping controller

Now we will add a controller with an action named as ping . The controller will be named as PingController . Use the following command for this

rails g controller ping

This controller should have the following code:

class PingController < ApplicationController
def ping
render status: :ok, body: "PONG"
end
end

Let’s add a route for this action in the route file as in below

get “/ping”, to: “ping#ping”

Now create a form in app/views/shared/_ping.html.erb to hit this rout.

<div data-controller="ping" >
<%= form_tag ping_path, method: :get, data: { action: "turbo:before-fetch-request->ping#pauseRequest turbo:submit-end->ping#measureLatency", "ping-target": "pingForm" } do %>
<%= button_tag "Ping" %>
<% end %>
<span data-ping-target="latency"></span>
</div>

Here, we need to create a controller which will display this _ping partial. We will name this controller as HomeController and and add a show action. For this, use the following command:

rails g controller home show

And then we will make this action as root . Go to the routes.rb file and add this line

root to: “home#show”

To render ping partial, add following code in app/views/home/show.html.erb

<%= render "shared/ping" %>

At this point, we can hit the ping button. Next step is to write a function to calculate the ping time.

Calculating ping time

For this, we need to create a stimulus controller. Use following command for this

rails g stimulus ping

This will create a file app/javascript/controllers/ping_controller.js . Now place the following cod in this file

import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["pingForm", "latency"]

pauseRequest(event) {
event.preventDefault();

setTimeout(() => this.saveRequestTime());

event.detail.resume();
}

saveRequestTime() {
this.requestTime = new Date().getTime();
}

measureLatency() {

this.saveResponseTime();

this.latency = this.responseTime - this.requestTime;

console.log(`${this.latency} ms`);
this.displayLatency()

setTimeout(() => this.ping(), 1000)
}

displayLatency() {
this.latencyTarget.textContent = this.latency + " ms"
}


saveResponseTime() {
this.responseTime = new Date().getTime();
}

ping() {
this.pingFormTarget.requestSubmit()
}

get requestTime() {
return this._requestTime;
}

set requestTime(requestTime) {
this._requestTime = requestTime;
}

get responseTime() {
return this._responseTime;
}

set responseTime(responseTime) {
this._responseTime = responseTime;
}

get latency() {
return this._latency;
}

set latency(latency) {
this._latency = latency;
}
}

What we’re doing in this code is

  1. Pause Request
  2. Save the response time
  3. Compute the difference between the response and request time
  4. Display the result

At this point, we’re all set. If you go to http://localhost:3000 and click Ping button, you will see the response time being displayed on the page after every second as shown below.

Discussion

This is how you can monitor your application’s latency time. This will help you understanding how user friendly your app is and will indicate you if you need to scale your application because time is everything these days. If you’re working on improving your app performance, this simple tool will help you.

--

--