ndr_error 1.1.4 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 26ef39b7a26a179c0169656601a9b3b036f1d0b3
4
- data.tar.gz: 48200c2d86631bb6dd3be30044e6d2df0fa31988
3
+ metadata.gz: ca01898083de92ab17019a9f2f312f4536bcf144
4
+ data.tar.gz: 8593a587b1fd43619dfebe0002205c78ea1018cf
5
5
  SHA512:
6
- metadata.gz: 4deb7e36e84c118d54c8b606f8c823372393157174703caafbaf3a8cbd52d733b1ab459a9b7b5bd293203f1e7670a340a8e9437d146fbdf1f06632a21354c375
7
- data.tar.gz: 1058ab87ec829b8556d8c8e114c961cd33a916951443ebaea0cac09d925c42250d5d085f462225fb6c2cd42a0fe889b2af154ad7da38b489fb73e94fff73c2eb
6
+ metadata.gz: b4b6b12acc1e1472a63d0c14df1254a6789a83acf9894ea60a319d71a1a19b6c9926de3ac7db4b3cd875ac51a450729e968b11e1dedaedf689703c39b2d34400
7
+ data.tar.gz: 1151c024cde520d1d6ada13e679e7f12bacfebe292db259a7c4f31a45b489c4829933c922d22cefbcbc413aa8979ef16d228d0ab51aa80c6235003f36bda5704
@@ -6,6 +6,8 @@ module NdrError
6
6
  # Ensure Rails doesn't find any host layouts first:
7
7
  layout 'ndr_error/ndr_error'
8
8
 
9
+ helper NdrUi::BootstrapHelper
10
+
9
11
  private
10
12
 
11
13
  def authenticate
@@ -20,6 +20,8 @@ module NdrError
20
20
  if @error.nil?
21
21
  flash[:error] = 'No matching Logs exist for that Fingerprint!'
22
22
  redirect_to error_fingerprints_url(q: @fingerprint.to_param)
23
+ elsif id.blank?
24
+ redirect_to log_id: @error.id
23
25
  end
24
26
  end
25
27
 
@@ -43,10 +43,17 @@ module NdrError
43
43
  end
44
44
 
45
45
  def similar_error_link(error)
46
- text = content_tag(:span, error.user_id, class: 'text-muted')
47
- text << ' - ' << error.created_at.to_s(:db)
46
+ user = error.user_id && content_tag(:span, error.user_id, class: 'text-muted')
47
+ text = safe_join([user, error.created_at.to_s(:db)].compact, ' - ')
48
48
 
49
- link_to text, error_fingerprint_path(error.error_fingerprint, log_id: error)
49
+ bootstrap_list_link_to text, error_fingerprint_path(error.error_fingerprint, log_id: error)
50
+ end
51
+
52
+ def downstream_fingerprint_link(print)
53
+ hash = content_tag(:span, print.id, class: 'text-muted')
54
+ text = print.error_logs.first.try(:error_class) || 'N/A'
55
+
56
+ bootstrap_list_link_to hash + ' - ' + text, error_fingerprint_path(print)
50
57
  end
51
58
 
52
59
  def ticket_link_for(fingerprint, small = false)
@@ -81,7 +88,7 @@ module NdrError
81
88
  def previous_button_for(error)
82
89
  css = 'btn btn-default'
83
90
  css << ' disabled' if error.nil?
84
- text = glyphicon_tag('chevron-left') + h('Previous Occurrence')
91
+ text = glyphicon_tag('chevron-left')
85
92
  path = error.nil? ? '#' : error_fingerprint_path(error.error_fingerprint, log_id: error)
86
93
 
87
94
  link_to(text, path, class: css)
@@ -90,7 +97,7 @@ module NdrError
90
97
  def next_button_for(error)
91
98
  css = 'btn btn-default'
92
99
  css << ' disabled' if error.nil?
93
- text = h('Next Occurrence') + glyphicon_tag('chevron-right')
100
+ text = glyphicon_tag('chevron-right')
94
101
  path = error.nil? ? '#' : error_fingerprint_path(error.error_fingerprint, log_id: error)
95
102
 
96
103
  link_to(text, path, class: css)
@@ -6,6 +6,17 @@ module NdrError
6
6
 
7
7
  self.primary_key = 'error_fingerprintid'
8
8
 
9
+ belongs_to_options = {
10
+ class_name: 'NdrError::Fingerprint',
11
+ foreign_key: 'causal_error_fingerprintid'
12
+ }
13
+ belongs_to_options[:optional] = true if Rails::VERSION::MAJOR > 4
14
+ belongs_to :causal_error_fingerprint, belongs_to_options
15
+
16
+ has_many :caused_error_fingerprints,
17
+ class_name: 'NdrError::Fingerprint',
18
+ foreign_key: 'causal_error_fingerprintid'
19
+
9
20
  has_many :error_logs,
10
21
  -> { latest_first },
11
22
  autosave: true,
@@ -63,27 +63,15 @@ module NdrError
63
63
  destroys.any?
64
64
  end
65
65
 
66
- # Finds gets all errors that share an MD5 hash
67
- # (including _error_).
68
- def self.similar_to(error)
69
- error.error_fingerprint.error_logs.not_deleted
70
- end
71
-
72
- # Gets similar errors.
73
- def similar_errors(include_self = false)
74
- unless defined?(@_similar)
75
- @_similar = {}
76
- @_similar[true] = self.class.similar_to(self)
77
- @_similar[false] = @_similar[true] - [self]
78
- end
79
-
80
- @_similar[include_self ? true : false]
66
+ # returns all sibling occurences, including self
67
+ def similar_errors
68
+ error_fingerprint.error_logs.not_deleted
81
69
  end
82
70
 
83
71
  # Returns the previous historical occurence,
84
72
  # or nil if there wasn't one.
85
73
  def previous
86
- lookup = similar_errors(true).reverse
74
+ lookup = similar_errors.reverse
87
75
  index = lookup.index(self)
88
76
  lookup[0...index].last
89
77
  end
@@ -91,7 +79,7 @@ module NdrError
91
79
  # Returns the next historical occurence,
92
80
  # or nil if there hasn't been one.
93
81
  def next
94
- lookup = similar_errors(true).to_a
82
+ lookup = similar_errors.to_a
95
83
  index = lookup.index(self)
96
84
  lookup[0...index].last
97
85
  end
@@ -116,6 +104,12 @@ module NdrError
116
104
  extract_request_attributes(request)
117
105
  end
118
106
 
107
+ # If we have more details about a parent error, track
108
+ # that too so it can be mixed in to the MD5 digest.
109
+ def register_parent(parent_print)
110
+ @parent_print = parent_print.id if parent_print
111
+ end
112
+
119
113
  # Store as much of `params' as possible in
120
114
  # the YAML parameters column.
121
115
  def parameters_yml=(params)
@@ -158,7 +152,7 @@ module NdrError
158
152
  # Creates (and caches) the md5 of this error,
159
153
  # which is used to match to similar errors.
160
154
  def md5_digest
161
- @_digest ||= fuzz(description, backtrace)
155
+ @_digest ||= fuzz(description, backtrace, parent_print)
162
156
  end
163
157
 
164
158
  # Allow the digest to be set manually if so desired.
@@ -168,6 +162,10 @@ module NdrError
168
162
 
169
163
  private
170
164
 
165
+ def parent_print
166
+ defined?(@parent_print) && @parent_print
167
+ end
168
+
171
169
  # For the given `request' object, return the
172
170
  # parameters in a form suitable for logging.
173
171
  def extract_request_params(request)
@@ -1,3 +1,12 @@
1
+ <%=
2
+ bootstrap_breadcrumbs([
3
+ bootstrap_breadcrumb('Errors', error_fingerprints_path),
4
+ bootstrap_breadcrumb(@fingerprint.id, error_fingerprint_path(@fingerprint), true),
5
+ bootstrap_breadcrumb('Edit', nil)
6
+ ])
7
+ %>
8
+
9
+
1
10
  <%= form_for @fingerprint, as: :error_fingerprint, url: error_fingerprint_path(@fingerprint), method: :put do |form| %>
2
11
  <div class="form-group">
3
12
  <%= form.label :ticket_url, 'Ticket URL' %>
@@ -1,3 +1,9 @@
1
+ <%=
2
+ bootstrap_breadcrumbs([
3
+ bootstrap_breadcrumb('Errors', error_fingerprints_path)
4
+ ])
5
+ %>
6
+
1
7
  <div class="row">
2
8
  <div id="search_form_container" class="col-md-4 col-md-offset-8">
3
9
  <%= form_tag(error_fingerprints_path, method: :get) do %>
@@ -1,4 +1,12 @@
1
- <div>
1
+ <%=
2
+ bootstrap_breadcrumbs([
3
+ bootstrap_breadcrumb('Errors', error_fingerprints_path),
4
+ bootstrap_breadcrumb(@fingerprint.id, error_fingerprint_path(@fingerprint, log_id: @error), true)
5
+ ])
6
+ %>
7
+
8
+ <hr />
9
+ <div class="clearfix">
2
10
  <div class="pull-right">
3
11
  <div class="btn-group">
4
12
  <%= ticket_link_for(@fingerprint) if @fingerprint.ticket_url.present? %>
@@ -8,30 +16,51 @@
8
16
  <%= purge_button_for(@fingerprint) if user_can_edit_errors? %>
9
17
  </div>
10
18
 
11
- <% if @error.similar_errors.any? %>
12
- <div class="">
13
- <%= previous_button_for(@error.previous) %>
19
+ <div class="btn-toolbar">
20
+ <% if @error.similar_errors.length > 1 %>
21
+ <div class="btn-group">
22
+ <%= previous_button_for(@error.previous) %>
23
+
24
+ <div class="btn-group">
25
+ <a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">
26
+ <%= pluralize(@error.similar_errors.length - 1, 'Similar Error') %> Stored
27
+ <span class="caret"></span>
28
+ </a>
29
+ <ul class="dropdown-menu">
30
+ <% @error.similar_errors.each do |other| %>
31
+ <li><%= similar_error_link(other) %></li>
32
+ <% end %>
33
+ </ul>
34
+ </div>
35
+
36
+ <%= next_button_for(@error.next) %>
37
+ </div>
38
+ <% end %>
39
+
40
+ <% if @fingerprint.causal_error_fingerprint %>
41
+ <div class="btn-group">
42
+ <%= link_to bootstrap_icon_tag('arrow-up') + ' View Cause', error_fingerprint_path(@fingerprint.causal_error_fingerprint), class: 'btn btn-default' %>
43
+ </div>
44
+ <% end %>
14
45
 
46
+ <% if @fingerprint.caused_error_fingerprints.any? %>
15
47
  <div class="btn-group">
16
48
  <a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">
17
- <%= pluralize(@error.similar_errors.length, 'Similar Error') %> Stored
49
+ <%= pluralize(@fingerprint.caused_error_fingerprints.length, 'Downstream Error') %> Stored
18
50
  <span class="caret"></span>
19
51
  </a>
20
52
  <ul class="dropdown-menu">
21
- <% @error.similar_errors.each do |other| %>
22
- <li><%= similar_error_link(other) %></li>
53
+ <% @fingerprint.caused_error_fingerprints.each do |print| %>
54
+ <li><%= downstream_fingerprint_link print %></li>
23
55
  <% end %>
24
56
  </ul>
25
57
  </div>
58
+ <% end %>
59
+ </div>
26
60
 
27
- <%= next_button_for(@error.next) %>
28
- </div>
29
- <% end %>
30
61
  </div>
31
62
 
32
- <hr/>
33
63
  <h1>
34
- <%= link_to 'Errors', error_fingerprints_path %> &#187;
35
64
  <%= @error.error_class %>
36
65
  <br><small><%=h @error.description %></small>
37
66
  </h1>
@@ -1,4 +1,4 @@
1
- # Adds complete ERROR_FINGERPRINT table to schema
1
+ # Adds original ERROR_FINGERPRINT table to schema
2
2
  class CreateErrorFingerprints < NdrError.migration_class
3
3
  def change
4
4
  create_table :error_fingerprints, id: false do |t|
@@ -0,0 +1,12 @@
1
+ # Adds supplementary column to error fingerprint
2
+ class AddCauseToErrorFingerprints < NdrError.migration_class
3
+ def change
4
+ add_column :error_fingerprints, :causal_error_fingerprintid, :string
5
+
6
+ add_foreign_key :error_fingerprints, :error_fingerprints,
7
+ column: :causal_error_fingerprintid,
8
+ primary_key: :error_fingerprintid
9
+
10
+ add_index :error_fingerprints, :causal_error_fingerprintid
11
+ end
12
+ end
@@ -1,8 +1,12 @@
1
1
  module NdrError
2
2
  # Mixin to help with fuzzing of exception messages/traces.
3
3
  module Fuzzing
4
- def fuzz(description, backtrace)
5
- Digest::MD5.hexdigest(fuzz_description(description) + fuzz_backtrace(backtrace))
4
+ def fuzz(description, backtrace, parent_print = nil)
5
+ Digest::MD5.hexdigest([
6
+ fuzz_description(description),
7
+ fuzz_backtrace(backtrace),
8
+ parent_print
9
+ ].compact.join)
6
10
  end
7
11
 
8
12
  private
@@ -6,16 +6,28 @@ module NdrError
6
6
 
7
7
  # Log the given `exception`.
8
8
  def log(exception, ancillary_data, request_object)
9
+ # Capture details about a parent exception, if possible:
10
+ parent_print, = exception.cause && log(exception.cause, ancillary_data, request_object)
11
+
9
12
  log = initialize_log(ancillary_data)
10
13
  log.register_exception(exception)
11
14
  log.register_request(request_object)
15
+ log.register_parent(parent_print)
12
16
 
13
17
  print = Fingerprint.find_or_create_by_id(log.md5_digest)
18
+ print.causal_error_fingerprint = parent_print
14
19
  error = print.store_log(log)
15
20
 
16
21
  [print, error]
17
22
  end
18
23
 
24
+ def monitor(ancillary_data: {}, request: nil, swallow: false)
25
+ yield
26
+ rescue Exception => exception # rubocop:disable Lint/RescueException
27
+ data = log(exception, ancillary_data, request)
28
+ swallow ? data : raise(exception)
29
+ end
30
+
19
31
  private
20
32
 
21
33
  # Manual attribute whitelisting:
@@ -28,7 +28,7 @@ module NdrError
28
28
  # Unhandled exceptions with logging could terminate the web server!
29
29
  def rescuing_everything
30
30
  yield
31
- rescue Exception => exception
31
+ rescue Exception => exception # rubocop:disable Lint/RescueException
32
32
  # "Log the exception caused by logging an exception..."
33
33
  Rails.logger.warn <<-MSG.strip_heredoc
34
34
  NdrError failed to log an exception!
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  # Contains the version of NdrError. Sourced by the gemspec.
3
3
  module NdrError
4
- VERSION = '1.1.4'.freeze
4
+ VERSION = '2.0.0'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ndr_error
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - NCRS Development Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-30 00:00:00.000000000 Z
11
+ date: 2018-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '4.1'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '5.2'
22
+ version: '6'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '4.1'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '5.2'
32
+ version: '6'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: will_paginate
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -134,14 +134,28 @@ dependencies:
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '2.1'
137
+ version: '3.0'
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '2.1'
144
+ version: '3.0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: database_cleaner
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
145
159
  description: Mountable engine for exception logging and fingerprinting
146
160
  email: []
147
161
  executables: []
@@ -166,6 +180,7 @@ files:
166
180
  - config/routes.rb
167
181
  - db/migrate/20150918162403_create_error_fingerprints.rb
168
182
  - db/migrate/20150918162612_create_error_logs.rb
183
+ - db/migrate/20180203174345_add_cause_to_error_fingerprints.rb
169
184
  - lib/ndr_error.rb
170
185
  - lib/ndr_error/backtrace_compression.rb
171
186
  - lib/ndr_error/engine.rb
@@ -196,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
211
  version: '0'
197
212
  requirements: []
198
213
  rubyforge_project:
199
- rubygems_version: 2.6.14
214
+ rubygems_version: 2.5.2.3
200
215
  signing_key:
201
216
  specification_version: 4
202
217
  summary: Rails exception logging