O11y on Rails

Al DuncansonAl Duncanson
6 min read

In my last article, Observability in Software, I explored the concept of observability, or o11y, and its role in maintaining and improving visibility in software systems.

Given this critical role, it’s essential to consider how it can be implemented effectively in the frameworks we use every day.

For me, Ruby on Rails is one such framework.

Rails is a full-stack framework that provides everything needed to create modern web applications, from rendering HTML templates and handling WebSockets to managing background jobs and sending emails.

Ruby on Rails is, of course, built with Ruby, a dynamic, open-source programming language known for its elegance, simplicity, and focus on developer productivity. These qualities make Ruby a natural fit for tools that aim to enhance developer experience and efficiency.

In line with this, highlight.io released significant updates to their open-source Ruby SDK in v0.3.1, with a few key improvements designed to make observability in Rails applications even more seamless:

  • It’s now easier to manually create spans, with the new start_span method (as well as new convenience methods)

  • New auto-instrumentations will create spans to show you timings for every layer of the Rails stack

  • Connect server spans from full page requests with client load spans so you can see the work being done on the server after requesting a full page reload.

In the following section, I’ll walk you through how to leverage the new features of the Highlight Ruby SDK.

Let’s get started.

Highlight Ruby SDK

To get started, open a Rails project if you have one.

If you don’t and still want to follow along, Rails has great documentation and you can get up and running in just a few minutes.

Client instrumentation

Setting up client instrumentation is as simple as initializing Highlight.

We can do this easily using their script from UNPKG’s CDN, place this in your HTML file:

<script src="https://unpkg.com/highlight.run"></script>

Directly followed by the H.init() method:

H.init("<YOUR_PROJECT_ID>", {
  tracingOrigins: ['localhost'],
  networkRecording: {
    enabled: true,
    recordHeadersAndBody: true,
  },
});

Replace <YOUR_PROJECT_ID> with your Highlight project ID.

That will look something like the following (lines 12-29):

HAML file showing the highlight client instrumentation scripts

Backend instrumentation

Next, install Highlight's ruby SDK by adding the Gem to your Gemfile:

I like to add comments above each Gem in my Gemfile with a small note and link for a better DX

and then install it with bundler:

bundle install

Initialization

Then, initialize the Ruby SDK:

require "highlight"

Highlight::H.new("<YOUR_PROJECT_ID>", environment: "production") do |c|
  c.service_name = "your-rad-app-name"
  c.service_version = "1.0.0"
end

Again, replace <YOUR_PROJECT_ID> with your Highlight project ID.

if you don't have a project ID, head over to Highlight.io to get started for free

Setting your project ID lets Highlight record errors for background tasks and processes not associated with a frontend user session.

Errors

Automatically record any error that occurs in your Rails controllers by adding Highlight's controller action to your ApplicationController:

require "highlight"

class ApplicationController < ActionController::Base
  include Highlight::Integrations::Rails

  around_action :with_highlight_context
end

In the code above, we've implemented an action callback that runs around every controller action.

This means that Rails will run the with_highlight_context method before and after every controller action inherited from the application controller.

Logging

Setting up Highlight's log ingestion is easy.

You can either replace your Rails logger entirely with the Highlight logger, by adding the following line at the bottom of your initializer:

Rails.logger = Highlight::Logger.new(STDOUT)

Or, you can extend it and log with both:

highlightLogger = Highlight::Logger.new(nil)
Rails.logger.extend(ActiveSupport::Logger.broadcast(highlightLogger))

Tracing

With the latest improvements in v0.3.1 of Highlight's Ruby SDK, building traces with custom spans is straightforward.

Using the new start_span convenience method, wrap any code you'd like to trace:

Highlight.start_span("Name your span") do
    # ... the code you want to trace
end

Below, for example, I've created custom spans in each controller action:

Enhance your traces with custom spans

And with that, we've set up our observability infrastructure in a Rails application.

O11y on Rails!

With our code in place, it's time to see the fruits of our labor. Let’s head over to the Highlight app portal, where we can now visualize our:

  • Session replay

  • Errors

  • Logs

  • Traces

These tools provide a comprehensive and cohesive view of our application's performance and user interactions, giving us the insights we need to maintain and improve our Rails app.

Session replay

With Highlight's session replay, you can watch how your users engage with your Rails application, observing the exact moment if and when an error occurs during a user interaction.

Session replay view in the Highlight app portal

Errors

View application errors across the entire Rails stack.

Along with metrics, enhanced stack traces, instance metadata, and user details when the error is associated with a user session.

Errors view in the Highlight app portal

Logs

Rails generates a lot of log data, especially given its reliance on ActiveRecord, background jobs, and middleware.

The Logs view in Highlight is particularly beneficial for Rails developers because it allows you to filter through this data and correlate logs with other observability metrics.

For instance, you can trace a slow ActiveRecord query back to a specific controller action or background job, enabling you to optimize database interactions and improve overall application performance.

Logs provide the raw data needed to understand what’s happening under the hood in a Rails app.

Logs view in Highlight app portal

Traces

In a Rails application, requests often pass through multiple layers—routing, controllers, models, and sometimes external services.

Traces are invaluable because they map out the exact path a request takes through these layers, making it easier to identify and address bottlenecks in your Rails stack. Highlight enhances this by allowing you to view the entire trace as a flame graph or waterfall, providing a visual representation of how time is spent across different parts of your application.

Additionally, Highlight takes this one step further and associates the backend data with the frontend session replays, in a process they call data cohesion. This enables you to watch what was going on, on the frontend, when the trace was recorded on the server.

Just click the View session button to view the frontend session related to the trace you're inspecting!

View a traces flame graph in the Highlight portal

Wrapping up

Thanks for taking the time to explore O11y on Rails with me! If you've read this far, I appreciate it.

We covered a lot of ground, from setting up the Highlight Ruby SDK to diving into the powerful tools it provides for session replay, error tracking, logging, and tracing.

By now, you should have a solid understanding of how these features can enhance your Rails applications.

If you have any questions or thoughts, feel free to reach out.

0
Subscribe to my newsletter

Read articles from Al Duncanson directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Al Duncanson
Al Duncanson

Software engineer, interested in web technologies, mathematics, and open source software. Occasionally, I share my thoughts in writing.