move to sentry?

This commit is contained in:
24c02 2025-12-29 10:39:37 -05:00
parent bff51d85cb
commit 92ef482132
25 changed files with 177 additions and 84 deletions

View file

@ -159,7 +159,8 @@ gem "ruby-openai", "~> 8.1"
gem "parallel", "~> 1.26"
gem "honeybadger", "~> 5.28"
gem "sentry-ruby"
gem "sentry-rails"
gem "rmagick", "~> 5.3"

View file

@ -239,9 +239,6 @@ GEM
hashids (1.0.6)
hashie (5.0.0)
hcbv4 (0.1.1)
honeybadger (5.28.0)
logger
ostruct
http (5.2.0)
addressable (~> 2.8)
base64 (~> 0.1)
@ -570,6 +567,12 @@ GEM
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
sentry-rails (6.2.0)
railties (>= 5.2.0)
sentry-ruby (~> 6.2.0)
sentry-ruby (6.2.0)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
slack-notifier (2.4.0)
slim (5.2.1)
temple (~> 0.10.0)
@ -721,7 +724,6 @@ DEPENDENCIES
good_job (~> 4.11)
hashid-rails (~> 1.4)
hcbv4 (~> 0.1)
honeybadger (~> 5.28)
http (~> 5.2)
ivymeter (~> 0.1.0)
jb (~> 0.8.2)
@ -755,6 +757,8 @@ DEPENDENCIES
select2-rails (~> 4.0)
selectize-rails (~> 0.12.6)
selenium-webdriver
sentry-rails
sentry-ruby
slack-notifier (~> 2.4)
slim-rails (~> 3.7)
snail (~> 2.3)

View file

@ -11,7 +11,6 @@ module API
end
rescue_from ActiveRecord::RecordInvalid do |e|
Honeybadger.notify(e)
render json: {
error: "Validation failed",
details: e.record.errors.full_messages,

View file

@ -10,7 +10,6 @@ module API
end
rescue_from ActiveRecord::RecordInvalid do |e|
Honeybadger.notify(e)
render json: {
error: "Validation failed",
details: e.record.errors.full_messages,

View file

@ -4,7 +4,7 @@ class ApplicationController < ActionController::Base
helper_method :current_user, :user_signed_in?
before_action :authenticate_user!, :set_honeybadger_context
before_action :authenticate_user!, :set_sentry_context
def current_user
@current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
@ -20,11 +20,8 @@ class ApplicationController < ActionController::Base
end
end
def set_honeybadger_context
Honeybadger.context({
user_id: current_user&.id,
user_email: current_user&.email,
})
def set_sentry_context
Sentry.set_user(id: current_user&.id, email: current_user&.email)
end
rescue_from Pundit::NotAuthorizedError do |e|

View file

@ -64,10 +64,9 @@ class BaseBatchesController < ApplicationController
begin
@batch.run_map!
rescue StandardError => e
raise
Rails.logger.warn(e)
uuid = Honeybadger.notify(e)
redirect_to send("#{@batch.class.name.split("::").first.downcase}_batch_path", @batch), flash: { alert: "error mapping fields! #{e.message} (please report EID: #{uuid})" }
event_id = Sentry.capture_exception(e)
redirect_to send("#{@batch.class.name.split("::").first.downcase}_batch_path", @batch), flash: { alert: "error mapping fields! #{e.message} (error: #{event_id})" }
return
end
redirect_to send("process_confirm_#{@batch.class.name.split("::").first.downcase}_batch_path", @batch), notice: "Field mapping saved. Please review and process your batch."

View file

@ -0,0 +1,9 @@
class ErrorsController < ApplicationController
skip_before_action :authenticate_user!
skip_after_action :verify_authorized
def internal_server_error
@sentry_event_id = request.env["sentry.error_event_id"] || Sentry.last_event_id
render status: :internal_server_error, formats: [:html]
end
end

View file

@ -128,8 +128,8 @@ class Letter::BatchesController < BaseBatchesController
redirect_to letter_batch_path(@batch, print_now: letter_batch_params[:print_immediately]), notice: "Batch processed successfully"
rescue => e
uuid = Honeybadger.notify(e)
redirect_to process_letter_batch_path(@batch), alert: "Failed to process batch: #{e.message} (please report EID: #{uuid})"
event_id = Sentry.capture_exception(e)
redirect_to process_letter_batch_path(@batch), alert: "Failed to process batch: #{e.message} (error: #{event_id})"
end
end
end

View file

@ -5,9 +5,8 @@ module Public
layout "public"
before_action do
Honeybadger.context({
user_id: current_public_user&.id,
user_email: current_public_user&.email,
Sentry.set_user(id: current_public_user&.id, email: current_public_user&.email)
Sentry.set_context("impersonation", {
real_user_id: current_user&.id,
real_user_email: current_user&.email,
impersonator_user_id: session[:public_impersonator_user_id],

View file

@ -6,7 +6,7 @@ class SessionsController < ApplicationController
def impersonate
unless current_user.admin?
redirect_to root_path, alert: "you are not authorized to impersonate users. this incident has been reported :-P"
Honeybadger.notify("Impersonation attempt by #{current_user.username} to #{params[:id]}")
Sentry.capture_message("Impersonation attempt by #{current_user.username} to #{params[:id]}", level: :warning)
return
end
@ -44,8 +44,8 @@ class SessionsController < ApplicationController
@user = User.from_hack_club_auth(auth)
rescue => e
Rails.logger.error "Error creating user from Hack Club Auth: #{e.message}"
uuid = Honeybadger.notify(e)
redirect_to login_path, alert: "error authenticating! (error: #{uuid})"
event_id = Sentry.capture_exception(e)
redirect_to login_path, alert: "error authenticating! (error: #{event_id})"
return
end

View file

@ -114,8 +114,8 @@ class Warehouse::BatchesController < BaseBatchesController
@batch.run_map!
rescue StandardError => e
Rails.logger.warn(e)
uuid = Honeybadger.notify(e)
redirect_to warehouse_batch_path(@batch), flash: { alert: "Error mapping fields! #{e.message} (please report EID: #{uuid})" }
event_id = Sentry.capture_exception(e)
redirect_to warehouse_batch_path(@batch), flash: { alert: "Error mapping fields! #{e.message} (error: #{event_id})" }
return
end
redirect_to process_confirm_warehouse_batch_path(@batch), notice: "Field mapping saved. Please review and process your batch."

View file

@ -38,11 +38,13 @@ class Warehouse::OrdersController < ApplicationController
begin
@warehouse_order.dispatch!
rescue Zenventory::ZenventoryError => e
uuid = Honeybadger.notify(e)
redirect_to @warehouse_order, alert: "zenventory said \"#{e.message}\" (please report EID: #{uuid})"
event_id = Sentry.capture_exception(e)
redirect_to @warehouse_order, alert: "zenventory said \"#{e.message}\" (error: #{event_id})"
return
rescue AASM::InvalidTransition => e
uuid = Honeybadger.notify(e)
redirect_to @warehouse_order, alert: "couldn't dispatch order! wrong state? (please report EID: #{uuid})"
event_id = Sentry.capture_exception(e)
redirect_to @warehouse_order, alert: "couldn't dispatch order! wrong state? (error: #{event_id})"
return
end
redirect_to @warehouse_order, flash: { success: "successfully sent to warehouse!" }
end

View file

@ -26,8 +26,7 @@ module SnailMail
).barcode_letters
rescue ArgumentError => e
Rails.logger.warn("Bad IMb input: #{e.message} @ MID #{mailer_id} SN #{serial_number} RC #{routing_code}")
uuid = Honeybadger.notify(e)
Rails.logger.warn("IMb error (please report EID: #{uuid})")
Sentry.capture_exception(e)
""
end
end

View file

@ -36,9 +36,8 @@ module SnailMail
pdf.image io, at: [x, y], width: size, height: size
rescue => e
Rails.logger.error("QR code generation failed: #{e.message}")
uuid = Honeybadger.notify(e)
# Fallback to a text label if QR code fails
pdf.text_box "QR Error (error: #{uuid})", at: [x, y], width: size, height: size
event_id = Sentry.capture_exception(e)
pdf.text_box "QR Error (error: #{event_id})", at: [x, y], width: size, height: size
end
end
end

View file

@ -137,9 +137,7 @@ class Letter::InstantQueue < Letter::Queue
end
rescue => e
Rails.logger.error("Failed to create indicium for letter #{letter.id}: #{e.message}")
Rails.logger.error(e.backtrace.join("\n"))
uuid = Honeybadger.notify(e)
raise "Failed to create indicium (please report EID: #{uuid} immediately)"
raise e
end
end
letter

View file

@ -102,8 +102,8 @@ class Warehouse::Batch < Batch
begin
Zenventory.create_customer_order(update_hash)
rescue Zenventory::ZenventoryError => e
uuid = Honeybadger.notify(e)
errors.add(:base, "couldn't create order, Zenventory said: #{e.message} (error: #{uuid})")
event_id = Sentry.capture_exception(e)
errors.add(:base, "couldn't create order, Zenventory said: #{e.message} (error: #{event_id})")
throw(:abort)
end
end

View file

@ -173,8 +173,8 @@ class Warehouse::Order < ApplicationRecord
}.compact_blank
Zenventory.update_customer_order(zenventory_id, update_hash) unless update_hash.empty?
rescue Zenventory::ZenventoryError => e
uuid = Honeybadger.notify(e)
errors.add(:base, "couldn't edit order, Zenventory said: #{e.message} (error: #{uuid})")
event_id = Sentry.capture_exception(e)
errors.add(:base, "couldn't edit order, Zenventory said: #{e.message} (error: #{event_id})")
throw(:abort)
end
end

View file

@ -105,10 +105,9 @@ module GeocodingService
key: ENV["HACKCLUB_GEOCODER_API_KEY"],
})
# Handle error responses
if response.body.key?("error")
Rails.logger.error "Hack Club Geocoder error: #{response.body["error"]}"
Honeybadger.notify("Geocoding error: #{response.body["error"]}")
Sentry.capture_message("Geocoding error: #{response.body["error"]}")
return nil
end
@ -123,7 +122,7 @@ module GeocodingService
}
rescue => e
Rails.logger.error "Hack Club Geocoder request failed: #{e.message}"
Honeybadger.notify(e)
Sentry.capture_exception(e)
nil
end

View file

@ -34,16 +34,14 @@ module FaradayMiddleware
def on_complete(env)
unless env.response.success?
unless env.response.body.respond_to?(:dig)
uuid = Honeybadger.notify(USPS::USPSError.new(env.response.body))
raise USPS::USPSError, "#{env.response.body} (please report EID: #{uuid})"
raise USPS::USPSError, env.response.body.to_s
end
if env.response.body.dig(:error, :message) == "Address Not Found."
raise USPS::NxAddress
elsif env.response.body.dig(:error, :message) == "Invalid Zip Code."
raise USPS::NxZIP
else
uuid = Honeybadger.notify(USPS::USPSError.new(env.response.body))
raise USPS::USPSError, "#{env.response.body} (please report EID: #{uuid})"
raise USPS::USPSError, env.response.body.to_s
end
end
end

View file

@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>error!!</title>
<style>
@font-face {
font-family: DOSVGA;
src: url(/unifont.woff) format("woff");
font-style: normal;
font-display: swap
}
:root {
--blue: rgb(42, 100, 197)
}
body {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--blue);
font-family: DOSVGA, Courier, monospace;
font-size: 18px;
color: #fff;
text-align: center
}
.logo {
margin: 0;
color: var(--blue);
background-color: #fff
}
a {
color: #fff;
}
.logo-container {
background-color: #fff;
display: inline-block;
padding: 0 10px;
margin: 10px
}
@keyframes blinky {
50% {
opacity: 0
}
}
.error-code {
margin: 10px 0;
animation: blinky 1s step-start infinite
}
.error-message {
margin: 20px 0;
line-height: 1.5;
max-width: 720px;
text-align: left;
}
.bootloader-link {
color: inherit;
text-decoration-thickness: 1px;
float: left;
}
.error-id {
text-align: left;
margin-left: 10px;
}
.error-id-text {
background-color: #fff;
color: var(--blue);
padding: 0 5px;
border-radius: 5px;
margin-left: 10px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="error-container">
<div class="logo-container">
<p class="logo">Theseus</p>
</div>
<p class="error-code">ERROR 500</p>
<p class="error-message">
An internal server error has occurred.<br />
Please poke <a href="https://hackclub.slack.com/team/U06QK6AG3RD" target="_blank">@nora</a> with the
following error ID and what you were trying to do when this happened.
</p>
<% if @sentry_event_id.present? %>
<p class="error-id">
<b>Error ID:</b><span class="error-id-text"
onclick="navigator.clipboard.writeText(this.textContent); this.textContent = 'copied!'"><%= @sentry_event_id %></span>
(click to copy)
</p>
<% end %>
<a class="bootloader-link" href="/"><- return to homepage</a>
</div>
</body>
</html>

View file

@ -45,5 +45,8 @@ module Theseus
expire_after: 30.days,
secure: Rails.env.production?,
httponly: true
# Use dynamic error pages so we can show Sentry event IDs
config.exceptions_app = routes
end
end

View file

@ -1,34 +0,0 @@
---
# For more options, see https://docs.honeybadger.io/lib/ruby/gem-reference/configuration
api_key: '<%= ENV["HONEYBADGER_API_KEY"] %>'
# The environment your app is running in.
env: "<%= Rails.env %>"
# The absolute path to your project folder.
root: "<%= Rails.root.to_s %>"
# Honeybadger won't report errors in these environments.
development_environments:
- test
- development
- cucumber
# By default, Honeybadger won't report errors in the development_environments.
# You can override this by explicitly setting report_data to true or false.
# report_data: true
# The current Git revision of your project. Defaults to the last commit hash.
# revision: null
# Enable verbose debug logging (useful for troubleshooting).
debug: false
# Enable Honeybadger Insights
insights:
enabled: false
user_informer:
enabled: true
info: "{{error_id}}"

View file

@ -0,0 +1,8 @@
Sentry.init do |config|
config.dsn = ENV["SENTRY_DSN"]
config.breadcrumbs_logger = [:active_support_logger, :http_logger]
config.enabled_environments = %w[production staging]
config.send_default_pii = true
config.traces_sample_rate = 0.1
end

View file

@ -704,6 +704,8 @@ Rails.application.routes.draw do
end
end
match "/500", to: "errors#internal_server_error", via: :all
# Render dynamic PWA files from app/views/pwa/* (remember to link manifest in application.html.erb)
# get "manifest" => "rails/pwa#manifest", as: :pwa_manifest
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker

View file

@ -100,7 +100,7 @@
</p>
<p class="error-id">
<b>Error ID:</b><span class="error-id-text"
onclick="navigator.clipboard.writeText(this.textContent); this.textContent = 'copied!'"><!-- HONEYBADGER ERROR --></span>
onclick="navigator.clipboard.writeText(this.textContent); this.textContent = 'copied!'"><!-- SENTRY ERROR --></span>
(click to copy)
</p>
<a class="bootloader-link" href="/"><- return to homepage</a>