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 +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
|