Complete setup for Rails, Sinatra, and standalone Ruby applications.
# Gemfile
gem 'honeybadger'
gem 'sentry-ruby'
gem 'sentry-rails' # For Rails
gem 'devcycle-ruby-server-sdk'
gem 'appwrite'bundle installSentry.init do |config|
config.dsn = ENV['SENTRY_DSN']
config.environment = Rails.env
config.traces_sample_rate = 0.1
config.breadcrumbs_logger = [:active_support_logger, :http_logger]
end# Or run: bundle exec honeybadger install [API_KEY]
Honeybadger.configure do |config|
config.api_key = ENV['HONEYBADGER_API_KEY']
config.env = Rails.env
endrequire 'devcycle-ruby-server-sdk'
$devcycle_client = DevCycle::Client.new(
ENV['DEVCYCLE_SERVER_SDK_KEY'],
DevCycle::Options.new(enable_cloud_bucketing: true)
)require 'appwrite'
$appwrite_client = Appwrite::Client.new
.set_endpoint(ENV['APPWRITE_ENDPOINT'])
.set_project(ENV['APPWRITE_PROJECT_ID'])
.set_key(ENV['APPWRITE_API_KEY'])
$appwrite_databases = Appwrite::Databases.new($appwrite_client)module Monitoring
class << self
def capture_error(error, context = {})
# Log locally
Rails.logger.error("#{error.class}: #{error.message}")
Rails.logger.error(error.backtrace.join("\n")) if error.backtrace
# Report to Sentry
Sentry.capture_exception(error, extra: context)
# Report critical errors to Honeybadger
if error.respond_to?(:critical?) && error.critical?
Honeybadger.notify(error, context: context)
end
end
def capture_message(message, level: :info, context: {})
Sentry.capture_message(message, level: level, extra: context)
end
end
end
# Usage in controllers
class ApplicationController < ActionController::Base
rescue_from StandardError do |exception|
Monitoring.capture_error(exception, {
user_id: current_user&.id,
path: request.path
})
raise exception
end
endmodule FeatureFlags
class << self
def enabled?(user, flag_key, default: false)
devcycle_user = DevCycle::User.new(user_id: user.id.to_s)
$devcycle_client.variable_value(devcycle_user, flag_key, default)
rescue => e
Monitoring.capture_error(e, { flag_key: flag_key })
default
end
def get_value(user, flag_key, default)
devcycle_user = DevCycle::User.new(
user_id: user.id.to_s,
email: user.email,
custom_data: { plan: user.plan }
)
$devcycle_client.variable_value(devcycle_user, flag_key, default)
rescue => e
Monitoring.capture_error(e, { flag_key: flag_key })
default
end
end
end
# Usage in controllers
class CheckoutController < ApplicationController
def show
if FeatureFlags.enabled?(current_user, 'new-checkout')
render :new_checkout
else
render :legacy_checkout
end
end
end
# Usage in views
<% if FeatureFlags.enabled?(current_user, 'show-banner') %>
<%= render 'banner' %>
<% end %>
module AppwriteService
class << self
def create_document(database_id, collection_id, data)
$appwrite_databases.create_document(
database_id: database_id,
collection_id: collection_id,
document_id: Appwrite::ID.unique,
data: data
)
end
def list_documents(database_id, collection_id, queries: [])
$appwrite_databases.list_documents(
database_id: database_id,
collection_id: collection_id,
queries: queries
)
end
def get_document(database_id, collection_id, document_id)
$appwrite_databases.get_document(
database_id: database_id,
collection_id: collection_id,
document_id: document_id
)
end
end
end
# Usage
AppwriteService.create_document('main', 'users', {
name: 'John',
email: 'john@example.com'
})require 'sinatra'
require 'sentry-ruby'
require 'honeybadger'
Sentry.init do |config|
config.dsn = ENV['SENTRY_DSN']
end
Honeybadger.configure do |config|
config.api_key = ENV['HONEYBADGER_API_KEY']
end
use Sentry::Rack::CaptureExceptions
error do
error = env['sinatra.error']
Honeybadger.notify(error)
'Something went wrong'
end
get '/' do
'Hello World'
endSidekiq.configure_server do |config|
config.error_handlers << proc { |ex, ctx_hash|
Sentry.capture_exception(ex, extra: ctx_hash)
Honeybadger.notify(ex, context: ctx_hash)
}
endclass ExampleJob
include Sidekiq::Job
def perform(user_id)
user = User.find(user_id)
# Add context for error tracking
Sentry.set_user(id: user.id, email: user.email)
Honeybadger.context(user_id: user.id)
# Your job logic
do_work(user)
rescue => e
Monitoring.capture_error(e, { user_id: user_id })
raise
end
end# .env
# Sentry
SENTRY_DSN=https://key@sentry.io/project
# Honeybadger
HONEYBADGER_API_KEY=your_key
# DevCycle
DEVCYCLE_SERVER_SDK_KEY=server_key
# Appwrite
APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
APPWRITE_PROJECT_ID=your_project
APPWRITE_API_KEY=your_api_keyrequire 'rails_helper'
RSpec.describe FeatureFlags do
let(:user) { create(:user) }
before do
allow($devcycle_client).to receive(:variable_value).and_return(true)
end
describe '.enabled?' do
it 'returns the flag value' do
expect(described_class.enabled?(user, 'new-feature')).to be true
end
it 'returns default on error' do
allow($devcycle_client).to receive(:variable_value).and_raise(StandardError)
expect(described_class.enabled?(user, 'new-feature', default: false)).to be false
end
end
endRSpec.configure do |config|
config.before(:each) do
allow(Sentry).to receive(:capture_exception)
allow(Honeybadger).to receive(:notify)
end
endnamespace :monitoring do
desc 'Test Sentry connection'
task test_sentry: :environment do
Sentry.capture_message('Test message from rake task')
puts 'Sentry test message sent'
end
desc 'Test Honeybadger connection'
task test_honeybadger: :environment do
Honeybadger.notify(StandardError.new('Test error from rake task'))
puts 'Honeybadger test error sent'
end
endnamespace :scheduled do
desc 'Daily cleanup task'
task cleanup: :environment do
# Start check-in
Honeybadger.check_in('daily-cleanup')
begin
# Your task logic
cleanup_old_records
rescue => e
Monitoring.capture_error(e)
raise
end
end
end