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 +4 -4
- data/app/controllers/ndr_error/application_controller.rb +2 -0
- data/app/controllers/ndr_error/errors_controller.rb +2 -0
- data/app/helpers/ndr_error/errors_helper.rb +12 -5
- data/app/models/ndr_error/fingerprint.rb +11 -0
- data/app/models/ndr_error/log.rb +16 -18
- data/app/views/ndr_error/errors/edit.html.erb +9 -0
- data/app/views/ndr_error/errors/index.html.erb +6 -0
- data/app/views/ndr_error/errors/show.html.erb +41 -12
- data/db/migrate/20150918162403_create_error_fingerprints.rb +1 -1
- data/db/migrate/20180203174345_add_cause_to_error_fingerprints.rb +12 -0
- data/lib/ndr_error/fuzzing.rb +6 -2
- data/lib/ndr_error/logging.rb +12 -0
- data/lib/ndr_error/middleware/public_exceptions.rb +1 -1
- data/lib/ndr_error/version.rb +1 -1
- metadata +22 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca01898083de92ab17019a9f2f312f4536bcf144
|
4
|
+
data.tar.gz: 8593a587b1fd43619dfebe0002205c78ea1018cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4b6b12acc1e1472a63d0c14df1254a6789a83acf9894ea60a319d71a1a19b6c9926de3ac7db4b3cd875ac51a450729e968b11e1dedaedf689703c39b2d34400
|
7
|
+
data.tar.gz: 1151c024cde520d1d6ada13e679e7f12bacfebe292db259a7c4f31a45b489c4829933c922d22cefbcbc413aa8979ef16d228d0ab51aa80c6235003f36bda5704
|
@@ -43,10 +43,17 @@ module NdrError
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def similar_error_link(error)
|
46
|
-
|
47
|
-
text
|
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
|
-
|
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')
|
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 =
|
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,
|
data/app/models/ndr_error/log.rb
CHANGED
@@ -63,27 +63,15 @@ module NdrError
|
|
63
63
|
destroys.any?
|
64
64
|
end
|
65
65
|
|
66
|
-
#
|
67
|
-
|
68
|
-
|
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
|
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
|
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,4 +1,12 @@
|
|
1
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
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(@
|
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
|
-
<% @
|
22
|
-
<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 %> »
|
35
64
|
<%= @error.error_class %>
|
36
65
|
<br><small><%=h @error.description %></small>
|
37
66
|
</h1>
|
@@ -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
|
data/lib/ndr_error/fuzzing.rb
CHANGED
@@ -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(
|
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
|
data/lib/ndr_error/logging.rb
CHANGED
@@ -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!
|
data/lib/ndr_error/version.rb
CHANGED
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:
|
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-
|
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: '
|
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: '
|
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: '
|
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: '
|
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.
|
214
|
+
rubygems_version: 2.5.2.3
|
200
215
|
signing_key:
|
201
216
|
specification_version: 4
|
202
217
|
summary: Rails exception logging
|