exception_hunter 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +103 -6
- data/app/assets/stylesheets/exception_hunter/base.css +66 -8
- data/app/assets/stylesheets/exception_hunter/errors.css +188 -25
- data/app/assets/stylesheets/exception_hunter/navigation.css +20 -5
- data/app/assets/stylesheets/exception_hunter/sessions.css +71 -0
- data/app/controllers/concerns/exception_hunter/authorization.rb +23 -0
- data/app/controllers/exception_hunter/application_controller.rb +2 -0
- data/app/controllers/exception_hunter/errors_controller.rb +29 -4
- data/app/controllers/exception_hunter/ignored_errors_controller.rb +25 -0
- data/app/controllers/exception_hunter/resolved_errors_controller.rb +11 -0
- data/app/helpers/exception_hunter/application_helper.rb +22 -0
- data/app/helpers/exception_hunter/sessions_helper.rb +16 -0
- data/app/jobs/exception_hunter/send_notification_job.rb +15 -0
- data/app/models/exception_hunter/application_record.rb +8 -0
- data/app/models/exception_hunter/error.rb +24 -7
- data/app/models/exception_hunter/error_group.rb +24 -5
- data/app/presenters/exception_hunter/dashboard_presenter.rb +56 -0
- data/app/presenters/exception_hunter/error_group_presenter.rb +25 -0
- data/app/presenters/exception_hunter/error_presenter.rb +3 -2
- data/app/views/exception_hunter/devise/sessions/new.html.erb +24 -0
- data/app/views/exception_hunter/errors/_error_row.erb +52 -0
- data/app/views/exception_hunter/errors/_error_summary.erb +5 -5
- data/app/views/exception_hunter/errors/_errors_table.erb +1 -0
- data/app/views/exception_hunter/errors/_last_7_days_errors_table.erb +12 -0
- data/app/views/exception_hunter/errors/index.html.erb +84 -29
- data/app/views/exception_hunter/errors/pagy/_pagy_nav.html.erb +15 -15
- data/app/views/exception_hunter/errors/show.html.erb +58 -22
- data/app/views/layouts/exception_hunter/application.html.erb +67 -6
- data/app/views/layouts/exception_hunter/exception_hunter_logged_out.html.erb +24 -0
- data/config/rails_best_practices.yml +3 -3
- data/config/routes.rb +21 -1
- data/lib/exception_hunter.rb +44 -2
- data/lib/exception_hunter/config.rb +25 -1
- data/lib/exception_hunter/data_redacter.rb +27 -0
- data/lib/exception_hunter/devise.rb +19 -0
- data/lib/exception_hunter/engine.rb +6 -0
- data/lib/exception_hunter/error_creator.rb +72 -0
- data/lib/exception_hunter/error_reaper.rb +20 -0
- data/lib/exception_hunter/middleware/delayed_job_hunter.rb +70 -0
- data/lib/exception_hunter/middleware/request_hunter.rb +5 -2
- data/lib/exception_hunter/middleware/sidekiq_hunter.rb +1 -1
- data/lib/exception_hunter/notifiers/misconfigured_notifiers.rb +10 -0
- data/lib/exception_hunter/notifiers/slack_notifier.rb +42 -0
- data/lib/exception_hunter/notifiers/slack_notifier_serializer.rb +20 -0
- data/lib/exception_hunter/tracking.rb +35 -0
- data/lib/exception_hunter/user_attributes_collector.rb +21 -0
- data/lib/exception_hunter/version.rb +1 -1
- data/lib/generators/exception_hunter/create_users/create_users_generator.rb +8 -1
- data/lib/generators/exception_hunter/install/install_generator.rb +3 -1
- data/lib/generators/exception_hunter/install/templates/create_exception_hunter_error_groups.rb.erb +3 -0
- data/lib/generators/exception_hunter/install/templates/exception_hunter.rb.erb +52 -0
- data/lib/tasks/exception_hunter_tasks.rake +6 -4
- metadata +46 -12
- data/app/services/exception_hunter/error_creator.rb +0 -41
- data/config/initializers/exception_hunter.rb +0 -16
@@ -0,0 +1,24 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Exception Hunter</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
|
8
|
+
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
|
9
|
+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.css">
|
10
|
+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/milligram/1.3.0/milligram.css">
|
11
|
+
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
|
12
|
+
|
13
|
+
<!-- Get patch fixes within a minor version -->
|
14
|
+
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/cferdinandi/tabby@12.0/dist/css/tabby-ui.min.css">
|
15
|
+
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/tabby@12.0/dist/js/tabby.polyfills.min.js"></script>
|
16
|
+
|
17
|
+
<%= stylesheet_link_tag "exception_hunter/application", media: "all" %>
|
18
|
+
</head>
|
19
|
+
<body style="background-color: #E5E5E5;">
|
20
|
+
<div class="container">
|
21
|
+
<%= yield %>
|
22
|
+
</div>
|
23
|
+
</body>
|
24
|
+
</html>
|
@@ -13,10 +13,10 @@ MoveCodeIntoControllerCheck: { }
|
|
13
13
|
MoveCodeIntoHelperCheck: { array_count: 3 }
|
14
14
|
MoveCodeIntoModelCheck: { use_count: 2 }
|
15
15
|
MoveFinderToNamedScopeCheck: { }
|
16
|
-
MoveModelLogicIntoModelCheck: { use_count: 4 }
|
16
|
+
# MoveModelLogicIntoModelCheck: { use_count: 4 }
|
17
17
|
NeedlessDeepNestingCheck: { nested_count: 2 }
|
18
18
|
NotUseDefaultRouteCheck: { }
|
19
|
-
NotUseTimeAgoInWordsCheck: { ignored_files: ['index.html.erb'] }
|
19
|
+
#NotUseTimeAgoInWordsCheck: { ignored_files: ['index.html.erb'] }
|
20
20
|
OveruseRouteCustomizationsCheck: { customize_count: 3 }
|
21
21
|
ProtectMassAssignmentCheck: { }
|
22
22
|
RemoveEmptyHelpersCheck: { }
|
@@ -29,7 +29,7 @@ ReplaceComplexCreationWithFactoryMethodCheck: { attribute_assignment_count: 2 }
|
|
29
29
|
ReplaceInstanceVariableWithLocalVariableCheck: { }
|
30
30
|
RestrictAutoGeneratedRoutesCheck: { }
|
31
31
|
SimplifyRenderInControllersCheck: { }
|
32
|
-
SimplifyRenderInViewsCheck: { }
|
32
|
+
#SimplifyRenderInViewsCheck: { }
|
33
33
|
#UseBeforeFilterCheck: { customize_count: 2 }
|
34
34
|
UseModelAssociationCheck: { }
|
35
35
|
UseMultipartAlternativeAsContentTypeOfEmailCheck: { }
|
data/config/routes.rb
CHANGED
@@ -1,3 +1,23 @@
|
|
1
1
|
ExceptionHunter::Engine.routes.draw do
|
2
|
-
resources :errors, only: %i[index show]
|
2
|
+
resources :errors, only: %i[index show] do
|
3
|
+
delete 'purge', on: :collection, to: 'errors#destroy', as: :purge
|
4
|
+
end
|
5
|
+
|
6
|
+
resources :resolved_errors, only: %i[create]
|
7
|
+
resources :ignored_errors, only: %i[create]
|
8
|
+
post :reopen, to: 'ignored_errors#reopen'
|
9
|
+
|
10
|
+
get '/', to: redirect('/exception_hunter/errors')
|
11
|
+
|
12
|
+
if ExceptionHunter::Config.auth_enabled?
|
13
|
+
admin_user_class = ExceptionHunter::Config.admin_user_class.underscore.to_sym
|
14
|
+
|
15
|
+
devise_scope admin_user_class do
|
16
|
+
get '/login', to: 'devise/sessions#new', as: :exception_hunter_login
|
17
|
+
post '/login', to: 'devise/sessions#create', as: :exception_hunter_create_session
|
18
|
+
get '/logout', to: 'devise/sessions#destroy', as: :exception_hunter_logout
|
19
|
+
end
|
20
|
+
|
21
|
+
devise_for admin_user_class, only: []
|
22
|
+
end
|
3
23
|
end
|
data/lib/exception_hunter.rb
CHANGED
@@ -1,16 +1,58 @@
|
|
1
|
+
require 'pagy'
|
2
|
+
|
1
3
|
require 'exception_hunter/engine'
|
2
4
|
require 'exception_hunter/middleware/request_hunter'
|
3
|
-
require 'exception_hunter/middleware/sidekiq_hunter' if defined?(Sidekiq)
|
4
5
|
require 'exception_hunter/config'
|
6
|
+
require 'exception_hunter/error_creator'
|
7
|
+
require 'exception_hunter/error_reaper'
|
8
|
+
require 'exception_hunter/tracking'
|
5
9
|
require 'exception_hunter/user_attributes_collector'
|
6
|
-
require '
|
10
|
+
require 'exception_hunter/notifiers/slack_notifier'
|
11
|
+
require 'exception_hunter/notifiers/slack_notifier_serializer'
|
12
|
+
require 'exception_hunter/notifiers/misconfigured_notifiers'
|
13
|
+
require 'exception_hunter/data_redacter'
|
7
14
|
|
15
|
+
# @api public
|
8
16
|
module ExceptionHunter
|
17
|
+
autoload :Devise, 'exception_hunter/devise'
|
18
|
+
|
19
|
+
extend ::ExceptionHunter::Tracking
|
20
|
+
|
21
|
+
# Used to setup ExceptionHunter's configuration
|
22
|
+
# it receives a block with the {ExceptionHunter::Config} singleton
|
23
|
+
# class.
|
24
|
+
#
|
25
|
+
# @return [void]
|
9
26
|
def self.setup(&block)
|
10
27
|
block.call(Config)
|
28
|
+
validate_config!
|
11
29
|
end
|
12
30
|
|
31
|
+
# Mounts the ExceptionHunter dashboard at /exception_hunter
|
32
|
+
# if it's enabled on the current environment.
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# Rails.application.routes.draw do
|
36
|
+
# ExceptionHunter.routes(self)
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# @param [ActionDispatch::Routing::Mapper] router to mount to
|
40
|
+
# @return [void]
|
13
41
|
def self.routes(router)
|
42
|
+
return unless Config.enabled
|
43
|
+
|
14
44
|
router.mount(ExceptionHunter::Engine, at: 'exception_hunter')
|
15
45
|
end
|
46
|
+
|
47
|
+
# @private
|
48
|
+
def self.validate_config!
|
49
|
+
notifiers = Config.notifiers
|
50
|
+
return if notifiers.blank?
|
51
|
+
|
52
|
+
notifiers.each do |notifier|
|
53
|
+
next if notifier[:name] == :slack && notifier.dig(:options, :webhook).present?
|
54
|
+
|
55
|
+
raise ExceptionHunter::Notifiers::MisconfiguredNotifiers, notifier
|
56
|
+
end
|
57
|
+
end
|
16
58
|
end
|
@@ -1,5 +1,29 @@
|
|
1
1
|
module ExceptionHunter
|
2
|
+
# Config singleton class used to customize ExceptionHunter
|
2
3
|
class Config
|
3
|
-
|
4
|
+
# @!attribute
|
5
|
+
# @return [Boolean] whether ExceptionHunter is active or not
|
6
|
+
cattr_accessor :enabled, default: true
|
7
|
+
# @!attribute
|
8
|
+
# @return [String] the name of the admin class (generally AdminUser)
|
9
|
+
cattr_accessor :admin_user_class
|
10
|
+
# @!attribute
|
11
|
+
# @return [Symbol] the name of the current user method provided by Devise
|
12
|
+
cattr_accessor :current_user_method
|
13
|
+
# @return [Array<Symbol>] attributes to whitelist on the user (see {ExceptionHunter::UserAttributesCollector})
|
14
|
+
cattr_accessor :user_attributes
|
15
|
+
# @return [Numeric] number of days until an error is considered stale
|
16
|
+
cattr_accessor :errors_stale_time, default: 45.days
|
17
|
+
# @return [Array<Hash>] configured notifiers for the application (see {ExceptionHunter::Notifiers})
|
18
|
+
cattr_accessor :notifiers, default: []
|
19
|
+
cattr_accessor :sensitive_fields, default: []
|
20
|
+
|
21
|
+
# Returns true if there's an admin user class configured to
|
22
|
+
# authenticate against.
|
23
|
+
#
|
24
|
+
# @return Boolean
|
25
|
+
def self.auth_enabled?
|
26
|
+
admin_user_class.present? && admin_user_class.try(:underscore)
|
27
|
+
end
|
4
28
|
end
|
5
29
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ExceptionHunter
|
2
|
+
class DataRedacter
|
3
|
+
attr_reader :params, :params_to_filter
|
4
|
+
|
5
|
+
def initialize(params, params_to_filter)
|
6
|
+
@params = params
|
7
|
+
@params_to_filter = params_to_filter
|
8
|
+
end
|
9
|
+
|
10
|
+
def redact
|
11
|
+
return params if params.blank?
|
12
|
+
|
13
|
+
parameter_filter = params_filter.new(params_to_filter)
|
14
|
+
parameter_filter.filter(params)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def params_filter
|
20
|
+
if defined?(::ActiveSupport::ParameterFilter)
|
21
|
+
::ActiveSupport::ParameterFilter
|
22
|
+
else
|
23
|
+
::ActionDispatch::Http::ParameterFilter
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ExceptionHunter
|
2
|
+
module Devise
|
3
|
+
# Used so we can integrate with {https://github.com/heartcombo/devise Devise} and
|
4
|
+
# provide a custom login on the dashboard.
|
5
|
+
class SessionsController < ::Devise::SessionsController
|
6
|
+
skip_before_action :verify_authenticity_token
|
7
|
+
|
8
|
+
layout 'exception_hunter/exception_hunter_logged_out'
|
9
|
+
|
10
|
+
def after_sign_out_path_for(*)
|
11
|
+
'/exception_hunter/login'
|
12
|
+
end
|
13
|
+
|
14
|
+
def after_sign_in_path_for(*)
|
15
|
+
'/exception_hunter'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module ExceptionHunter
|
2
|
+
# @private
|
2
3
|
class Engine < ::Rails::Engine
|
3
4
|
isolate_namespace ExceptionHunter
|
4
5
|
|
@@ -12,5 +13,10 @@ module ExceptionHunter
|
|
12
13
|
app.config.assets.precompile << 'exception_hunter/application.css'
|
13
14
|
app.config.assets.precompile << 'exception_hunter/logo.png'
|
14
15
|
end
|
16
|
+
|
17
|
+
initializer 'exception_hunter.load_middleware', group: :all do
|
18
|
+
require 'exception_hunter/middleware/sidekiq_hunter' if defined?(Sidekiq)
|
19
|
+
require 'exception_hunter/middleware/delayed_job_hunter' if defined?(Delayed)
|
20
|
+
end
|
15
21
|
end
|
16
22
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ExceptionHunter
|
2
|
+
# Core class in charge of the actual persistence of errors and notifications.
|
3
|
+
class ErrorCreator
|
4
|
+
HTTP_TAG = 'HTTP'.freeze
|
5
|
+
WORKER_TAG = 'Worker'.freeze
|
6
|
+
MANUAL_TAG = 'Manual'.freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
# Creates an error with the given attributes and persists it to
|
10
|
+
# the database.
|
11
|
+
#
|
12
|
+
# @param [HTTP_TAG, WORKER_TAG, MANUAL_TAG] tag to append to the error if any
|
13
|
+
# @return [ExceptionHunter::Error, false] the error or false if it was not possible to create it
|
14
|
+
def call(tag: nil, **error_attrs)
|
15
|
+
return unless should_create?
|
16
|
+
|
17
|
+
ActiveRecord::Base.transaction do
|
18
|
+
error_attrs = extract_user_data(error_attrs)
|
19
|
+
error_attrs = hide_sensitive_values(error_attrs)
|
20
|
+
error = ::ExceptionHunter::Error.new(error_attrs)
|
21
|
+
error_group = ::ExceptionHunter::ErrorGroup.find_matching_group(error) || ::ExceptionHunter::ErrorGroup.new
|
22
|
+
update_error_group(error_group, error, tag)
|
23
|
+
error.error_group = error_group
|
24
|
+
error.save!
|
25
|
+
return if error_group.ignored?
|
26
|
+
|
27
|
+
notify(error)
|
28
|
+
error
|
29
|
+
end
|
30
|
+
rescue ActiveRecord::RecordInvalid
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def should_create?
|
37
|
+
Config.enabled
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_error_group(error_group, error, tag)
|
41
|
+
error_group.error_class_name = error.class_name
|
42
|
+
error_group.message = error.message
|
43
|
+
error_group.tags << tag unless tag.nil?
|
44
|
+
error_group.tags.uniq!
|
45
|
+
|
46
|
+
error_group.save!
|
47
|
+
end
|
48
|
+
|
49
|
+
def extract_user_data(**error_attrs)
|
50
|
+
user = error_attrs[:user]
|
51
|
+
error_attrs[:user_data] = UserAttributesCollector.collect_attributes(user)
|
52
|
+
|
53
|
+
error_attrs.delete(:user)
|
54
|
+
error_attrs
|
55
|
+
end
|
56
|
+
|
57
|
+
def notify(error)
|
58
|
+
ExceptionHunter::Config.notifiers.each do |notifier|
|
59
|
+
slack_notifier = ExceptionHunter::Notifiers::SlackNotifier.new(error, notifier)
|
60
|
+
serializer = ExceptionHunter::Notifiers::SlackNotifierSerializer
|
61
|
+
serialized_slack_notifier = serializer.serialize(slack_notifier)
|
62
|
+
ExceptionHunter::SendNotificationJob.perform_later(serialized_slack_notifier)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def hide_sensitive_values(error_attrs)
|
67
|
+
sensitive_fields = ExceptionHunter::Config.sensitive_fields
|
68
|
+
ExceptionHunter::DataRedacter.new(error_attrs, sensitive_fields).redact
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ExceptionHunter
|
2
|
+
# Class in charge of disposing of stale errors as specified in the {ExceptionHunter::Config}.
|
3
|
+
class ErrorReaper
|
4
|
+
class << self
|
5
|
+
# Destroys all stale errors.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# ErrorReaper.purge(stale_time: 30.days)
|
9
|
+
#
|
10
|
+
# @param [Numeric] stale_time considered when destroying errors
|
11
|
+
# @return [void]
|
12
|
+
def purge(stale_time: Config.errors_stale_time)
|
13
|
+
ActiveRecord::Base.transaction do
|
14
|
+
Error.with_occurrences_before(Date.today - stale_time).destroy_all
|
15
|
+
ErrorGroup.without_errors.destroy_all
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'delayed_job'
|
2
|
+
|
3
|
+
module ExceptionHunter
|
4
|
+
module Middleware
|
5
|
+
# DelayedJob plugin to track exceptions on apps using DelayedJob.
|
6
|
+
class DelayedJobHunter < ::Delayed::Plugin
|
7
|
+
TRACK_AT_RETRY = [0, 3, 6, 10].freeze
|
8
|
+
JOB_TRACKED_DATA = %w[
|
9
|
+
attempts
|
10
|
+
].freeze
|
11
|
+
ARGS_TRACKED_DATA = %w[
|
12
|
+
queue_name
|
13
|
+
job_class
|
14
|
+
job_id
|
15
|
+
arguments
|
16
|
+
enqueued_at
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
callbacks do |lifecycle|
|
20
|
+
lifecycle.around(:invoke_job) do |job, *args, &block|
|
21
|
+
block.call(job, *args)
|
22
|
+
|
23
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
24
|
+
track_exception(exception, job)
|
25
|
+
|
26
|
+
raise exception
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.track_exception(exception, job)
|
31
|
+
return unless should_track?(job.attempts)
|
32
|
+
|
33
|
+
ErrorCreator.call(
|
34
|
+
tag: ErrorCreator::WORKER_TAG,
|
35
|
+
class_name: exception.class.to_s,
|
36
|
+
message: exception.message,
|
37
|
+
environment_data: environment_data(job),
|
38
|
+
backtrace: exception.backtrace
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.environment_data(job)
|
43
|
+
job_data =
|
44
|
+
JOB_TRACKED_DATA.reduce({}) do |dict, data_param|
|
45
|
+
dict.merge(data_param => job.try(data_param))
|
46
|
+
end
|
47
|
+
|
48
|
+
job_class = if job.payload_object.class.name == 'ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper'
|
49
|
+
# support for Rails 4.2 ActiveJob
|
50
|
+
job.payload_object.job_data['job_class']
|
51
|
+
elsif job.payload_object.object.is_a?(Class)
|
52
|
+
job.payload_object.object.name
|
53
|
+
else
|
54
|
+
job.payload_object.object.class.name
|
55
|
+
end
|
56
|
+
args_data = (job.payload_object.try(:job_data) || {}).select { |key, _value| ARGS_TRACKED_DATA.include?(key) }
|
57
|
+
|
58
|
+
args_data['job_class'] = job_class || job.payload_object.class.name if args_data['job_class'].nil?
|
59
|
+
|
60
|
+
job_data.merge(args_data)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.should_track?(attempts)
|
64
|
+
TRACK_AT_RETRY.include?(attempts)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
Delayed::Worker.plugins << ExceptionHunter::Middleware::DelayedJobHunter
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module ExceptionHunter
|
2
2
|
module Middleware
|
3
|
+
# {https://www.rubyguides.com/2018/09/rack-middleware Rack Middleware} used to
|
4
|
+
# rescue from exceptions track them and then re-raise them.
|
3
5
|
class RequestHunter
|
4
6
|
ENVIRONMENT_KEYS =
|
5
7
|
%w[PATH_INFO
|
@@ -30,6 +32,7 @@ module ExceptionHunter
|
|
30
32
|
def catch_prey(env, exception)
|
31
33
|
user = user_from_env(env)
|
32
34
|
ErrorCreator.call(
|
35
|
+
tag: ErrorCreator::HTTP_TAG,
|
33
36
|
class_name: exception.class.to_s,
|
34
37
|
message: exception.message,
|
35
38
|
environment_data: environment_data(env),
|
@@ -52,14 +55,14 @@ module ExceptionHunter
|
|
52
55
|
|
53
56
|
def filtered_sensitive_params(env)
|
54
57
|
params = env['action_dispatch.request.parameters']
|
55
|
-
|
56
|
-
parameter_filter.filter(params || {})
|
58
|
+
ExceptionHunter::DataRedacter.new(params, FILTERED_PARAMS).redact
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
62
64
|
module ExceptionHunter
|
65
|
+
# @private
|
63
66
|
class Railtie < Rails::Railtie
|
64
67
|
initializer 'exception_hunter.add_middleware', after: :load_config_initializers do |app|
|
65
68
|
app.config.middleware.insert_after(
|
@@ -2,7 +2,6 @@ module ExceptionHunter
|
|
2
2
|
module Middleware
|
3
3
|
# Middleware to report errors
|
4
4
|
# when a Sidekiq worker fails
|
5
|
-
#
|
6
5
|
class SidekiqHunter
|
7
6
|
TRACK_AT_RETRY = [0, 3, 6, 10].freeze
|
8
7
|
JOB_TRACKED_DATA = %w[
|
@@ -29,6 +28,7 @@ module ExceptionHunter
|
|
29
28
|
return unless should_track?(context)
|
30
29
|
|
31
30
|
ErrorCreator.call(
|
31
|
+
tag: ErrorCreator::WORKER_TAG,
|
32
32
|
class_name: exception.class.to_s,
|
33
33
|
message: exception.message,
|
34
34
|
environment_data: environment_data(context),
|