exception_hunter 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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