
In this guide, we'll harness AppSignal to detect, diagnose, and remove performance bottlenecks and employ proper tracing in a Ruby on Rails application. From setting up tracing to capturing errors and logging, we’ve got you covered.
We'll ensure our application runs smoother than ever, even under the heaviest loads!
But first, let's quickly touch on how to define tracing and its benefits.
What Is Tracing?
Tracing is the process of following a request and operation through an application. In Ruby applications, tracing captures the execution flow, providing deep insights into the performance of various components.
Benefits of Tracing
Tracing has several benefits, including:
- Performance Optimization: Tracing identifies slow parts of an application that need performance improvements.
- Better Debugging: Detailed traces allow you to quickly pin down code issues and determine their causes.
- Improved Reliability: Tracing tracks application behavior, ensuring more reliable and effective system operation.
A Scenario: Our Lagging Rails App
Let's say it's Black Friday, the biggest shopping day of the year. Your Rails-based e-commerce platform is buzzing with thousands of eager customers, their carts brimming with products, ready to check out. Everything seems perfect — until the system starts lagging.
Transactions fail. Abandoned carts skyrocket. Panic ensues. This is every developer's nightmare. But what if you had a secret weapon? A tool that not only alerts you to issues in real-time but also dives deep into the heart of your application, tracing every request, every database query, and every background job? Enter AppSignal.
How to Set Up Tracing for Ruby on Rails Apps using AppSignal
To demonstrate the power of tracing using AppSignal, I have created a sample Rails e-commerce project that we can integrate with AppSignal. This will help you see firsthand how tracing can identify and resolve these problems.
Prerequisites
- Ruby Version: AppSignal is compatible with Ruby 2.5 and above.
- AppSignal Account: Create an account on AppSignal (there's a free trial available)
Now you're ready to set up tracing in your Ruby application using AppSignal.
Step 1: Install the AppSignal Gem
Here's the gem:
gem 'appsignal'
Simply run bundle install
:
bundle install
Step 2: Initialize AppSignal
Run the AppSignal installation command to set up the necessary configuration files.
bundle exec appsignal install <YOUR-PUSH-API-KEY>
Follow the prompt on your terminal. You can choose a config file or environment variables to configure AppSignal in your app. We will choose the config file option.
This command will generate an appsignal.yml
configuration file in your config directory.
This file will be pre-filled with your AppSignal push API key and some basic configuration settings.
Step 3: Configure AppSignal
Ensure config/appsignal.yml
is correctly configured for your environments. This file contains configuration settings for different environments (development, test, production). Ignore actions that provide little value.
And ta da! You're all set up:
Instrumenting our Ruby on Rails Application
AppSignal can automatically instrument several key components of our Rails application, such as database queries and web requests. We can also add custom instrumentation to trace specific parts of our application.
Custom Rails Instrumentation
To instrument specific parts of our code, we will wrap a couple of lines of code with the Appsignal.instrument
method. This method can be used to trace specific blocks of code, such as more complex parts of controller actions or background jobs.
# app/controllers/orders_controller.rb class OrdersController < ApplicationController def index @orders = Order.all #=> Candidate for N+1 queries Appsignal.instrument('calculate_totals.orders') do @orders.each do |order| order.total_price = order.line_items.sum { |item| item.quantity * item.product.price } end end render json: @orders.as_json(include: { user: { only: [:id, :name, :email] }, line_items: { include: { product: { only: [:id, :name, :price] } }, only: [:id, :quantity, :price] } }) end end
Sending a request to this endpoint will result in an N+1 query being reported.
An N+1 issue occurs when our application makes multiple database queries to load associated records for each object in a collection, instead of using a single, efficient query. This can significantly degrade performance, especially when dealing with large datasets.
The fix in this case is to eager load the get all orders query — simply replace this code:
@orders = Order.all
With the following:
@orders = Order.includes(:user, line_items: :product).all
Collecting and Reporting Ruby Errors with AppSignal
AppSignal allows you to capture and report application errors using the Appsignal.set_error
method.
Here’s an example of capturing and reporting an error in the order controller index action:
def index @orders = Order.all #=> Candidate for N+1 queries # Introduce a deliberate error based on order count if @orders.size > 10 raise "Too many orders" end render json: @orders.as_json(include: { user: { only: [:id, :name, :email] }, line_items: { include: { product: { only: [:id, :name, :price] } }, only: [:id, :quantity, :price] } }) rescue => e # Report error to AppSignal Appsignal.set_error(e) render json: { error: e.message }, status: :internal_server_error end
In this example, we demonstrate custom error handling within a specific controller action. However, it's important to note that AppSignal reports errors by default, so explicit error reporting with Appsignal.set_error
is not usually necessary.
For consistent and centralized error handling across all controller actions, it’s recommended you use rescue_from
at the controller level. This approach ensures that any unhandled exceptions in your controller actions are properly reported and managed.
Here’s an example of how you can implement this:
class OrdersController < ApplicationController # Use rescue_from to handle errors for all controller actions rescue_from StandardError, with: :handle_error def index @orders = Order.includes(:user, line_items: :product).all Appsignal.instrument('orders.index.custom_query') do # Fake some complexity @orders.each do |order| order.total = order.line_items.sum { |item| item.quantity * item.product.price } end end render json: @orders.as_json(include: { user: { only: [:id, :name, :email] }, line_items: { include: { product: { only: [:id, :name, :price] } }, only: [:id, :quantity, :price] } }) end private # Error handling method def handle_error(exception) Appsignal.set_error(exception) render json: { error: exception.message }, status: :internal_server_error end end
On the Error > Issue list tab, we can see a list of all errors, the status of each issue, and how long ago the error occurred:

Clicking on the RuntimeError
, we can see the error log and the code line that is triggering this error:

Let's touch on some more advanced tracing techniques before we wrap up.
Advanced Tracing Techniques
We'll implement some advanced tracing techniques on the order endpoint of our e-commerce app.
These techniques will help us manage high-traffic environments efficiently, ensure data privacy, and secure access to trace data.
High Traffic Use Cases
In high-throughput environments, collecting trace data for every request can lead to significant overhead. Sampling helps reduce this by collecting trace data for only a subset of requests.
Adding Metadata to Transactions
You can supply extra context on errors and performance issues using tags and sample data. This can help to add information that is not already part of the request, session, or environment parameters. Read more about how to pass and add additional metadata.
Asynchronous Processing
Asynchronous processing is a common technique used to handle tasks that are too time-consuming to be performed within the request-response cycle, such as sending emails, processing background jobs, and handling large data imports. Ruby on Rails applications typically use background job libraries like Sidekiq, Resque, or Delayed Job to manage these tasks.
AppSignal seamlessly integrates with libraries such as Active Job, DelayedJob, Shoryuken, Sidekiq, and Que to provide insights into the performance and errors of your background jobs.
Security Considerations
Security is a very important piece of any production-ready application.
We need to ensure that sensitive data is not included in trace data to maintain user privacy. The values of filter parameters will be replaced with [FILTERED]
when transmitted to AppSignal.
Let's modify config/appsignal.yml
to include several sensitive request params that need masking.
# config/appsignal.yml default: &defaults push_api_key: "<%= ENV['APPSIGNAL_PUSH_API_KEY'] %>" name: "ECommerceApp" filter_parameters: - password - email - api_token - token
If you use the Rails filter_parameters
config option, AppSignal will merge its config with Rails's config, so there's no need to configure it twice.
By implementing these advanced tracing techniques, you can efficiently manage high-traffic environments and ensure the privacy of sensitive data. Read more on filter parameters.
Wrapping Up
We've seen that setting up tracing for a Ruby app using AppSignal involves understanding tracing fundamentals, preparing your application, and following a step-by-step setup process. Advanced methods and debugging techniques can then be used to enhance tracing.
Regularly applying tracing in development and maintenance cycles leads to higher performance and reliability. Get started with AppSignal today for enhanced monitoring and deep performance insights into your Ruby applications.
Happy coding!
Wondering what you can do next?
Finished this article? Here are a few more things you can do:
- Subscribe to our Ruby Magic newsletter and never miss an article again.
- Start monitoring your Ruby app with AppSignal.
- Share this article on social media
Most popular Ruby articles
What's New in Ruby on Rails 8
Let's explore everything that Rails 8 has to offer.
See moreMeasuring the Impact of Feature Flags in Ruby on Rails with AppSignal
We'll set up feature flags in a Solidus storefront using Flipper and AppSignal's custom metrics.
See moreFive Things to Avoid in Ruby
We'll dive into five common Ruby mistakes and see how we can combat them.
See more

Daniel Amah
Our guest author Daniel is a Principal Software Engineer and Technical Founder with over a decade of experience building scalable web and mobile platforms using Ruby on Rails, React, and AI-powered architectures. He is the creator of Taskclan and frequently writes about engineering leadership, developer workflows, and startup execution on Medium and LinkedIn.
All articles by Daniel AmahBecome our next author!
AppSignal monitors your apps
AppSignal provides insights for Ruby, Rails, Elixir, Phoenix, Node.js, Express and many other frameworks and libraries. We are located in beautiful Amsterdam. We love stroopwafels. If you do too, let us know. We might send you some!
