ndr_error 1.1.4 → 2.0.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
  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