mirror of
https://github.com/System-End/theseus.git
synced 2026-04-19 15:28:19 +00:00
move to sentry?
This commit is contained in:
parent
bff51d85cb
commit
92ef482132
25 changed files with 177 additions and 84 deletions
3
Gemfile
3
Gemfile
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
12
Gemfile.lock
12
Gemfile.lock
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
|
|
|
|||
9
app/controllers/errors_controller.rb
Normal file
9
app/controllers/errors_controller.rb
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
112
app/views/errors/internal_server_error.html.erb
Normal file
112
app/views/errors/internal_server_error.html.erb
Normal 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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}}"
|
||||
8
config/initializers/sentry.rb
Normal file
8
config/initializers/sentry.rb
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue