Skip to content

Latest commit

 

History

201 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Railwatch

First-class monitoring for Rails. One gem instruments requests, jobs, scheduled tasks, commands, queries, exceptions, cache, mail, broadcasts, outgoing HTTP, storage, views, and logs, and links them into one trace per execution, for about half a millisecond per request plus tens of microseconds per query, with zero writes to your database.

By default all of it stays inside the app: embedded mode serves the full dashboard at /railwatch out of two SQLite files your app owns, with no token, no Node, no Redis and no job worker. Railwatch Cloud is optional: it delivers alerts to Slack, email, webhooks or Linear (including when the app is down), serves MCP to your AI assistant, and puts many apps and servers in one place.

Install

bundle add railwatch                  # 1. add the public gem
bin/rails generate railwatch:install  # 2. embedded: databases, Puma writer, dashboard at /railwatch

Restart and open /railwatch. It is open in development; before you deploy, give it a password with RAILS_ENV=production bin/rails railwatch:authentication:configure (it answers 401 in production until you do). On a PostgreSQL or MySQL app without the sqlite3 gem, the generator adds it to the Gemfile; run bundle install and bin/rails db:prepare to finish.

To send everything to Railwatch Cloud instead, pass --cloud or a token option:

bundle add railwatch
bin/rails generate railwatch:install --prompt-token  # hidden token input plus app wiring
bin/rails railwatch:doctor                          # check every piece is wired up after restart

The generator's flags, getting a token, and deploying with Kamal, Docker, Heroku, or Render are covered in Getting started. For an unreleased revision, use the Git source instead:

gem "railwatch", github: "Rebulk/railwatch"

What you get

  • Requests, jobs, scheduled tasks, commands, queries, exceptions, and logs, linked into one trace per execution (Record types).
  • Sampling decided once per execution, plus tail sampling that keeps a sampled-out request that turns out slow or raises (Configuration).
  • An optional stack profiler through vernier or stackprof, off by default (Configuration).
  • LLM calls made through RubyLLM: tokens, cost, cut-off answers, tool calls and workflows, each tied to the request or job that made it (Record types).
  • A browser client for Inertia apps: page-visit timing, Core Web Vitals, and browser errors (Getting started).
  • RSpec and Minitest matchers that turn a query budget into a CI gate (Testing).
  • With Railwatch Cloud, an MCP server so Claude Code, Cursor, VS Code, or Zed can read your production data (AI assistants and MCP).

Configuration lives in config/initializers/railwatch.rb; most options also have a RAILWATCH_* environment variable.

Railwatch.configure do |c|
  c.sample = { requests: 0.1, jobs: 1.0 }
  c.user { |u| { id: u.id, name: u.name, email: u.email } }
end

The same instrumentation runs in your test suite, so a spec can hold a hot path to a query budget:

expect { get "/widgets" }.to have_railwatch_queries(at_most: 6)
expect { get "/widgets" }.not_to have_railwatch_n_plus_one

Embedded mode

Telemetry goes to two SQLite files the app owns -- railwatch for issues, comments and saved views, railwatch_telemetry for what the app reports -- and the dashboard is served at /railwatch from a bundle shipped inside the gem. Nothing leaves the machine unless you turn on export to Railwatch Cloud, and there is nothing else to run.

Puma forks a single writer process (plugin :railwatch, which the installer adds) that owns both files. The web workers hand it batches over a Unix socket instead of writing SQLite on their own threads, and it runs the maintenance clock too, so exception grouping, rollups, retention and threshold scans happen without a queue.

That dashboard reads every query, log line and exception the app produced, so it is gated the way Mission Control Jobs is: HTTP Basic is on, and with no credentials every request is 401 until you set them with bin/rails railwatch:authentication:configure. Development is the exception: with no credentials set there, it is open. Apps that would rather use their own authentication turn Basic off and gate the pages with base_controller_class or a routes constraint around the mount; a dashboard_user resolver then names the operator and authorizes live updates, but does not gate pages. Embedded mode covers all of it, including upgrades and what it costs to store.

Documentation

  • Getting started — the embedded install, the Railwatch Cloud install and its token, the three optional lines, and deploying with Kamal, Docker, Heroku, Render, or none of them.
  • Configuration — every option and RAILWATCH_* variable, field by field.
  • Record types — every record Railwatch ships and every attribute on it, sourced from the code that builds it.
  • Testing — the RSpec and Minitest matchers, and a CI performance gate.
  • AI assistants and MCP — connecting Claude Code, Cursor, VS Code, or Zed to your production data through Railwatch Cloud.
  • Replacing Sentry — a step-by-step migration, option by option and call site by call site.
  • Coming from Laravel Nightwatch — the record-type mapping and the sampling model, for Laravel people.
  • Embedded mode — the default: the whole dashboard inside your app, telemetry in your own SQLite files, and optional export to Railwatch Cloud.
  • Self-hosting — pointing the gem at your own Railwatch Cloud.
  • Troubleshooting — every failure mode, paired with the railwatch:doctor line it shows up as.
  • FAQ — overhead numbers, retention, PII posture, SQLite.
  • Security — transport, capture defaults, the browser beacon, and application responsibilities.

AI coding agents working on an app that uses Railwatch: llms.txt and AGENTS.md.

Replacing Sentry

Railwatch subscribes to Rails.error on install, so existing Rails.error.report and Rails.error.handle calls are captured with no code changes. Each exception is linked to the request, job, or command it happened inside. The option-by-option mapping and the supported-workload matrix live in Replacing Sentry.

Development

bundle install
bundle exec rspec

About

Railwatch: first-class monitoring for Rails. The gem.

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages