bugwatch-ruby
Official Ruby/Rails SDK for BugWatch — open-source error monitoring.
Installation
# Gemfile
gem "bugwatch-ruby"
bundle install
Configuration
# config/initializers/bugwatch.rb
Bugwatch.configure do |c|
c.api_key = ENV["BUGWATCH_API_KEY"]
c.endpoint = ENV["BUGWATCH_ENDPOINT"] # e.g. "https://your-app.herokuapp.com"
c.release_stage = Rails.env.to_s
c.notify_release_stages = ["production", "staging"]
c.ignore_classes = ["ActionController::RoutingError"]
c.app_version = ENV["GIT_REV"] # optional git SHA
end
User context
# app/controllers/application_controller.rb
before_action :set_bugwatch_user
private
def set_bugwatch_user
return unless current_user
Bugwatch.set_user(
id: current_user.id,
email: current_user.email,
name: current_user.name
)
end
Breadcrumbs
Bugwatch.("User clicked checkout", type: "ui", metadata: { cart_id: 42 })
Manual notification
begin
risky_operation
rescue => e
Bugwatch.notify(e)
raise
end
Deploy tracking
Track deploys so BugWatch can correlate new errors with releases.
Bugwatch.track_deploy(
version: "abc1234",
environment: "production", # defaults to config.release_stage
description: "Deployed abc1234",
deployed_by: "ci"
)
Heroku
On Heroku, SOURCE_VERSION (the git SHA) is available during the build phase but not during the release phase. The recommended approach is to bake the SHA into a REVISION file at build time, then read it at release time.
1. Create a Rake task in lib/tasks/bugwatch.rake:
namespace :bugwatch do
task write_revision: :environment do
revision = ENV["SOURCE_VERSION"] || `git rev-parse HEAD 2>/dev/null`.strip
if revision.present?
File.write(Rails.root.join("REVISION"), revision)
puts "Bugwatch: wrote REVISION #{revision[0..6]}"
end
end
task track_deploy: :environment do
revision_file = Rails.root.join("REVISION")
version = ENV["SOURCE_VERSION"] \
|| (File.read(revision_file).strip if File.exist?(revision_file)).presence \
|| Time.now.utc.strftime("%Y%m%d%H%M%S")
thread = Bugwatch.track_deploy(
version: version,
description: "Deployed #{version[0..6]}",
deployed_by: ENV["BUGWATCH_DEPLOYED_BY"] || "heroku"
)
thread&.join(5)
puts "Bugwatch: tracked deploy #{version[0..6]}"
end
end
# Bake the SHA into the slug during assets:precompile
if Rake::Task.task_defined?("assets:precompile")
Rake::Task["assets:precompile"].enhance(["bugwatch:write_revision"])
end
2. Add the deploy task to your Procfile release phase:
release: bundle exec rails db:migrate && bundle exec rails bugwatch:track_deploy
The build will write the commit SHA to REVISION, and the release phase will read it back and report the deploy to BugWatch.
User Feedback Widget
Drop a feedback form into any view so users can report issues directly from your app. The form submits to BugWatch's feedback API — no controller code needed.
<%%= bugwatch_feedback_widget %>
The helper renders a plain, unstyled HTML form with CSS classes you can target:
| Class | Element |
|---|---|
.bugwatch-feedback-form |
The <form> wrapper |
.bugwatch-feedback-field |
Each field's <div> |
.bugwatch-feedback-label |
<label> elements |
.bugwatch-feedback-input |
Text/email <input> |
.bugwatch-feedback-textarea |
The message <textarea> |
.bugwatch-feedback-submit |
Submit <button> |
.bugwatch-feedback-success |
Success message (hidden by default) |
.bugwatch-feedback-error |
Error message (hidden by default) |
Options
<%%= bugwatch_feedback_widget(
user_email: current_user&.email,
user_name: current_user&.name,
placeholder: "Describe the issue...",
submit_text: "Report Issue",
success_message: "We got it — thanks!",
issue_id: @issue_id, # optional: link to a specific BugWatch issue
metadata: { page: "checkout" }
) %>
Styling example (Tailwind)
.bugwatch-feedback-form { @apply space-y-4 max-w-md; }
.bugwatch-feedback-label { @apply block text-sm font-medium text-gray-700; }
.bugwatch-feedback-input,
.bugwatch-feedback-textarea { @apply w-full border rounded-lg px-3 py-2 text-sm; }
.bugwatch-feedback-submit { @apply bg-blue-600 text-white px-4 py-2 rounded-lg text-sm; }
.bugwatch-feedback-success { @apply text-green-600 text-sm; }
.bugwatch-feedback-error { @apply text-red-600 text-sm; }
Server-side feedback
You can also send feedback from Ruby (e.g. from a controller that handles your own form):
Bugwatch.send_feedback(
params[:message],
email: current_user.email,
name: current_user.name,
url: request.original_url
)
Database query tracking
The gem automatically subscribes to sql.active_record notifications and reports query performance data to your BugWatch instance. DB tracking is enabled by default — no extra setup required.
Configuration
# config/initializers/bugwatch.rb
Bugwatch.configure do |c|
# ... existing config ...
c.enable_db_tracking = true # default: true — set false to disable
c.db_sample_rate = 1.0 # 0.0–1.0 — fraction of requests to track (default: 1.0)
c.db_query_threshold_ms = 0 # only collect queries slower than this (default: 0 = all)
c.max_queries_per_request = 200 # cap per request to limit overhead (default: 200)
end
| Option | Default | Description |
|---|---|---|
enable_db_tracking |
true |
Master switch for DB tracking |
db_sample_rate |
1.0 |
Fraction of requests whose queries are collected (0.0–1.0) |
db_query_threshold_ms |
0 |
Minimum query duration (ms) to collect — set higher to focus on slow queries |
max_queries_per_request |
200 |
Maximum queries stored per request |
Schema operations and transaction bookkeeping (BEGIN, COMMIT, ROLLBACK) are automatically excluded. SQL literals are sanitized before sending, so no user data leaves your app.
Skipping tracking
Wrap any code block with Bugwatch.without_tracking to suppress all performance tracking (DB queries and transaction recording) for queries executed inside it. This is useful when BugWatch monitors itself, or for any internal bookkeeping queries you don't want tracked.
Bugwatch.without_tracking do
SomeModel.insert_all(records) # not tracked
end
In a controller:
around_action :skip_tracking
private
def skip_tracking(&block)
Bugwatch.without_tracking(&block)
end
How it works
Bugwatch::Middlewarewraps your entire Rack stack.- When an unhandled exception propagates out of a request, the middleware:
- Captures the exception, full backtrace (with 3 lines of source context per in-app frame), request details, user context, and breadcrumbs.
- POSTs the payload to your BugWatch instance in a background thread (fire-and-forget, 3s timeout).
- Re-raises the exception so Rails error handling fires normally.
- Thread-local user context and breadcrumbs are cleared automatically after each request by the Rails around_action hook.
What gets sent
| Field | Description |
|---|---|
exception.error_class |
Exception class name |
exception.message |
Exception message |
exception.backtrace |
Array of frames with file, line, method, in_app, source_context |
request.* |
Method, URL, params (filtered), headers (filtered), IP |
app.* |
Rails env, Ruby version, Rails version, git SHA, hostname |
user.* |
ID, email, name, any custom fields |
breadcrumbs |
Last 50 breadcrumbs with timestamp, type, message, metadata |
duration_ms |
Request duration in milliseconds |
Sensitive params (password, token, secret, key, auth, credit, card, cvv, ssn) are automatically filtered from request params and never sent.
Publishing
cd /home/max/bugwatch-ruby
gem build bugwatch-ruby.gemspec
gem signin
gem push bugwatch-ruby-0.1.0.gem