Skip to main content

Backend Setup: Ruby

This guide walks you through instrumenting a Ruby application with the SF Veritas SDK. Ruby instrumentation captures logs, print statements, exceptions, HTTP request/response telemetry, and function execution spans.

Installation

Add the Gem Source

First, add the Sailfish gem repository:

gem sources -a https://ruby-gemrepo.sailfishqa.com/

Add sf-veritas to your Gemfile:

# Gemfile
gem 'sf-veritas', group: :development

Then install:

bundle install

Direct Install

gem install sf-veritas

Basic Setup

Add the following to your application's entry point. Use an environment variable check so instrumentation only runs during local development:

Setting SF_DEV=true

You must set the SF_DEV=true environment variable when running your app locally. This is how SF Veritas knows to activate. Add it as a prefix to your run command:

SF_DEV=true rails server
SF_DEV=true bundle exec rackup
SF_DEV=true ruby app.rb
# At the top of your application entry point
if ENV['SF_DEV'] == 'true'
require 'sf_veritas'

SfVeritas.setup_interceptors(
api_key: 'sf-veritas-local',
api_graphql_endpoint: 'http://localhost:6776/graphql/',
service_identifier: 'my-ruby-service',
service_version: '1.0.0'
)
end

# Your application code continues below...

Using a .env File

Instead of prefixing every command, create a .env file in your project root:

# .env
SF_DEV=true

Then load it in your application using the dotenv gem:

gem install dotenv
require 'dotenv/load'  # Loads .env file

if ENV['SF_DEV'] == 'true'
require 'sf_veritas'

SfVeritas.setup_interceptors(
api_key: 'sf-veritas-local',
api_graphql_endpoint: 'http://localhost:6776/graphql/',
service_identifier: 'my-ruby-service'
)
end
tip

Add .env to your .gitignore to avoid committing development settings. Create a .env.example file for reference:

# .env.example
SF_DEV=true

Configuration Options

OptionTypeRequiredDescription
api_keyStringYesUse "sf-veritas-local" for local development
api_graphql_endpointStringYesURL of the local collector (default port 6776)
service_identifierStringYesUnique name for your service
service_versionStringNoVersion of your service
service_display_nameStringNoDisplay name in the UI
git_shaStringNoGit commit SHA (auto-detected)
git_orgStringNoGit organization (auto-detected)
git_repoStringNoGit repository name (auto-detected)
git_providerStringNoGit provider (auto-detected)
sf_debugBooleanNoEnable debug logging to stderr
domains_to_not_propagate_headers_toArrayNoDomains to skip header propagation
routes_to_skip_network_hopsArrayNoRoutes to skip inbound tracing

What Gets Captured Automatically

Once setup_interceptors is called, these are captured with zero additional code:

  • Structured logs — All Ruby Logger output
  • Print statements — All $stdout / puts output
  • Exceptions — Unhandled exceptions with full stack traces
  • Outbound HTTP requests — Via Net::HTTP (automatic monkey-patch)
  • Inbound HTTP requests — Via Rack middleware (auto-installed in Rails, manual in Sinatra)

Framework Examples

Ruby on Rails

Rails integration is automatic via a Railtie. When the sf-veritas gem is loaded, the Rack middleware is auto-installed — no extra configuration needed.

Add to your config/environments/development.rb or config/initializers/sf_veritas.rb:

# config/initializers/sf_veritas.rb
if ENV['SF_DEV'] == 'true'
require 'sf_veritas'

SfVeritas.setup_interceptors(
api_key: 'sf-veritas-local',
api_graphql_endpoint: 'http://localhost:6776/graphql/',
service_identifier: 'rails-api',
service_version: '1.0.0'
)
end

Then start Rails with:

SF_DEV=true rails server
note

The Rack middleware for inbound request tracking is automatically inserted via a Rails Railtie. You don't need to add config.middleware.use manually.

Sinatra

For Sinatra, require the gem and add the middleware manually:

# app.rb
require 'sinatra'

if ENV['SF_DEV'] == 'true'
require 'sf_veritas'

SfVeritas.setup_interceptors(
api_key: 'sf-veritas-local',
api_graphql_endpoint: 'http://localhost:6776/graphql/',
service_identifier: 'sinatra-api',
service_version: '1.0.0'
)

use SfVeritas::Middleware
end

get '/api/users' do
puts 'Fetching users' # This will appear in SF Veritas Console
{ users: [] }.to_json
end

# Run with: SF_DEV=true ruby app.rb

Generic Rack

For any Rack-compatible application:

# config.ru
if ENV['SF_DEV'] == 'true'
require 'sf_veritas'

SfVeritas.setup_interceptors(
api_key: 'sf-veritas-local',
api_graphql_endpoint: 'http://localhost:6776/graphql/',
service_identifier: 'rack-app'
)

use SfVeritas::Middleware
end

run MyApp

Function Tracing

Manual Spans

Use SfVeritas.start_span for manual control over which functions appear in the Flamechart:

def process_order(order_id)
span = SfVeritas.start_span('OrderService#process_order',
arguments: { order_id: order_id }.to_json
)
begin
result = do_work(order_id)
span.finish(result)
result
rescue => e
span.finish(nil, error: e)
raise
end
end

Block Tracing

Use SfVeritas.trace for a cleaner block-based syntax that automatically handles finish and errors:

def process_order(order_id)
SfVeritas.trace('OrderService#process_order',
arguments: { order_id: order_id }.to_json
) do
do_work(order_id)
end
end

Automatic Function Capture (TracePoint)

For full automatic function tracing, set the SF_FUNCSPAN_AUTO_CAPTURE environment variable. This uses Ruby's TracePoint API to intercept all method calls in your application code:

SF_DEV=true SF_FUNCSPAN_AUTO_CAPTURE=true rails server

Auto-capture only instruments your application code — it automatically skips gems, stdlib, and SF Veritas internals.

User Identification

SfVeritas.identify('user-123', { email: 'user@example.com', name: 'Jane Doe', plan: 'enterprise' })

Exception Reporting

Exceptions are captured automatically, but you can also report them manually:

begin
risky_operation
rescue => e
SfVeritas::ExceptionHandler.report(e)
# Handle or re-raise
end

Environment Variables

VariableDefaultDescription
SF_DEBUGfalseEnable debug logging to stderr
SF_LOG_IGNORE_REGEXRegex to suppress matching log messages
SF_FUNCSPAN_AUTO_CAPTUREfalseEnable automatic function span capture via TracePoint
SF_FUNCSPAN_CAPTURE_ARGUMENTSfalseCapture function arguments
SF_FUNCSPAN_CAPTURE_RETURN_VALUEfalseCapture return values
SF_FUNCSPAN_ARG_LIMIT_MB1Max argument capture size in MB
SF_FUNCSPAN_RETURN_LIMIT_MB1Max return value capture size in MB
SF_FUNCSPAN_ENABLE_SAMPLINGfalseEnable span sampling
SF_FUNCSPAN_SAMPLE_RATE1.0Function span sampling rate (0.0 to 1.0)
SF_FUNCSPAN_AUTOCAPTURE_ALL_CHILD_FUNCTIONStrueAuto-capture all child function calls
SF_NETWORKHOP_CAPTURE_REQUEST_HEADERSfalseCapture HTTP request headers
SF_NETWORKHOP_CAPTURE_REQUEST_BODYfalseCapture HTTP request bodies
SF_NETWORKHOP_CAPTURE_RESPONSE_HEADERSfalseCapture HTTP response headers
SF_NETWORKHOP_CAPTURE_RESPONSE_BODYfalseCapture HTTP response bodies
SF_NETWORKHOP_REQUEST_LIMIT_MB1Max request body capture size in MB
SF_NETWORKHOP_RESPONSE_LIMIT_MB1Max response body capture size in MB
SF_DISABLE_INBOUND_NETWORK_TRACING_ON_ROUTESComma-separated routes to skip inbound tracing
SF_DISABLE_PRINT_CAPTUREfalseDisable stdout capture

Configuration File

Create a .sailfish file in your project root for per-file and per-function span configuration. Supports JSON, TOML, and YAML formats.

JSON

{
"funcspan": {
"default": {
"capture_arguments": true,
"capture_return_value": true,
"sample_rate": 1.0
},
"files": {
"app/models/*.rb": {
"capture_arguments": false
}
},
"functions": {
"User#save": {
"capture_arguments": true,
"capture_return_value": true,
"arg_limit_mb": 2
},
"HealthCheck#ping": {
"sample_rate": 0.0
}
}
}
}

TOML

[funcspan.default]
capture_arguments = true
capture_return_value = true
sample_rate = 1.0

[funcspan.files."app/models/*.rb"]
capture_arguments = false

[funcspan.functions."User#save"]
capture_arguments = true
capture_return_value = true
arg_limit_mb = 2

Inline Pragma

You can also add per-file configuration directly in your Ruby source files using a comment pragma in the first 50 lines:

# frozen_string_literal: true
# sailfish-funcspan: capture_arguments=true capture_return_value=false

class UsersController < ApplicationController
# ...
end

Configuration Priority

Settings are resolved in this order (highest priority first):

  1. Function-level.sailfish config functions section
  2. Inline pragma# sailfish-funcspan: comment in source file
  3. File-level.sailfish config files section (glob matching)
  4. Default.sailfish config default section
  5. Environment variablesSF_FUNCSPAN_* variables

Configuration Options

OptionTypeDescription
capture_argumentsboolCapture function arguments
capture_return_valueboolCapture return values
arg_limit_mbintMax argument size in MB
return_limit_mbintMax return value size in MB
sample_ratefloatSampling rate (0.0 to 1.0)
enable_samplingboolEnable span sampling
autocapture_all_childrenboolAuto-capture child function calls
capture_sf_veritasboolMaster kill switch for span capture
parse_json_stringsboolParse JSON string arguments into structured data

Verifying the Setup

  1. Start your application with SF_DEV=true:
    • Rails: SF_DEV=true rails server
    • Sinatra: SF_DEV=true ruby app.rb
    • Rack: SF_DEV=true bundle exec rackup
  2. Open the SF Veritas Desktop App
  3. Open the Console panel — you should see logs and print statements
  4. Trigger some HTTP requests — you should see them in the Network panel
  5. If using auto-capture or manual spans, open the Flamechart to see function traces

Debug Mode

Enable debug output to verify instrumentation is working:

SF_DEV=true SF_DEBUG=true rails server

You'll see output like:

[sf-veritas] Configuration: {...}
[sf-veritas] Initialized successfully (v0.1.0)

Troubleshooting

No logs appearing

  1. Check the desktop app: Ensure the SF Veritas Desktop App is running
  2. Verify the endpoint: Ensure api_graphql_endpoint matches your server port
  3. Check SF_DEV: Must be set to "true"
  4. Check terminal output: Look for [sf-veritas] initialization messages

Connection refused errors

  1. Verify the SF Veritas Desktop App is installed and running
  2. Check that the local server is running (look for server status in the Desktop App)
  3. Ensure port 6776 is not blocked by a firewall

Gem not found

  1. Ensure the Sailfish gem source is added: gem sources -l should include https://ruby-gemrepo.sailfishqa.com/
  2. Re-add if missing: gem sources -a https://ruby-gemrepo.sailfishqa.com/
  3. Run bundle install again if using Bundler
  4. Verify Ruby 2.6+ is installed: ruby --version

No function spans in Flamechart

  1. Ensure SF_FUNCSPAN_AUTO_CAPTURE=true is set (for automatic capture)
  2. Or verify you're using SfVeritas.start_span / SfVeritas.trace in your code (for manual capture)
  3. Check that SF_FUNCSPAN_CAPTURE_ARGUMENTS is not disabled if you expect argument capture

Multi-Service Setup

When running multiple Ruby services locally, give each a unique service_identifier:

# user-service/config/initializers/sf_veritas.rb
if ENV['SF_DEV'] == 'true'
require 'sf_veritas'
SfVeritas.setup_interceptors(
api_key: 'sf-veritas-local',
api_graphql_endpoint: 'http://localhost:6776/graphql/',
service_identifier: 'user-service',
service_version: '1.0.0'
)
end

# order-service/config/initializers/sf_veritas.rb
if ENV['SF_DEV'] == 'true'
require 'sf_veritas'
SfVeritas.setup_interceptors(
api_key: 'sf-veritas-local',
api_graphql_endpoint: 'http://localhost:6776/graphql/',
service_identifier: 'order-service',
service_version: '1.0.0'
)
end

Use the service filter in the Console to switch between services.

Next Steps