TraceKitTraceKit Docs
Backend SDKs

Ruby Integration Guide

Add TraceKit to your Ruby applications for automatic distributed tracing. Debug production Ruby services with live breakpoints and Rails/Sinatra support.

Learn how to instrument your Ruby applications with the TraceKit Ruby SDK for distributed tracing, metrics, and code monitoring.

Let AI set up TraceKit for you -- AI assistants can guide you through the entire setup process. Try AI Setup

Prerequisites

  • Ruby 2.7 or higher (Ruby 3.0+ recommended)
  • A TraceKit account (create one free)
  • A generated API key from the API Keys page

What Gets Traced Automatically?

With proper setup, these operations are traced automatically with zero manual instrumentation:

ComponentSpan TypeCaptured AttributesAuto-Traced?
HTTP EndpointsSERVERmethod, route, status_code, duration, client_ipYes
ActiveRecord QueriesDBdb.system, db.statement, db.name, durationYes
HTTP Client CallsCLIENTmethod, url, status_code, duration, peer.serviceYes
Redis OperationsDBdb.system (redis), db.statement, durationYes
Sidekiq JobsCustomjob.class, job.id, queue, durationYes
Custom Business LogicCustomuser-defined attributesManual

Installation

Add the TraceKit Ruby SDK to your Gemfile:

# Gemfile
gem 'tracekit'

# Then run:
bundle install

Basic Setup

Rails Applications (Auto-Configuration via .env)

For Rails applications, TraceKit automatically configures itself using environment variables:

# .env file
TRACEKIT_API_KEY=ctxio_abc123...
TRACEKIT_ENDPOINT=https://app.tracekit.dev
TRACEKIT_SERVICE_NAME=my-rails-app
TRACEKIT_ENVIRONMENT=production
TRACEKIT_CODE_MONITORING=true

# That's it! The TraceKit Railtie automatically:
# - Loads configuration from ENV variables
# - Initializes OpenTelemetry with OTLP exporters
# - Adds Rack middleware for request instrumentation
# - Sets up graceful shutdown

Non-Rails Applications (Manual Configuration)

For non-Rails applications, configure the SDK manually:

require 'tracekit'

# Configure the SDK
Tracekit.configure do |config|
  config.api_key = ENV['TRACEKIT_API_KEY']
  config.service_name = 'my-service'
  config.endpoint = 'https://app.tracekit.dev'
  config.environment = 'production'
  config.enable_code_monitoring = true
end

# For Rack applications, add middleware
use Tracekit::Middleware

# At application shutdown
at_exit { Tracekit.shutdown }

Verify It Works -- Start your application and make a few requests. Then open the Traces page in your TraceKit dashboard. You should see:

  • SERVER spans for each incoming request to Rails routes
  • CLIENT spans for outgoing HTTP calls (if using Net::HTTP/Faraday instrumentation)
  • DB spans for ActiveRecord queries (if instrumented)

Traces typically appear within 30 seconds. If you don't see them, check the Troubleshooting section.

Framework Integration

TraceKit SDK provides first-class support for popular Ruby frameworks with automatic instrumentation.

Ruby on Rails

# Your controllers are automatically traced!
class UsersController < ApplicationController
  def index
    # This action is automatically traced!
    @users = User.all
    render json: @users
  end

  def create
    sdk = Tracekit.sdk

    # Track metrics
    sdk.counter("user.created").add(1)

    # Capture snapshot with context
    sdk.capture_snapshot("user-create", {
      email: params[:email],
      name: params[:name]
    })

    @user = User.create!(user_params)
    render json: @user, status: :created
  end

  private

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

Sinatra

# app.rb
require 'sinatra'
require 'tracekit'

# Configure TraceKit
Tracekit.configure do |config|
  config.api_key = ENV['TRACEKIT_API_KEY']
  config.service_name = 'my-sinatra-app'
  config.endpoint = 'https://app.tracekit.dev'
end

# Add TraceKit middleware
use Tracekit::Middleware

# Routes are automatically traced!
get '/api/users' do
  sdk = Tracekit.sdk

  # Track metrics
  sdk.counter("api.users.requests").add(1)

  content_type :json
  User.all.to_json
end

Automatic Instrumentation Libraries

These libraries automatically create child spans for common operations. Set them up once, and every call is traced automatically.

ActiveRecord Queries

Automatically trace all database operations:

# ActiveRecord is automatically instrumented by TraceKit

# All queries are automatically traced!
User.all                    # Traced!
User.find(1)               # Traced!
User.where(active: true)   # Traced!
User.create(name: 'Alice') # Traced!

HTTP Client Calls

Automatically trace all outgoing HTTP requests:

# Net::HTTP is automatically instrumented by TraceKit

require 'net/http'

# All HTTP requests are automatically traced!
uri = URI('https://api.example.com/users')
response = Net::HTTP.get_response(uri)  # Traced!

Redis Operations

Trace Redis commands automatically:

# Redis operations are automatically traced by TraceKit
redis = Redis.new(host: 'localhost', port: 6379)

redis.set('key', 'value')  # Traced!
redis.get('key')           # Traced!

Manual Instrumentation (Optional)

For custom business logic that isn't covered by auto-instrumentation libraries, you can manually create spans. This is optional and only needed for specific operations you want to measure.

def process_order(order_id)
  sdk = Tracekit.sdk

  # Capture snapshot at key moments
  sdk.capture_snapshot("order-processing-start", {
    orderId: order_id,
    status: "processing"
  })

  # Track metrics
  sdk.counter("orders.processed").add(1)
  sdk.gauge("orders.active").inc

  # Validation logic here...

  # Track duration
  start_time = Time.now
  result = charge_payment(order_id)
  duration_ms = ((Time.now - start_time) * 1000).round(2)

  sdk.histogram("order.payment.duration").record(duration_ms)

  # Capture completion snapshot
  sdk.capture_snapshot("order-processing-complete", {
    orderId: order_id,
    status: "completed",
    duration: duration_ms
  })

  sdk.gauge("orders.active").dec
end

SDK.current API

Access the configured SDK singleton from anywhere in your application:

MethodParametersReturnsDescription
SDK.currentnoneSDKReturns the current SDK singleton instance. Use after SDK.configure().

SDK.current Example

# After configuration:
Tracekit::SDK.configure(config)

# Access anywhere in your application:
sdk = Tracekit::SDK.current
sdk.capture_snapshot("checkout", { order_id: order.id, total: total })
sdk.counter("orders.processed").inc

Supporting Types

Internal and advanced types used by the SDK (not intended for direct use):

SymbolTypeDescription
EndpointResolverClass (Internal)Resolves API endpoint URLs. Handles protocol selection and path construction.
LocalUI::DetectorClass (Internal)Detects when TraceKit Local UI is running on the configured port.
Security::DetectorClass (Advanced)Detects PII and credentials in snapshot variables. Automatically applied during capture.
Snapshots::ClientClass (Internal)Used for breakpoint polling and snapshot transmission. Use capture_snapshot() instead.

Code Monitoring (Live Debugging)

Production-Safe Live Debugging -- Capture variable state, stack traces, and request context at any point in your code without redeployment. Perfect for debugging production issues! Full Code Monitoring Documentation

Enable Code Monitoring

Enable code monitoring when initializing TraceKit:

# config/initializers/tracekit.rb
Tracekit::SDK.configure do |c|
  c.api_key              = ENV['TRACEKIT_API_KEY']
  c.service_name         = "my-rails-app"
  c.enable_code_monitoring = true  # defaults to true in Ruby SDK
end

Code monitoring defaults to true in the Ruby SDK. The snippet above is shown for clarity -- you can omit enable_code_monitoring and it will be enabled automatically.

Capture Snapshots

Use capture_snapshot to capture variable state at specific points:

# In a Rails controller
class OrdersController < ApplicationController
  def create
    order = Order.new(order_params)
    user  = current_user

    # Instance method -- capture via the SDK singleton
    sdk = Tracekit::SDK.current
    sdk.capture_snapshot('order-create', {
      order_id: order.id,
      total:    order.total,
      user_id:  user.id,
      items:    order.line_items.count
    })

    # Module convenience method -- same result, shorter syntax
    Tracekit.capture_snapshot('order-validate', {
      valid:  order.valid?,
      errors: order.errors.full_messages
    })

    if order.save
      redirect_to order_path(order)
    else
      render :new
    end
  end
end

Features

  • Auto-Registration -- Breakpoints automatically created on first capture_snapshot call
  • Variable Capture -- Deep inspection of hashes, arrays, and Ruby objects
  • Stack Traces -- Full call stack with file and line numbers via caller_locations
  • Request Context -- HTTP method, route, headers, and query params from Rack env

Production Safety

The Ruby SDK v6.0 includes multiple layers of production safety built into code monitoring:

  • PII Scrubbing -- 13 built-in patterns via Security::Patterns. Enabled by default with typed [REDACTED:type] markers for auditability.
  • Crash Isolation -- begin/rescue on all entry points. Snapshot failures never propagate to application code.
  • Circuit Breaker -- 3 failures in 60s triggers a 5-minute cooldown. Mutex-based thread safety for concurrent environments.
  • Remote Kill Switch -- Dashboard toggle to disable code monitoring instantly. Propagates to all SDK instances via SSE (Net::HTTP streaming in daemon thread).

Real-Time Updates -- The Ruby SDK receives configuration changes (kill switch, breakpoint updates) in real time via Server-Sent Events (SSE). The SSE connection uses Net::HTTP streaming in a daemon thread, so it does not block your application and is automatically cleaned up when the process exits.

Code Monitoring API

MethodParametersReturnsDescription
sdk.capture_snapshot(label, vars)label: String, vars: HashnilCapture variable state at this point. Only fires when a breakpoint is active.
Tracekit.capture_snapshot(label, vars)label: String, vars: HashnilModule-level convenience method. Delegates to SDK.current.capture_snapshot.
capture_depthIntegerDefault: 3Maximum depth for nested object inspection.
max_payloadInteger (bytes)Default: 65536Maximum size of a single snapshot payload.
capture_timeoutFloat (seconds)Default: 5.0Timeout for snapshot capture and transmission.
pii_scrubbingBooleanDefault: trueEnable PII scrubbing via Security::Patterns.
circuit_breakerHashDefault: { threshold: 3, window: 60, cooldown: 300 }Circuit breaker configuration.

End-to-End Workflow

  1. Enable Code Monitoring -- Defaults to enabled in the Ruby SDK. Explicitly set for clarity or use TRACEKIT_CODE_MONITORING=true.
  2. Add Capture Points -- Place capture_snapshot calls at code paths you want to debug.
  3. Deploy and Verify Traces -- Deploy and check the Traces dashboard.
  4. Navigate to Code Monitoring -- Go to /snapshots and click "Browse Code".
  5. Set Breakpoints -- Auto-registered on first capture_snapshot call, or manually via the UI.
  6. Trigger a Capture -- Make a request that hits a code path with capture_snapshot.
  7. View Snapshot -- Inspect variables, call stack, request context, security flags, and trace link.

LLM Instrumentation

TraceKit automatically instruments OpenAI and Anthropic API calls when detected. LLM calls appear as spans with OTel GenAI semantic convention attributes.

Zero-config auto-instrumentation -- If the openai or anthropic gem is installed, TraceKit patches them automatically via Module#prepend at init. No code changes required.

Captured Attributes

AttributeDescription
gen_ai.systemProvider name (openai, anthropic)
gen_ai.request.modelModel name (gpt-4o, claude-sonnet-4-20250514, etc.)
gen_ai.usage.input_tokensPrompt token count
gen_ai.usage.output_tokensCompletion token count
gen_ai.response.finish_reasonsFinish reason (stop, end_turn, tool_calls)

Configuration

Tracekit.configure do |c|
  c.api_key = ENV['TRACEKIT_API_KEY']
  c.service_name = 'my-ruby-service'
  c.llm.enabled = true          # Master toggle
  c.llm.openai = true           # OpenAI instrumentation
  c.llm.anthropic = true        # Anthropic instrumentation
  c.llm.capture_content = false # Capture prompts/completions (off by default)
end

Environment Variable Override

Use TRACEKIT_LLM_CAPTURE_CONTENT=true to enable prompt/completion capture without code changes. Useful for enabling in staging but not production.

Streaming Support

Streaming responses produce a single span that covers the entire stream. Token counts are accumulated from the final chunk. No special configuration needed.

LLM Dashboard

View LLM cost, token usage, and latency metrics on the dedicated LLM Observability dashboard at /ai/llm in your TraceKit instance.

Environment Variables

Best practice: Store sensitive configuration in environment variables:

# .env
TRACEKIT_API_KEY=ctxio_your_generated_api_key_here
TRACEKIT_ENDPOINT=https://app.tracekit.dev
TRACEKIT_SERVICE_NAME=my-rails-app
TRACEKIT_ENVIRONMENT=production
TRACEKIT_CODE_MONITORING=true

Config Fields Reference

FieldTypeDefaultDescription
api_keyStringrequiredYour TraceKit API key for authentication
service_nameString"ruby-app"Name of your service in the trace dashboard
endpointString"app.tracekit.dev"TraceKit collector endpoint URL
enabledBooleantrueEnable or disable tracing globally
sample_rateFloat1.0Trace sampling rate (0.0 to 1.0)
enable_code_monitoringBooleanfalseEnable live code debugging / snapshot capture

These fields are set via Config.build { |c| c.api_key = '...' } block syntax or through the Tracekit.configure block.

Environment Variable Reference

OptionTypeDefaultEnv VariableDescription
api_keyStringrequiredTRACEKIT_API_KEYYour TraceKit API key for authentication
service_nameStringrequiredTRACEKIT_SERVICE_NAMEName of your service in the trace dashboard
endpointString"app.tracekit.dev"TRACEKIT_ENDPOINTTraceKit collector endpoint URL
use_sslBooleantrueTRACEKIT_USE_SSLEnable TLS for the exporter connection
environmentString"production"TRACEKIT_ENVIRONMENTDeployment environment
service_versionString"1.0.0"TRACEKIT_SERVICE_VERSIONVersion of your service
enable_code_monitoringBooleantrueTRACEKIT_CODE_MONITORING_ENABLEDEnable live code debugging
code_monitoring_poll_intervalInteger30TRACEKIT_CODE_MONITORING_POLL_INTERVALHow often to poll for active breakpoints (seconds)
local_ui_portInteger9999TRACEKIT_LOCAL_UI_PORTPort for the local development UI
sampling_rateFloat1.0TRACEKIT_SAMPLE_RATETrace sampling rate (0.0 to 1.0)

The Ruby SDK does not auto-read environment variables. Read them with ENV['TRACEKIT_*'] and pass to the builder.

Production Configuration

Production Checklist:

  • Use HTTPS/TLS for the OTLP endpoint
  • Store API keys in a secrets manager (AWS Secrets Manager, HashiCorp Vault)
  • Set appropriate service names and versions
  • Configure resource attributes (deployment.environment, host.name, etc.)
  • Adjust sampling rates if needed for high-traffic services

Troubleshooting

Traces not appearing?

Cause: The SDK is not initialized or required gems are missing.

Fix:

  • Verify Tracekit.configure block is called at application startup (in an initializer for Rails)
  • Check that api_key is set
  • Look for errors in application logs
  • Confirm sampling_rate is not 0

Missing gem errors?

Cause: Ruby OTel gems must be explicitly listed in the Gemfile.

Fix:

  • Add all required gems: gem 'tracekit', gem 'opentelemetry-api', gem 'opentelemetry-sdk', and any instrumentation gems
  • Run bundle install
  • Verify with bundle list | grep opentelemetry

Code monitoring not working?

Cause: The capture_snapshot method is not being called or permissions are insufficient.

Fix:

  • Code monitoring defaults to true in the Ruby SDK
  • Add Tracekit.capture_snapshot('label') calls in your code
  • Reduce code_monitoring_poll_interval to 5 for testing
  • Verify API key permissions in the dashboard

Authentication errors (401/403)?

Cause: API key is missing, empty, or invalid.

Fix:

  • Verify with puts ENV['TRACEKIT_API_KEY'] in Rails console
  • Ensure no extra whitespace: api_key: ENV['TRACEKIT_API_KEY']&.strip
  • Regenerate key in dashboard if expired

Connection refused errors?

Cause: The TraceKit endpoint is unreachable or SSL configuration is wrong.

Fix:

  • Test with curl -X POST https://app.tracekit.dev/v1/traces (expect 401)
  • Verify use_ssl: true (default) for production
  • For local development without TLS, set use_ssl: false
  • Check that endpoint does not include the protocol prefix if use_ssl is being used

Complete Example

Here's a complete working Rails example:

# Complete Rails example with TraceKit SDK

# Gemfile
gem 'tracekit'

# .env
TRACEKIT_API_KEY=ctxio_your_generated_api_key_here
TRACEKIT_ENDPOINT=https://app.tracekit.dev
TRACEKIT_SERVICE_NAME=rails-api
TRACEKIT_ENVIRONMENT=production
TRACEKIT_CODE_MONITORING=true

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    # Automatically traced - no code changes needed!
    @users = User.all
    render json: @users
  end

  def show
    # Automatically traced - no code changes needed!
    @user = User.find(params[:id])
    render json: @user
  end

  def create
    sdk = Tracekit.sdk

    # Track metrics
    sdk.counter("users.created").add(1)

    # Capture snapshot for debugging
    sdk.capture_snapshot("user-creation", {
      email: params[:email],
      name: params[:name]
    })

    @user = User.create!(user_params)
    render json: @user, status: :created
  end

  private

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

# That's it! Your Rails app now has:
# - Distributed tracing with automatic span creation
# - Metrics collection (counters, gauges, histograms)
# - Code monitoring with non-breaking snapshots

You're all set! Your Ruby application is now sending traces to TraceKit. Visit the Dashboard to see your traces.

Custom Metrics

The TraceKit Ruby SDK includes a lightweight metrics API for tracking counters, gauges, and histograms.

Counter

Track monotonically increasing values (requests, events):

sdk = Tracekit.sdk

# Create a counter with tags
counter = sdk.counter("http.requests.total", {
  service: "api",
  endpoint: "/users"
})

# Increment the counter
counter.add(1)
counter.add(5)  # Add specific value

Gauge

Track values that can go up or down (queue size, connections):

sdk = Tracekit.sdk

# Create a gauge
gauge = sdk.gauge("memory.usage.bytes")

# Set absolute value
gauge.set(1024 * 1024 * 512)  # 512 MB

# Increment/decrement
gauge.inc      # +1
gauge.inc(10)  # +10
gauge.dec      # -1
gauge.dec(5)   # -5

Histogram

Track value distributions (latencies, sizes):

sdk = Tracekit.sdk

# Create a histogram with tags
histogram = sdk.histogram("http.request.duration", {
  unit: "ms"
})

# Record values
histogram.record(123.45)
histogram.record(67.89)

Metrics are automatically buffered and exported via OTLP. View them in the Metrics Explorer.

View Custom Metrics Guide

Migrating from OpenTelemetry

TraceKit wraps OpenTelemetry internally, so you get the same standards-based trace data with significantly less setup code.

Before vs After

Before: Raw OpenTelemetry (~15 lines):

require 'opentelemetry/sdk'
require 'opentelemetry-exporter-otlp'

OpenTelemetry::SDK.configure do |c|
  c.service_name = 'my-service'
  c.add_span_processor(
    OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
      OpenTelemetry::Exporter::OTLP::Exporter.new(
        endpoint: 'https://api.tracekit.io/v1/traces',
        headers: { 'Authorization' => "Bearer #{api_key}" }
      )
    )
  )
  c.use_all # auto-instrumentation
end

After: TraceKit SDK (4 lines):

# Rails: just set .env vars (auto-configured via Railtie)
# TRACEKIT_API_KEY=your-api-key
# TRACEKIT_SERVICE_NAME=my-service

# Non-Rails:
Tracekit.configure do |c|
  c.api_key = ENV['TRACEKIT_API_KEY']
  c.service_name = 'my-service'
end

Migration Steps

  1. Add the gem: bundle add tracekit
  2. Replace init code: Remove the OpenTelemetry::SDK.configure block and replace with Tracekit.configure
  3. For Rails: Set TRACEKIT_API_KEY and TRACEKIT_SERVICE_NAME in .env -- auto-configured via Railtie
  4. Remove OTel gems: bundle remove opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
  5. Verify: Start your app and check the Traces page for incoming data

Key Migration Benefits:

  • 15 lines to 4 lines -- no more boilerplate for exporters, processors, resources
  • No OTel dependency management -- TraceKit handles version pinning internally
  • Built-in code monitoring -- not available with raw OpenTelemetry
  • Built-in security scanning -- automatic variable redaction on snapshots
  • Rails auto-configuration -- Railtie handles setup from .env vars automatically

Performance Overhead

TraceKit is built on OpenTelemetry's efficient batch processing pipeline. The SDK adds minimal overhead to your Ruby application.

MetricImpactDetails
Request Tracing< 2ms per requestSpans are batched and exported asynchronously
Code Monitoring (Idle)Zero overheadNo performance impact when no active breakpoints
Code Monitoring (Capture)< 5ms per snapshotIncludes variable serialization and security scanning
Memory Footprint~15-25 MBSDK runtime and span buffer
SDK Initialization< 300ms one-timeIncludes OpenTelemetry provider setup and auto-instrumentation

Performance characteristics are typical for production workloads and may vary with application complexity, request volume, and number of instrumented libraries. Use sampling configuration to reduce overhead in high-traffic services.

Best Practices

DO:

  • For Rails, rely on Railtie auto-init -- just add the gem and configure via environment variables
  • For non-Rails apps (Sinatra), init in config.ru before run
  • Use environment variables for API keys -- store in TRACEKIT_API_KEY rather than hardcoding
  • Enable code monitoring in staging first before production
  • Use sampling in high-traffic services -- set TRACEKIT_SAMPLING_RATE below 1.0
  • Set meaningful service names for easy identification in the trace viewer

DON'T:

  • Call Tracekit.configure in Rails apps -- the Railtie handles initialization automatically
  • Create spans for every function -- trace boundaries like HTTP handlers, DB calls, and external services
  • Add high-cardinality attributes -- avoid user IDs, request IDs, or session tokens as span attributes
  • Disable TLS in production -- the TRACEKIT_INSECURE flag is for local development only

Next Steps

  • Add auto-instrumentation libraries for components you use (Redis, Sidekiq, MongoDB, etc.)
  • Explore your traces on the Traces page to identify performance bottlenecks
  • Optionally add custom spans for specific business logic you want to measure
  • Configure sampling for high-traffic services to reduce overhead
  • Set up alert rules to get notified when issues occur

On this page