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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 461f614a3acb4efa1cabad37cc849850c45b0f186f627b016c5d48d09684b6c4
4
- data.tar.gz: fa8c5abe1c5a2020d96ce5be459cacc624e227917eca8a5875046f528a021aa4
3
+ metadata.gz: a48a18bd03288de4cf787931d9be95dea04f3f168224c87c971ad5b2cd9fb1bf
4
+ data.tar.gz: 6194494c81ccd89d7f3ce0c2a00c607fe2c7836e872074d11b37454cf8f93122
5
5
  SHA512:
6
- metadata.gz: a057aff5a6cea927c804120a39b2c708a6e1d363d08d2707461c9fd0f39a8234bdb4cc7ca6b6e153f56cacf18d657eb88e0bd843c08953beef2aacfa2f721108
7
- data.tar.gz: 68eafa484c4350384b5fd8bd38c131462d6634fe9ff344c62ab71c91fcd3995f1b7f8ad4700b5715b7c89ca86741469141364a412887fa5eda680a4f63fd1d30
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.1.1'
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 (Devise uses the same model) you can run the command with the `--skip-users` flag.
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!
@@ -59,6 +59,10 @@
59
59
  color: var(--main-color);
60
60
  }
61
61
 
62
+ .tracked-data {
63
+ border-left-color: var(--main-color);
64
+ }
65
+
62
66
  .backtrace {
63
67
  padding-top: 1em;
64
68
  padding-bottom: 1em;
@@ -0,0 +1,7 @@
1
+ module ExceptionHunter
2
+ module ErrorsHelper
3
+ def format_tracked_data(tracked_data)
4
+ JSON.pretty_generate(tracked_data)
5
+ end
6
+ end
7
+ end
@@ -14,6 +14,14 @@ module ExceptionHunter
14
14
  end
15
15
  end
16
16
 
17
+ def environment_data
18
+ error.environment_data.except('params')
19
+ end
20
+
21
+ def tracked_params
22
+ (error.environment_data || {})['params']
23
+ end
24
+
17
25
  private
18
26
 
19
27
  attr_reader :error
@@ -6,10 +6,22 @@
6
6
  <div class="row error-row-no-border data-title">
7
7
  Environment Data
8
8
  </div>
9
- <% error.environment_data.each do |key, value| %>
10
- <b><%= key %></b>: <%= value %><br>
11
- <% end %>
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
- <% error.custom_data.each do |key, value| %>
22
- <b><%= key %></b>: <%= value || 'None' %> <br>
23
- <% end %>
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
- <% error.user_data.transform_keys(&:to_sym).each do |key, value| %>
7
- <div class="column column-15">
8
- <b><%= key %></b>: <%= value %>
9
- </div>
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 }
@@ -1,5 +1,6 @@
1
1
  require 'exception_hunter/engine'
2
- require 'exception_hunter/railtie'
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
@@ -1,3 +1,3 @@
1
1
  module ExceptionHunter
2
- VERSION = '0.1.1'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  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.1.1
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-17 00:00:00.000000000 Z
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/railtie.rb
166
- - lib/exception_hunter/request_hunter.rb
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