Instrumentation on a Weather API app using Rails, OpenTelemetry, and Jaeger
Building instrumentation code with OpenTelemetry and Jaeger on a Rails API app.
We've previously discussed Rails with OpenTelemetry and Jaeger. In this blog, let's discuss how we can build a simple Rails API that serves weather data. OpenTelemetry and Jaeger will observe this application with custom instrumentation.
Screenshot sourced from Behance.
Step 1: Rails Application Setup
Create new Rails API app
Run rails new weather_api_app --api
to create a new Rails API application. The --api
flag tells Rails to set up the application specifically for an API.
I'm assuming you already have Rails in your system.
Add Dependencies
Install the following gems to your Gemfile:
💎 httparty - Responsible for making HTTP requests to the OpenWeatherMap API.
💎 opentelemetry-sdk, opentelemetry-exporter-otlp, opentelemetry-instrumentation-all - OpenTelemetry gems for observability. You can learn about how to set them up here.
Step 2: Weather Data Retrieval
Generate Controller
rails g controller Weather show
Update the WeatherController code
The routes should look like this:
You can now fetch data from the API using a CURL request (or use Postman):
curl "http://localhost:3000/weather/show?city=Colombo"
That's the simplest way of requesting data from OpenWeatherMap API.
🚀 Refactoring the code to follow the Single Responsibility Principle
What we will do here is keep our controllers slim and focused only on handling web requests. Moving the API request logic into a service.
Here's how you do it:
1. Create a PORO for Fetching Weather Data
2. Update the WeatherController
Modify your WeatherController
to use this new WeatherFetcher
service:
With the OpenTelemetry and Jaeger setup, you can observe your application like the video below.
Step 3: Instrumentation with OpenTelemetry
What is instrumentation? Instrumentation is the act of adding observability code to the app yourself. The simple analogy is like adding `logger.info` but sending the data to OpenTelemetry and Jaeger instead of the console.
Global Tracer
The first thing we need to do is to acquire a Tracer from the `config/initializers/opentelemetry.rb`:
This "Tracer" will be globally available to any part of the app.
Adding a Span
We want to add a new span to break down the execution of a process into smaller, measurable units. In this case, we want to isolate the OpenWeatherMap request.
On the `app/services/weather_fetcher.rb`, let's add code to create a new span on the fetch method:
Adding an Event
On the private method `fetch`, let's add an event. To signify during the start and end of the OpenWeatherMap API request.
What's an event?
A span event is a human-readable message on a span that represents “something happening” during it’s lifetime.
On the `app/services/weather_fetcher.rb`, let's update the fetch method:
The new weather_fetcher.rb with instrumentation should look like this:
You should be able to see the changes on the new span and event on Jaeger UI.
Hello there!
Do you have a startup idea or an exciting project you’re passionate about? I’d love to bring your vision to life!
I’m a software developer with 13 years of experience in building apps for startups, I specialize in Rails + Hotwire/React.
Whether you’re looking to innovate, grow your business, or bring a creative idea to the forefront, I’m here to provide tailored solutions that meet your unique needs.
Let’s collaborate to make something amazing!
Sincerely,
Ademar Tutor
hey@ademartutor.com