0.0
The project is in a healthy, maintained state
Captures unhandled exceptions from controllers, Rack, Sidekiq and ActiveJob, deduplicates them by fingerprint, and exposes a kanban dashboard (and optional RailsAdmin board) to triage them as tasks.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 1.4

Runtime

>= 7.0, < 9
 Project Readme

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 to enum :name, {...} (see app/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 chartkick dependency); the kanban uses SortableJS.