exception_hunter 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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),
|