Skip to main content

Automatic Instrumentation

The BrainzLab SDK automatically instruments popular Ruby libraries to provide performance tracing, error context, and logging without any code changes.

Supported Libraries

LibraryWhat’s TrackedPulseReflexRecall
Rails/RackRequests, responses, timing
Active RecordSQL queries, duration
Net::HTTPOutbound HTTP calls
FaradayHTTP client requests
HTTPartyHTTP client requests
RedisCommands, duration
SidekiqJobs, queue wait time
Delayed::JobJobs, execution time
GraphQLQueries, field resolution
GrapeAPI endpoints
MongoDBDatabase operations
ElasticsearchSearch operations
ActionMailerEmail delivery

Rails/Rack

Automatically instruments all incoming HTTP requests. What’s tracked:
  • Request method, path, and parameters
  • Response status code
  • Total request duration
  • Controller and action name
  • View rendering time
  • Database query time breakdown
Configuration:
config.pulse_excluded_paths = ['/health', '/ping', '/up', '/assets']
Example trace:
GET /users/123 → 200 (45ms)
├── UsersController#show (40ms)
│   ├── User.find (5ms)
│   ├── User.posts (12ms)
│   └── render show.html.erb (18ms)

Active Record

Tracks all SQL queries with timing and query details. What’s tracked:
  • SQL query (sanitized)
  • Query duration
  • Table/model name
  • Query type (SELECT, INSERT, UPDATE, DELETE)
  • Row count (when available)
Configuration:
config.instrument_active_record = true  # default: true
Example breadcrumb:
{
  category: "db.sql",
  message: "User Load",
  data: {
    sql: "SELECT * FROM users WHERE id = ?",
    duration_ms: 2.5,
    name: "User Load"
  }
}

Net::HTTP

Instruments Ruby’s built-in HTTP client. What’s tracked:
  • Request method and URL
  • Response status code
  • Request duration
  • Request/response headers (configurable)
Configuration:
config.instrument_http = true  # default: true
config.http_ignore_hosts = ['localhost', '127.0.0.1', 'internal-api.local']
Distributed tracing: Trace context is automatically injected into outgoing requests:
  • traceparent (W3C Trace Context)
  • X-B3-TraceId, X-B3-SpanId (B3 format)

Faraday

Instruments Faraday HTTP client via middleware. What’s tracked:
  • Request method and URL
  • Response status code
  • Request duration
  • Error details on failure
Configuration:
config.instrument_http = true  # default: true
Manual middleware setup (optional):
conn = Faraday.new do |f|
  f.use BrainzLab::Instrumentation::FaradayMiddleware::Middleware
  f.adapter Faraday.default_adapter
end

HTTParty

Instruments HTTParty requests automatically. What’s tracked:
  • Request method and URL
  • Response status code
  • Request duration
Configuration:
config.instrument_http = true  # default: true

Redis

Tracks Redis commands with timing. What’s tracked:
  • Command name (GET, SET, HGET, etc.)
  • Key (first argument)
  • Duration
  • Database number
Configuration:
config.instrument_redis = true  # default: true
config.redis_ignore_commands = ['ping', 'info', 'select']
Supports:
  • Redis gem v4.x (via monkey-patching)
  • Redis gem v5.x+ (via middleware)
Example span:
{
  name: "Redis GET",
  kind: "redis",
  data: {
    command: "GET",
    key: "user:123:session"
  },
  duration_ms: 0.8
}

Sidekiq

Full instrumentation for Sidekiq background jobs. What’s tracked:
  • Job class and arguments
  • Queue name
  • Queue wait time (time in queue before processing)
  • Execution duration
  • Retry count
  • Error details on failure
Configuration:
config.instrument_sidekiq = true  # default: true
Distributed tracing: Trace context automatically propagates from web request → Sidekiq job:
# Web request creates trace
class OrdersController < ApplicationController
  def create
    @order = Order.create!(params)
    ProcessOrderJob.perform_async(@order.id)  # Trace context passed automatically
  end
end

# Job receives trace context
class ProcessOrderJob
  include Sidekiq::Job

  def perform(order_id)
    # This job is linked to the original web request trace
    order = Order.find(order_id)
    order.process!
  end
end
Middleware components:
  • ServerMiddleware - Traces job execution
  • ClientMiddleware - Injects trace context when enqueueing

Delayed::Job

Instruments Delayed::Job background processing. What’s tracked:
  • Job class/method name
  • Queue name
  • Queue wait time
  • Execution duration
  • Retry attempts
  • Failure details
Configuration:
config.instrument_delayed_job = true  # default: true
Installation methods:
  1. Automatic via lifecycle hooks
  2. Plugin: Delayed::Worker.plugins << BrainzLab::Instrumentation::DelayedJobInstrumentation::Plugin

GraphQL

Instruments GraphQL-Ruby queries and mutations. What’s tracked:
  • Query/mutation name
  • Operation type
  • Execution duration
  • Field resolution (fields >10ms)
  • Variables (sanitized)
  • Errors
Configuration:
config.instrument_graphql = true  # default: true
Schema setup (for GraphQL-Ruby 2.0+):
class MySchema < GraphQL::Schema
  trace_with BrainzLab::Instrumentation::GraphQLInstrumentation::Tracer

  query QueryType
  mutation MutationType
end
Example trace:
GraphQL query GetUser (25ms)
├── Query.user (3ms)
├── User.posts (15ms)  # Flagged: >10ms
└── User.avatar (2ms)

Grape

Instruments Grape API endpoints. What’s tracked:
  • HTTP method and path
  • Route pattern
  • Response status
  • Endpoint duration
  • Filter execution time
Configuration:
config.instrument_grape = true  # default: true
Middleware setup:
class API < Grape::API
  # Option 1: Use middleware for full tracing
  use BrainzLab::Instrumentation::GrapeInstrumentation::Middleware

  # Option 2: Automatic via ActiveSupport notifications
  # (works without middleware if Grape emits notifications)

  resource :users do
    get do
      User.all
    end

    get ':id' do
      User.find(params[:id])
    end
  end
end

MongoDB

Instruments MongoDB operations via the Ruby driver. What’s tracked:
  • Command name (find, insert, update, delete, aggregate)
  • Collection name
  • Duration
  • Document count
Configuration:
config.instrument_mongodb = true  # default: true
Supports:
  • mongo gem (MongoDB Ruby Driver)
  • mongoid ODM
Example span:
{
  name: "MongoDB find users",
  kind: "mongodb",
  data: {
    command: "find",
    collection: "users",
    database: "myapp_production"
  },
  duration_ms: 3.2
}

Elasticsearch

Instruments Elasticsearch and OpenSearch queries. What’s tracked:
  • Operation type (search, index, delete, bulk)
  • Index name
  • Duration
  • Query details (sanitized)
Configuration:
config.instrument_elasticsearch = true  # default: true
Supports:
  • elasticsearch gem
  • opensearch-ruby gem
  • Elastic 8.x client
Example span:
{
  name: "Elasticsearch search products",
  kind: "elasticsearch",
  data: {
    operation: "search",
    index: "products",
    method: "POST"
  },
  duration_ms: 15.4
}

ActionMailer

Tracks email delivery with ActionMailer. What’s tracked:
  • Mailer class and action
  • Recipients (masked for privacy)
  • Subject (truncated)
  • Delivery duration
  • Message ID
Configuration:
config.instrument_action_mailer = true  # default: true
Privacy: Email addresses are automatically masked: Example span:
{
  name: "Mail deliver UserMailer#welcome",
  kind: "mailer",
  data: {
    mailer: "UserMailer",
    action: "welcome",
    to: "jo***@example.com",
    subject: "Welcome to our app!"
  },
  duration_ms: 245
}

Disabling Instrumentation

Disable specific instrumentations:
BrainzLab.configure do |config|
  # Disable all HTTP instrumentation
  config.instrument_http = false

  # Disable specific libraries
  config.instrument_redis = false
  config.instrument_sidekiq = false
  config.instrument_graphql = false
  config.instrument_mongodb = false
  config.instrument_elasticsearch = false
  config.instrument_action_mailer = false
  config.instrument_delayed_job = false
  config.instrument_grape = false
end

Custom Instrumentation

Add custom spans for code you want to track:
BrainzLab::Pulse.trace("custom_operation", kind: "custom") do |span|
  span[:data] = { key: "value" }

  # Your code here
  perform_operation()
end
See Pulse documentation for more details.