exception_hunter 0.1.1 → 0.2.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 +3 -2
- data/app/assets/stylesheets/exception_hunter/errors.css +4 -0
- data/app/helpers/exception_hunter/errors_helper.rb +7 -0
- data/app/presenters/exception_hunter/error_presenter.rb +8 -0
- data/app/views/exception_hunter/errors/_error_summary.erb +19 -6
- data/app/views/exception_hunter/errors/_error_user_data.erb +4 -5
- data/config/rails_best_practices.yml +0 -1
- data/lib/exception_hunter.rb +2 -1
- data/lib/exception_hunter/middleware/request_hunter.rb +70 -0
- data/lib/exception_hunter/middleware/sidekiq_hunter.rb +58 -0
- data/lib/exception_hunter/version.rb +1 -1
- metadata +5 -4
- data/lib/exception_hunter/railtie.rb +0 -11
- data/lib/exception_hunter/request_hunter.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a48a18bd03288de4cf787931d9be95dea04f3f168224c87c971ad5b2cd9fb1bf
|
4
|
+
data.tar.gz: 6194494c81ccd89d7f3ce0c2a00c607fe2c7836e872074d11b37454cf8f93122
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bd3b4b6410b75f39a43ce1a4f87234883f5a625d77e63f42dd217db865f31a515a95577d3def6d0de838905003640c348f9b43f8d1c4c9731b13e3d4dbff8a7
|
7
|
+
data.tar.gz: 18744e0c947daa72a222449986d3c75d2e80b9993baa89ab9d90f137b2de9ac5b82272550096894dd248f4f7b337277ff94f61aa605a7229715a8fdf0049fb1e
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ How to use my plugin.
|
|
8
8
|
Add Exception Hunter to your application's Gemfile:
|
9
9
|
|
10
10
|
```ruby
|
11
|
-
gem 'exception_hunter', '~> 0.
|
11
|
+
gem 'exception_hunter', '~> 0.2.0'
|
12
12
|
```
|
13
13
|
|
14
14
|
You may also need to add [Devise](https://github.com/heartcombo/devise) to your Gemfile
|
@@ -26,7 +26,8 @@ $ rails generate exception_hunter:install
|
|
26
26
|
|
27
27
|
This will create an initializer and invoke Devise to
|
28
28
|
create an `AdminUser` which will be used for authentication to access the dashboard. If you already
|
29
|
-
have this user created (
|
29
|
+
have this user created ([ActiveAdmin](https://github.com/activeadmin/activeadmin) uses the same model)
|
30
|
+
you can run the command with the `--skip-users` flag.
|
30
31
|
|
31
32
|
Additionally it should add the 'ExceptionHunter.routes(self)' line to your routes, which means you can go to
|
32
33
|
`/exception_hunter/errors` in your browser and start enjoying some good old fashioned exception tracking!
|
@@ -6,10 +6,22 @@
|
|
6
6
|
<div class="row error-row-no-border data-title">
|
7
7
|
Environment Data
|
8
8
|
</div>
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
<pre class="tracked-data">
|
10
|
+
|
11
|
+
<%= format_tracked_data(error.environment_data) %>
|
12
|
+
</pre>
|
12
13
|
<% end %>
|
14
|
+
|
15
|
+
<% unless error.tracked_params.nil? %>
|
16
|
+
<div class="row error-row-no-border data-title">
|
17
|
+
Tracked Params
|
18
|
+
</div>
|
19
|
+
<pre class="tracked-data">
|
20
|
+
|
21
|
+
<%= format_tracked_data(error.tracked_params) %>
|
22
|
+
</pre>
|
23
|
+
<% end %>
|
24
|
+
|
13
25
|
<% if error.custom_data.nil? %>
|
14
26
|
<div class="row error-row-no-border data-title">
|
15
27
|
No custom data included.
|
@@ -18,7 +30,8 @@
|
|
18
30
|
<div class="row error-row-no-border data-title">
|
19
31
|
Custom Data
|
20
32
|
</div>
|
21
|
-
|
22
|
-
|
23
|
-
|
33
|
+
<pre class="tracked-data">
|
34
|
+
|
35
|
+
<%= format_tracked_data(error.custom_data) %>
|
36
|
+
</pre>
|
24
37
|
<% end %>
|
@@ -3,9 +3,8 @@
|
|
3
3
|
Unfortunately, no user information has been registered for this error.
|
4
4
|
</div>
|
5
5
|
<% else %>
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
<% end %>
|
6
|
+
<pre class="tracked-data">
|
7
|
+
|
8
|
+
<%= format_tracked_data(error.user_data) %>
|
9
|
+
</pre>
|
11
10
|
<% end %>
|
@@ -15,7 +15,6 @@ MoveCodeIntoModelCheck: { use_count: 2 }
|
|
15
15
|
MoveFinderToNamedScopeCheck: { }
|
16
16
|
MoveModelLogicIntoModelCheck: { use_count: 4 }
|
17
17
|
NeedlessDeepNestingCheck: { nested_count: 2 }
|
18
|
-
NotRescueExceptionCheck: { ignored_files: 'request_hunter.rb' }
|
19
18
|
NotUseDefaultRouteCheck: { }
|
20
19
|
NotUseTimeAgoInWordsCheck: { ignored_files: ['index.html.erb'] }
|
21
20
|
OveruseRouteCustomizationsCheck: { customize_count: 3 }
|
data/lib/exception_hunter.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'exception_hunter/engine'
|
2
|
-
require 'exception_hunter/
|
2
|
+
require 'exception_hunter/middleware/request_hunter'
|
3
|
+
require 'exception_hunter/middleware/sidekiq_hunter' if defined?(Sidekiq)
|
3
4
|
require 'exception_hunter/config'
|
4
5
|
require 'exception_hunter/user_attributes_collector'
|
5
6
|
require 'pagy'
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module ExceptionHunter
|
2
|
+
module Middleware
|
3
|
+
class RequestHunter
|
4
|
+
ENVIRONMENT_KEYS =
|
5
|
+
%w[PATH_INFO
|
6
|
+
QUERY_STRING
|
7
|
+
REMOTE_HOST
|
8
|
+
REQUEST_METHOD
|
9
|
+
REQUEST_URI
|
10
|
+
SERVER_PROTOCOL
|
11
|
+
HTTP_HOST
|
12
|
+
CONTENT_TYPE
|
13
|
+
HTTP_USER_AGENT].freeze
|
14
|
+
|
15
|
+
FILTERED_PARAMS = [/password/].freeze
|
16
|
+
|
17
|
+
def initialize(app)
|
18
|
+
@app = app
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
@app.call(env)
|
23
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
24
|
+
catch_prey(env, exception)
|
25
|
+
raise exception
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def catch_prey(env, exception)
|
31
|
+
user = user_from_env(env)
|
32
|
+
ErrorCreator.call(
|
33
|
+
class_name: exception.class.to_s,
|
34
|
+
message: exception.message,
|
35
|
+
environment_data: environment_data(env),
|
36
|
+
backtrace: exception.backtrace,
|
37
|
+
user: user
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def environment_data(env)
|
42
|
+
env
|
43
|
+
.select { |key, _value| ENVIRONMENT_KEYS.include?(key) }
|
44
|
+
.merge(params: filtered_sensitive_params(env))
|
45
|
+
end
|
46
|
+
|
47
|
+
def user_from_env(env)
|
48
|
+
current_user_method = Config.current_user_method
|
49
|
+
controller = env['action_controller.instance']
|
50
|
+
controller.try(current_user_method)
|
51
|
+
end
|
52
|
+
|
53
|
+
def filtered_sensitive_params(env)
|
54
|
+
params = env['action_dispatch.request.parameters']
|
55
|
+
parameter_filter = ::ActiveSupport::ParameterFilter.new(FILTERED_PARAMS)
|
56
|
+
parameter_filter.filter(params || {})
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module ExceptionHunter
|
63
|
+
class Railtie < Rails::Railtie
|
64
|
+
initializer 'exception_hunter.add_middleware', after: :load_config_initializers do |app|
|
65
|
+
app.config.middleware.insert_after(
|
66
|
+
ActionDispatch::DebugExceptions, ExceptionHunter::Middleware::RequestHunter
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module ExceptionHunter
|
2
|
+
module Middleware
|
3
|
+
# Middleware to report errors
|
4
|
+
# when a Sidekiq worker fails
|
5
|
+
#
|
6
|
+
class SidekiqHunter
|
7
|
+
TRACK_AT_RETRY = [0, 3, 6, 10].freeze
|
8
|
+
JOB_TRACKED_DATA = %w[
|
9
|
+
queue
|
10
|
+
retry_count
|
11
|
+
].freeze
|
12
|
+
ARGS_TRACKED_DATA = %w[
|
13
|
+
job_class
|
14
|
+
job_id
|
15
|
+
arguments
|
16
|
+
enqueued_at
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
def call(_worker, context, _queue)
|
20
|
+
yield
|
21
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
22
|
+
track_exception(exception, context)
|
23
|
+
raise exception
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def track_exception(exception, context)
|
29
|
+
return unless should_track?(context)
|
30
|
+
|
31
|
+
ErrorCreator.call(
|
32
|
+
class_name: exception.class.to_s,
|
33
|
+
message: exception.message,
|
34
|
+
environment_data: environment_data(context),
|
35
|
+
backtrace: exception.backtrace
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def environment_data(context)
|
40
|
+
job_data = context.select { |key, _value| JOB_TRACKED_DATA.include?(key) }
|
41
|
+
args_data = (context['args']&.first || {}).select { |key, _value| ARGS_TRACKED_DATA.include?(key) }
|
42
|
+
|
43
|
+
job_data.merge(args_data)
|
44
|
+
end
|
45
|
+
|
46
|
+
def should_track?(context)
|
47
|
+
TRACK_AT_RETRY.include?(context['retry_count'].to_i)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# As seen in https://github.com/mperham/sidekiq/wiki/Error-Handling
|
54
|
+
Sidekiq.configure_server do |config|
|
55
|
+
config.server_middleware do |chain|
|
56
|
+
chain.add(ExceptionHunter::Middleware::SidekiqHunter)
|
57
|
+
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exception_hunter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bruno Vezoli
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-05-
|
12
|
+
date: 2020-05-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pagy
|
@@ -142,6 +142,7 @@ files:
|
|
142
142
|
- app/controllers/exception_hunter/application_controller.rb
|
143
143
|
- app/controllers/exception_hunter/errors_controller.rb
|
144
144
|
- app/helpers/exception_hunter/application_helper.rb
|
145
|
+
- app/helpers/exception_hunter/errors_helper.rb
|
145
146
|
- app/jobs/exception_hunter/application_job.rb
|
146
147
|
- app/mailers/exception_hunter/application_mailer.rb
|
147
148
|
- app/models/exception_hunter/application_record.rb
|
@@ -162,8 +163,8 @@ files:
|
|
162
163
|
- lib/exception_hunter.rb
|
163
164
|
- lib/exception_hunter/config.rb
|
164
165
|
- lib/exception_hunter/engine.rb
|
165
|
-
- lib/exception_hunter/
|
166
|
-
- lib/exception_hunter/
|
166
|
+
- lib/exception_hunter/middleware/request_hunter.rb
|
167
|
+
- lib/exception_hunter/middleware/sidekiq_hunter.rb
|
167
168
|
- lib/exception_hunter/user_attributes_collector.rb
|
168
169
|
- lib/exception_hunter/version.rb
|
169
170
|
- lib/generators/exception_hunter/create_users/create_users_generator.rb
|
@@ -1,11 +0,0 @@
|
|
1
|
-
require_dependency 'exception_hunter/request_hunter'
|
2
|
-
|
3
|
-
module ExceptionHunter
|
4
|
-
class Railtie < Rails::Railtie
|
5
|
-
initializer 'exception_hunter.add_middleware', after: :load_config_initializers do |app|
|
6
|
-
app.config.middleware.insert_after(
|
7
|
-
ActionDispatch::DebugExceptions, ExceptionHunter::RequestHunter
|
8
|
-
)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module ExceptionHunter
|
2
|
-
class RequestHunter
|
3
|
-
ENVIRONMENT_KEYS =
|
4
|
-
%w[PATH_INFO QUERY_STRING REMOTE_HOST REQUEST_METHOD REQUEST_URI
|
5
|
-
SERVER_PROTOCOL HTTP_HOST HTTP_USER_AGENT].freeze
|
6
|
-
|
7
|
-
def initialize(app)
|
8
|
-
@app = app
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(env)
|
12
|
-
@app.call(env)
|
13
|
-
rescue Exception => exception
|
14
|
-
catch_prey(env, exception)
|
15
|
-
raise exception
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def catch_prey(env, exception)
|
21
|
-
user = user_from_env(env)
|
22
|
-
ErrorCreator.call(
|
23
|
-
class_name: exception.class.to_s,
|
24
|
-
message: exception.message,
|
25
|
-
environment_data: environment_data(env),
|
26
|
-
backtrace: exception.backtrace,
|
27
|
-
user: user
|
28
|
-
)
|
29
|
-
end
|
30
|
-
|
31
|
-
def environment_data(env)
|
32
|
-
env.select { |key, _value| ENVIRONMENT_KEYS.include?(key) }
|
33
|
-
end
|
34
|
-
|
35
|
-
def user_from_env(env)
|
36
|
-
current_user_method = Config.current_user_method
|
37
|
-
controller = env['action_controller.instance']
|
38
|
-
controller.try(current_user_method)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|