Skip to content
Knowledge base

Track errors in Rails, Rack and Sidekiq

The Ruby gem: one Gemfile line, a DSN, and unhandled exceptions from web requests and background jobs land as issues.

1. Add the gem

gem "realuptime-errors", git: "https://github.com/RealUptimeHQ/realuptime-errors-ruby", require: "realuptime/errors/rails" in your Gemfile, then bundle install. It installs from GitHub today; a RubyGems package is coming. The gem is MIT and has zero runtime dependencies: standard library only, enforced by its own test suite, so it cannot drag a transitive dependency into your app.

2. Give it a DSN

Set REALUPTIME_ERRORS_DSN in the environment, or Rails.application.config.realuptime_errors.dsn in an initializer, to the ingest URL from your project's dashboard. The Railtie initializes itself from either one, so an app that sets the environment variable needs no initializer at all. A missing DSN logs once and the SDK stays inert: it never raises at boot.

3. Let the Railtie do the wiring

Requiring realuptime/errors/rails installs three things through the one capture path: Rack middleware at the outermost position of the stack, so an exception that escapes (or one Rails swallowed into its own error page) is reported exactly once with method, path and the matched controller#action; an ActiveJob hook that reports a job's unhandled exception and re-raises, so retry_on and discard_on behave exactly as before; and per-request context. Route templates carry controller and action names only, never the :id and other path parameter values.

4. Plain Rack, without Rails

For Sinatra, Hanami, or a bare Rack app: require "realuptime/errors", call Realuptime::Errors.init(dsn: ...), then use Realuptime::Errors::RackMiddleware. It captures the unhandled exception with minimal request context and re-raises, so your own error handling is unchanged.

5. Sidekiq jobs

require "realuptime/errors/sidekiq" and call Realuptime::Errors::Sidekiq.install in your Sidekiq initializer. Each failure is reported with the worker class in the fingerprint, so ArgumentError in ChargeWorker and ArgumentError in MailWorker stay separate issues, plus queue and retry count as tags, then re-raised so retries and the dead set work untouched. Job arguments are never captured: that is where your users' data lives.

6. Know what gets scrubbed

Scrubbing runs inside your process before anything is serialized, and there is no switch to turn it off. Authorization, Proxy-Authorization and Cookie headers are replaced whole. Card-shaped digit runs that pass a Luhn check, JWTs, prefixed API keys and long high-entropy strings are replaced with [scrubbed] anywhere they appear. user.email and user.username are removed unless you name them: allow_fields: ["user.email"] in init, per field, in code. The gem is tested against the same scrub vector file as the JavaScript and Python SDKs, byte for byte, so all three behave identically.

7. Understand the buffer and the drop count

Events go into a bounded in-memory buffer (200 events) and ship on a background thread, re-spawned automatically after a fork so Puma and Unicorn workers keep reporting. Delivery backs off exponentially from 5 seconds to 5 minutes, pauses when you are over quota, and disables itself for the process if the key is revoked. If the buffer overflows, the oldest event is evicted and counted, and the count rides the next successful batch, so client-side drops show on your dashboard instead of vanishing. Call Realuptime::Errors.flush before a process exits deliberately; an at_exit flush is installed for you.

Go deeper

The full reference lives in the docs: Getting started documentation. Error codes named above are each explained in the error-code reference.