Error Radar
Drop-in error tracking & task board for Rails apps. Captures unhandled
exceptions from controllers, Rack, Sidekiq and ActiveJob, deduplicates them
by fingerprint (a flood of the same failure stays one task with an occurrence
count), and ships a kanban dashboard — plus an optional RailsAdmin board — to
triage them as tasks (open → in_progress → resolved → ignored).
It is built as a mountable Rails Engine, so the model, middleware, routes, dashboard and migration all come from the gem. Everything app-specific (authentication, custom exception types, server expectations) is injected via a small config block.
Requirements
- Rails
>= 7.0, Ruby>= 3.0 - Optional: Sidekiq (job capture + server panel), RailsAdmin (admin board)
Rails 8 note: the model uses the classic
enum name: {...}form. On Rails 8 switch it toenum :name, {...}(seeapp/models/error_radar/error_log.rb).
Install
# Gemfile
gem 'error_radar', git: 'https://github.com/chienbn9x/error_radar.git'
# or, while developing locally:
gem 'error_radar', path: '../error_radar'
bundle install
bin/rails generate error_radar:install # creates initializer + migration
bin/rails db:migrate
Mount the dashboard:
# config/routes.rb
authenticate :admin do # your own guard, optional
mount ErrorRadar::Engine, at: '/monitoring'
end
Visit /monitoring.
Configure
config/initializers/error_radar.rb (generated):
ErrorRadar.configure do |config|
config.enabled = !Rails.env.test?
# Dashboard auth
config.authenticate = ->(controller) { controller.send(:authenticate_admin!) }
config.current_user = ->(controller) { controller.current_admin&.email }
# Teach it about your own API error type
config.categorize { |e| :external_api if e.is_a?(MyApi::Error) }
config.extract_details do |e|
{ http_status: e.status, request_url: e.url, api_code: e.code } if e.is_a?(MyApi::Error)
end
end
Use
# Capture an exception with context
ErrorRadar.capture(e, source: 'HealthController#index', context: { check: :redis })
# Log a problem without an exception
ErrorRadar.notify('Webhook signature mismatch', category: :external_api, severity: :warning)
# Wrap a boundary the middleware/Sidekiq hooks don't cover (rake tasks, cron)
ErrorRadar.monitor('NightlyReindex', context: { batch: 1 }) { do_work }
Web requests and Sidekiq jobs are captured automatically once installed. For non-Sidekiq ActiveJob adapters, include the concern:
class ApplicationJob < ActiveJob::Base
include ErrorRadar::Integrations::ActiveJob
end
What gets stored
ErrorRadar::ErrorLog (error_radar_error_logs): category, severity, status,
error_class, source, message, backtrace, JSON context, HTTP/API fields,
occurrence count, first/last seen, and resolution metadata. Identical errors
roll up by a SHA1 fingerprint of (category, error_class, source,
normalized_message).
Design notes
- Never raises. Every capture path rescues internally and logs to
Rails.logger— error tracking must not break the code it watches. - Decoupled. No host model, controller or constant is referenced directly;
app-specifics arrive through
ErrorRadar.config. - Self-contained dashboard. Charts use Chart.js from a CDN (no
chartkickdependency); the kanban uses SortableJS. ```