Introducing the Treblle SDK to the Ruby Community

Discover Treblle's E2E solution for mastering API management. Six integrated service ensure quality, security, and performance for your APIs.

19 days ago   •   6 min read

By Borna Kapusta

The flurry of errors in the bug tracker was the last thing John needed at 5pm on a Friday. Why were all these clients sending the wrong parameter?

Monitoring, managing, and observing your APIs is crucial for ensuring optimal performance, identifying potential issues, and understanding user behavior. Treblle helps engineering and product teams build, ship and understand their REST APIs in one single place.

Our mission at Cactus Code was to introduce Treblle to the Ruby community as a new gem, making it easy to add API monitoring and observability to your Rails applications.

Trusted by over 90,000 developers at top companies like Apple, IBM, and PwC, Treblle has proven its worth in the industry. That said, let’s dive in and explore how Treblle can transform your API management experience.


When do you want to use Treblle?

Discover Treblle's all-in-one solution for mastering API management. With six integrated services, Treblle ensures quality, security, and performance for your APIs. From comprehensive documentation and real-time monitoring to advanced analytics and robust security checks, Treblle streamlines your API operations and development process.

It’s split into six services:

API Governance: Evaluates the quality, security, and performance of your APIs. Provides a score for each category to ensure compliance with industry standards and best practices.

API Documentation: Generates comprehensive documentation in Swagger format. Makes it easy to understand and use your APIs.

API Observability: Offers an in-depth view of API requests. Allows real-time monitoring and tracking of interactions for better performance insights.

API Analytics: Provides a detailed overview of metadata and statistics. Enables effective analysis of usage patterns and performance metrics.

API Security: Performs thorough security checks on API requests. Identifies vulnerabilities and ensures your APIs are protected against threats.

API Assistant: Chat-based tool that uses comprehensive data to generate examples and integrations. Supports development in your preferred programming language, streamlining the process.

RubyGem

The treblle-ruby gem functions as a middleware package which collects extensive data from the request/response objects and sends it to the Treblle API through a single POST request as a JSON-formatted payload.

Treblle prioritizes data privacy and has default settings that ensure data safety. Additionally, you can specify parameters that you would like to mask before the gem sends the data for processing to the Treblle dashboard.

Testing plays a crucial role in ensuring our gem functions seamlessly with your setup and doesn't break your application. To achieve this, we use the Appraisal gem, which integrates with bundler and rake to test the middleware against different supported Ruby and Rails version combinations. This will give you peace of mind as we push out updates to the middleware in the future.

Sounds simple enough? Let’s dive into how the middleware works under the hood.

Gem as a middleware

Let’s start from the basics. What actually is middleware and how do we use it to monitor requests/responses?

Middleware is a flexible term that can have various meanings depending on the context.

But in the Ruby world, middleware is a layer that is between the application and the web server. It functions as a standalone application that processes requests independently, either before or after your main application.

In the illustration above you can see the flow of the request and response from a client to your Rails application. First thing that happens is that the request is received by the Rack web server.

Server will read the data from the client socket, create a Rack environment object (marked as env) and call the application with it as an argument. 

An environment variable represents an HTTP request as a ruby hash, containing various attributes that describe the request. Example of these attributes:

{
    "REQUEST_METHOD" => "GET",
    "PATH_INFO" => "/",
    "HTTP_VERSION" => "1.1",
    "SERVER_NAME"=>"localhost",
    "SERVER_PORT"=>"3000",
    ...
}

But, before the request hits your Rails controller it will go through a bunch of rack compatible middlewares in the stack, or in other words, Rack applications.

Rack applications are objects which respond to call (with an env argument) and return an array that contains status code, headers and response body.

[
  200,
  {"Header" => "Value"},
  ["The response body"]
]

Middleware is essentially a class with a call method. This method receives the incoming HTTP request (env) from the web server, processes it, and then passes it to the next middleware and at the very end, the Rails application itself. After the Rails application processes the request and generates a response, the middlewares further processes this response before returning it to the web server.

Let's look at this simple middleware that measures and prints the time taken by request to respond:

class CustomMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    started_on = Time.now
    status, headers, response = @app.call(env)
    ended_on = Time.now

    puts ended_on - started_on

    [status, headers, response]
  end
end

As we mentioned before, there are a few rules that the middleware needs to follow here:

  • The middleware's constructor must accept the application (or the next middleware) as a parameter;
  • It must respond to a call method with exactly one argument, rack environment;
  • It must return a response containing an array of status code, headers, and body to the web server or pass it to the next middleware in the pipeline.;

Rack
The Rack protocol ensures that any Rack-compliant middleware can work seamlessly with any Rack-compliant web server. This is due to the standardized structure that the call method enforces. By following this protocol, the middleware can effectively handle the request-response cycle, providing a minimal, modular, and adaptable interface for web applications.

As the Treblle middleware intersects request/response, it will build and mask all needed data for the dashboard telemetry and send it to Treblle server.

Rails Middleware API

Now that we have middleware, we still need to tell our application where it should be implemented in the middleware chain.

To inspect your middleware chain, you can run:

rails middleware

That will output middleware chain in order from first to last:

use ActionDispatch::HostAuthorization
use Rack::Sendfile
use ActionDispatch::Static
use ActionDispatch::Executor
use ActionDispatch::ServerTiming
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use ActionDispatch::RequestId
use ActionDispatch::RemoteIp
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::ActionableExceptions
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag

Now that we know our chain, we need to insert our middleware into it. Rails offers a straightforward configuration interface, config.middleware, for managing the middleware stack. This includes adding, removing, and modifying middleware components.

Our strategy is to integrate Treblle middleware directly into the gem, handling everything for you out of the box.

module Treblle
  module Rails
    class Railtie < ::Rails::Railtie
      initializer 'treblle.install_middleware' do |app|
        app.config.middleware.insert_after ActionDispatch::ShowExceptions, Treblle::Middleware
      end
    end
  end
end

Here is a snippet of inserting our middleware right after ActionDispatch::ShowExceptions.

This middleware rescues any exception returned by the application and calls an exceptions app that will wrap it in a format for the end user. Which is perfect for us having all we need from the response and sending it to Treblle.

Rails implementation

One of our biggest goals while creating ruby gem was creating a gem that is dead simple and flexible to integrate into your Rails application. It requires only three steps to enable Treblle’s toolset with your app.

  1. Add treble gem to your gemfile:
  2. Run: bundle install
  3. Configure it to your needs:
# config/initializers/treblle.rb

Treblle.configure do |config|
  config.api_key               = ENV.fetch('TREBLLE_API_KEY')
  config.project_id            = ENV.fetch('TREBLLE_PROJECT_ID')
  config.enabled_environments  = %w[staging development]
  config.sensitive_attrs       = %w[top_secret_custom_attribute password_digest]
  config.restricted_endpoints  = %w[/api/users /api/v2/*]
  config.whitelisted_endpoints = %w[/api/]
end

Description for all possible options:

  • config.api_key (required)- your Treblle API key
  • config.project_id (required) - your Treblle project id
  • config.enabled_environments (required) - enables monitoring on desired environments.
  • config.sensitive_attrs (optional) - if default list of sensitive attributes is not enough for you, add additional attributes to mask here
  • config.restricted_endpoints (optional) - routes that you specifically don't want to monitor, here you can use a wildcard (*) to define patterns. For example, /api/v2/ would blacklist all routes under api/v2/
  • config.whitelisted_endpoints (optional) - routes that you want to monitor, and starts with value you define, by default /api/

And that's all it takes to enable your Treblle monitoring and your dashboard. treblle-ruby will start tracking your requests/responses as they start coming in.

In your Treblle Dashboard you get to see real-time requests to your API, auto-generated API docs, API analytics like how fast the response was for an endpoint, the load size of the response, etc.


Spread the word

Keep reading