DEV Community

AdeelSarim
AdeelSarim

Posted on

1 1

Adding Ping tool in Rails App

You've heard of word ping or latency in network based applications. It's the time an application takes to respond to requests. For example, you're making a search on google. Your successful search will have following steps:

  1. In search bar, you enter some text
  2. Hit enter
  3. Request is being processed
  4. Response/results appear on webpage

Latency is the time it takes from step-2 to step-4.

Problem
In this blog, we will learn how to add a ping/latency time tool to our rails app. After setting this tool up, we will be able to monitor ping time for our rails app. The basic idea is to see how fast/slow our app is working.

Solution
Here is a prerequisite before we start adding this.

  1. Rails App running with webpacker (rails version should be >=5)
  2. Webpacker added

Let’s assume we have a rails app working with rails version => 5 and webpacker is added. Here’s how we will add this ping tool:

1-Add Stimulus
Run this command to add stimulus

Yarn add stimulus

Once it’s installed, use webpack to import it to the application. We will do this in app/javascript/packs/application.js. In javascript directory, create controllers folder and then add index.js there. Then reference this folder inside application.js. This is how your index.js will look like

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

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


Enter fullscreen mode Exit fullscreen mode

2- Add turbo-rails and redis
To setup turbo-rails, use following commands
bundle add turbo-rails
rails turbo:install
rails turbo:install:redis

Now we’re all set and ready to use it. Let’s generate a PingsController with following command.
rails g controller ping
Let’s add #pong action which renders plain text response with PONG

class PingController < ApplicationController
  def pong
    render status: :ok, body: "PONG"
  end
end
Enter fullscreen mode Exit fullscreen mode

Let’s add a /ping endpoint routed to the #pong action like this:
get “/ping”, to: “ping#pong”, as: “ping”

Let’s create a form now 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>
Enter fullscreen mode Exit fullscreen mode

Let’s create a homepage and add this partial their so it would be usable from the homepage. First, let’s create HomeController with show action.

rails g controller home show

Now make this show action as root action in route.rb

root to: “home#show”

Now render the form partial on show page
Add following code in app/views/home/show.html.erb

<%= render "shared/ping" %>

Next step is to measure the time latency now.
For this, we need to generate a stimulus controller.

rails g stimulus ping

And then let’s define the getters and setters we need to serve our purpose. We have a measureLatency() fucntion that will measure the latency. Then there's a displayLatency() function that will display latency on page every second. All of this code will go in app/javascript/controllers/ping_controller.js as below.

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

If we submit the form ping time will be printed after each second like in this picture.

Image description

Discussion
This is how you can tell the end user about the latency time. It is more helpful when you're working to scale your app and improving the app performance. To make the UI better, you can print a graph as well.

A simple Rails ping app is here in this Repo

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

Jetbrains image

Build Secure, Ship Fast

Discover best practices to secure CI/CD without slowing down your pipeline.

Read more

👋 Kindness is contagious

If this article connected with you, consider tapping ❤️ or leaving a brief comment to share your thoughts!

Okay