API Governance | Jun 28, 2024 | 8 min read
Discover Treblle's E2E solution for mastering API management. Six integrated service ensure quality, security, and performance for your APIs.
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.
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.
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.
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:
call
method with exactly one argument, rack environment;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.
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.
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.
bundle install
# 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 keyconfig.project_id
(required) - your Treblle project idconfig.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 hereconfig.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.
Inconsistent API endpoints slow development, confuse teams, and frustrate users. This guide breaks down the principles and best practices for designing clean, predictable, and scalable API paths that improve developer experience and reduce errors.
We’ve updated the Treblle Go SDK to support Treblle V3, with a full rewrite focused on performance, ease of use, and better integration with Go tools and frameworks. This guide walks you through the changes, setup, and new features.
In this blog, we explore how Go’s concurrency model helps us do more with less. Through a fun kitchen party analogy, you’ll learn about goroutines, channels, waitgroups, semaphores, and how to use them together to build efficient, concurrent programs.