Skip to content

brainz-lab/brainzlab-ruby

BrainzLab Ruby SDK

Gem Version CI CodeQL codecov Docs License: OSAaSy

Official Ruby SDK for BrainzLab - the complete observability platform.

  • Recall - Structured logging
  • Reflex - Error tracking
  • Pulse - APM & distributed tracing

Installation

From RubyGems (recommended)

Add to your Gemfile:

gem 'brainzlab'

Then run:

bundle install

From GitHub Packages

Add the GitHub Packages source to your Gemfile:

source "https://rubygems.pkg.github.com/brainz-lab" do
  gem 'brainzlab'
end

Configure Bundler with your GitHub token:

bundle config set --global rubygems.pkg.github.com USERNAME:TOKEN

Quick Start

Get Your API Key

  1. Sign up at platform.brainzlab.ai
  2. Create or select a project
  3. Copy your API key (sk_live_xxx or sk_test_xxx)
  4. Set it as BRAINZLAB_SECRET_KEY environment variable

One key, all products: Your Platform API key works across Recall, Reflex, Pulse, and all BrainzLab products. No separate keys needed.

Configuration

# config/initializers/brainzlab.rb
BrainzLab.configure do |config|
  # Authentication (required) - Your Platform API key
  config.secret_key = ENV['BRAINZLAB_SECRET_KEY']

  # Environment
  config.environment = Rails.env
  config.service = 'my-app'

  # Enable/disable products
  config.recall_enabled = true   # Logging
  config.reflex_enabled = true   # Error tracking
  config.pulse_enabled = true    # APM

  # Auto-provisioning (creates projects automatically)
  config.recall_auto_provision = true
  config.reflex_auto_provision = true
  config.pulse_auto_provision = true
end

Recall - Structured Logging

# Log levels
BrainzLab::Recall.debug("Debug message", details: "...")
BrainzLab::Recall.info("User signed up", user_id: user.id)
BrainzLab::Recall.warn("Rate limit approaching", current: 95, limit: 100)
BrainzLab::Recall.error("Payment failed", error: e.message, amount: 99.99)
BrainzLab::Recall.fatal("Database connection lost")

# With context
BrainzLab::Recall.info("Order created",
  order_id: order.id,
  user_id: user.id,
  total: order.total,
  items: order.items.count
)

Configuration Options

config.recall_min_level = :info        # Minimum log level (:debug, :info, :warn, :error, :fatal)
config.recall_buffer_size = 50         # Batch size before flush
config.recall_flush_interval = 5       # Seconds between flushes

Reflex - Error Tracking

# Capture exceptions
begin
  risky_operation
rescue => e
  BrainzLab::Reflex.capture(e,
    user_id: current_user.id,
    order_id: order.id
  )
end

# Add breadcrumbs for context
BrainzLab::Reflex.add_breadcrumb("User clicked checkout",
  category: "ui.click",
  data: { button: "checkout" }
)

# Set user context
BrainzLab::Reflex.set_user(
  id: user.id,
  email: user.email,
  plan: user.plan
)

# Add tags
BrainzLab::Reflex.set_tags(
  environment: "production",
  region: "us-east-1"
)

Configuration Options

config.reflex_excluded_exceptions = ['ActiveRecord::RecordNotFound']
config.reflex_sample_rate = 1.0        # 1.0 = 100%, 0.5 = 50%
config.reflex_before_send = ->(event) {
  # Modify or filter events
  event[:tags][:custom] = 'value'
  event  # Return nil to drop the event
}

Pulse - APM & Distributed Tracing

Pulse automatically instruments your application to track performance.

Automatic Instrumentation

The SDK automatically instruments:

Library Description
Rails/Rack Request tracing with breakdown
Active Record SQL queries with timing
Net::HTTP Outbound HTTP calls
Faraday HTTP client requests
HTTParty HTTP client requests
Redis Redis commands
Sidekiq Background job processing
Delayed::Job Background job processing
GraphQL Query and field resolution
Grape API endpoint tracing
MongoDB Database operations
Elasticsearch Search operations
ActionMailer Email delivery

Configuration Options

# Enable/disable specific instrumentations
config.instrument_http = true           # Net::HTTP, Faraday, HTTParty
config.instrument_active_record = true  # SQL queries
config.instrument_redis = true          # Redis commands
config.instrument_sidekiq = true        # Sidekiq jobs
config.instrument_graphql = true        # GraphQL queries
config.instrument_mongodb = true        # MongoDB operations
config.instrument_elasticsearch = true  # Elasticsearch queries
config.instrument_action_mailer = true  # Email delivery
config.instrument_delayed_job = true    # Delayed::Job
config.instrument_grape = true          # Grape API

# Filtering
config.http_ignore_hosts = ['localhost', '127.0.0.1']
config.redis_ignore_commands = ['ping', 'info']
config.pulse_excluded_paths = ['/health', '/ping', '/up', '/assets']
config.pulse_sample_rate = 1.0          # 1.0 = 100%

Distributed Tracing

Pulse supports distributed tracing across services using W3C Trace Context and B3 propagation.

# Extracting trace context from incoming requests (automatic in Rails)
context = BrainzLab::Pulse.extract!(request.headers)

# Injecting trace context into outgoing requests (automatic with instrumentation)
BrainzLab::Pulse.inject!(headers)

Custom Spans

BrainzLab::Pulse.trace("process_payment", kind: "payment") do |span|
  span[:data] = { amount: 99.99, currency: "USD" }
  process_payment(order)
end

Rails Integration

The SDK automatically integrates with Rails when loaded:

  • Request context (request_id, path, method, params)
  • Exception reporting to Reflex
  • Performance tracing with Pulse
  • User context from current_user

Setting User Context

class ApplicationController < ActionController::Base
  before_action :set_brainzlab_context

  private

  def set_brainzlab_context
    if current_user
      BrainzLab.set_user(
        id: current_user.id,
        email: current_user.email,
        name: current_user.name
      )
    end
  end
end

Sidekiq Integration

For Sidekiq, the SDK automatically:

  • Traces job execution with queue wait time
  • Propagates trace context between web and worker
  • Captures job failures to Reflex
# config/initializers/sidekiq.rb
# Instrumentation is automatic, but you can configure:

BrainzLab.configure do |config|
  config.instrument_sidekiq = true
end

Grape API Integration

For Grape APIs, you can use the middleware:

class API < Grape::API
  use BrainzLab::Instrumentation::GrapeInstrumentation::Middleware

  # Your API endpoints...
end

GraphQL Integration

For GraphQL-Ruby 2.0+, add the tracer:

class MySchema < GraphQL::Schema
  trace_with BrainzLab::Instrumentation::GraphQLInstrumentation::Tracer

  # Your schema...
end

Environment Variables

Variable Description
BRAINZLAB_SECRET_KEY API key for authentication
BRAINZLAB_ENVIRONMENT Environment name (default: auto-detect)
BRAINZLAB_SERVICE Service name
BRAINZLAB_APP_NAME App name for auto-provisioning
BRAINZLAB_DEBUG Enable debug logging (true/false)
BRAINZLAB_MODE SDK mode: production (default) or development (offline)
BRAINZLAB_DEV_DB_PATH SQLite database path for development mode
RECALL_URL Custom Recall endpoint
REFLEX_URL Custom Reflex endpoint
PULSE_URL Custom Pulse endpoint

Scrubbing Sensitive Data

The SDK automatically scrubs sensitive fields:

config.scrub_fields = [:password, :password_confirmation, :token, :api_key, :secret]

Debug Mode

Debug mode provides detailed visibility into SDK operations, including all API requests and responses with timing information. This is invaluable for troubleshooting integration issues.

Enabling Debug Mode

# In your initializer
BrainzLab.configure do |config|
  config.debug = true
end

# Or via environment variable
# BRAINZLAB_DEBUG=true

Debug Output Format

When debug mode is enabled, you'll see colorized output in your terminal:

[BrainzLab] 12:34:56 -> Recall POST /api/v1/logs (count: 5)
[BrainzLab] 12:34:56 <- Recall 200 OK (45ms)

[BrainzLab] 12:34:57 -> Reflex POST /api/v1/errors (exception: RuntimeError)
[BrainzLab] 12:34:57 <- Reflex 201 Created (23ms)

[BrainzLab] 12:34:58 -> Pulse POST /api/v1/traces (name: GET /users)
[BrainzLab] 12:34:58 <- Pulse 200 OK (18ms)

The output includes:

  • Timestamp for each operation
  • Service name (Recall, Reflex, Pulse, etc.)
  • Request method and path
  • Payload summary (log count, exception type, etc.)
  • Response status code and message
  • Request duration with color coding (green < 100ms, yellow < 1s, red > 1s)

Custom Logger

You can provide your own logger to capture debug output:

BrainzLab.configure do |config|
  config.debug = true
  config.logger = Rails.logger
  # Or any Logger-compatible object
  config.logger = Logger.new('log/brainzlab.log')
end

Debug Callbacks

For advanced debugging and monitoring, you can hook into SDK operations:

BrainzLab.configure do |config|
  # Called before each API request
  config.on_send = ->(service, method, path, payload) {
    Rails.logger.debug "[BrainzLab] Sending to #{service}: #{method} #{path}"

    # You can use this to:
    # - Log all outgoing requests
    # - Send metrics to your monitoring system
    # - Add custom tracing
  }

  # Called when an SDK error occurs
  config.on_error = ->(error, context) {
    Rails.logger.error "[BrainzLab] Error in #{context[:service]}: #{error.message}"

    # You can use this to:
    # - Alert on SDK failures
    # - Track error rates
    # - Fallback to alternative logging

    # Note: This is for SDK errors, not application errors
    # Application errors are sent to Reflex as normal
  }
end

Programmatic Debug Logging

You can also use the Debug module directly:

# Log a debug message (only outputs when debug=true)
BrainzLab::Debug.log("Custom message", level: :info)
BrainzLab::Debug.log("Something went wrong", level: :error, error_code: 500)

# Measure operation timing
BrainzLab::Debug.measure(:custom, "expensive_operation") do
  # Your code here
end

# Check if debug mode is enabled
if BrainzLab::Debug.enabled?
  # Perform additional debug operations
end

Debug Output Levels

Debug messages are color-coded by level:

  • DEBUG (gray) - Verbose internal operations
  • INFO (cyan) - Normal operations
  • WARN (yellow) - Potential issues
  • ERROR (red) - Failed operations

Development Mode

Development mode allows you to use the SDK without a BrainzLab server connection. Events are logged to stdout in a readable format and stored locally in a SQLite database.

Configuration

# config/initializers/brainzlab.rb
BrainzLab.configure do |config|
  # Enable development mode (works offline)
  config.mode = :development

  # Optional: customize the SQLite database path (default: tmp/brainzlab.sqlite3)
  config.development_db_path = 'tmp/brainzlab_dev.sqlite3'

  # Other settings still apply
  config.environment = Rails.env
  config.service = 'my-app'
end

Or use the environment variable:

export BRAINZLAB_MODE=development

Features

In development mode:

  • No server connection required - Works completely offline
  • Stdout logging - All events are pretty-printed to the console with colors
  • Local storage - Events are stored in SQLite at tmp/brainzlab.sqlite3
  • Queryable - Use BrainzLab.development_events to query stored events

Querying Events

# Get all events
events = BrainzLab.development_events

# Filter by service
logs = BrainzLab.development_events(service: :recall)
errors = BrainzLab.development_events(service: :reflex)
traces = BrainzLab.development_events(service: :pulse)

# Filter by event type
BrainzLab.development_events(event_type: 'log')
BrainzLab.development_events(event_type: 'error')
BrainzLab.development_events(event_type: 'trace')

# Filter by time
BrainzLab.development_events(since: 1.hour.ago)

# Limit results
BrainzLab.development_events(limit: 10)

# Combine filters
BrainzLab.development_events(
  service: :recall,
  since: 30.minutes.ago,
  limit: 50
)

# Get stats by service
BrainzLab.development_stats
# => { recall: 42, reflex: 3, pulse: 15 }

# Clear all stored events
BrainzLab.clear_development_events!

Console Output

In development mode, events are pretty-printed to stdout:

[14:32:15.123] [RECALL] log [INFO] User signed up
  user_id: 123
  data: {email: "user@example.com"}

[14:32:16.456] [REFLEX] error RuntimeError: Something went wrong
  error_class: "RuntimeError"
  environment: "development"
  request_id: "abc-123"

[14:32:17.789] [PULSE] trace GET /users (45.2ms)
  request_method: "GET"
  request_path: "/users"
  status: 200
  db_ms: 12.3

Use Cases

Development mode is useful for:

  • Local development without setting up a BrainzLab account
  • Testing SDK integration in CI/CD pipelines
  • Debugging to inspect exactly what events would be sent
  • Offline development when working without internet access

Self-Hosted

For self-hosted BrainzLab installations:

BrainzLab.configure do |config|
  config.recall_url = 'https://recall.your-domain.com'
  config.reflex_url = 'https://reflex.your-domain.com'
  config.pulse_url = 'https://pulse.your-domain.com'
end

Documentation

Full documentation: docs.brainzlab.ai

Related

Contributors

Thanks to all our contributors! See all-contributors for how to add yourself.

License

OSAaSy License - see LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors