exception_handling 2.2.1 → 2.3.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -0
- data/Gemfile +7 -6
- data/Gemfile.lock +26 -23
- data/README.md +0 -1
- data/Rakefile +4 -4
- data/config/exception_filters.yml +2 -3
- data/exception_handling.gemspec +12 -10
- data/lib/exception_handling/exception_catalog.rb +5 -4
- data/lib/exception_handling/exception_description.rb +28 -28
- data/lib/exception_handling/exception_info.rb +80 -72
- data/lib/exception_handling/honeybadger_callbacks.rb +41 -24
- data/lib/exception_handling/log_stub_error.rb +10 -8
- data/lib/exception_handling/mailer.rb +27 -48
- data/lib/exception_handling/methods.rb +15 -11
- data/lib/exception_handling/sensu.rb +7 -5
- data/lib/exception_handling/testing.rb +21 -19
- data/lib/exception_handling/version.rb +1 -1
- data/lib/exception_handling.rb +105 -200
- data/test/helpers/controller_helpers.rb +3 -1
- data/test/helpers/exception_helpers.rb +9 -0
- data/test/test_helper.rb +26 -21
- data/test/unit/exception_handling/exception_catalog_test.rb +15 -14
- data/test/unit/exception_handling/exception_description_test.rb +22 -31
- data/test/unit/exception_handling/exception_info_test.rb +76 -37
- data/test/unit/exception_handling/honeybadger_callbacks_test.rb +46 -9
- data/test/unit/exception_handling/log_error_stub_test.rb +6 -4
- data/test/unit/exception_handling/mailer_test.rb +8 -14
- data/test/unit/exception_handling/methods_test.rb +9 -6
- data/test/unit/exception_handling/sensu_test.rb +6 -4
- data/test/unit/exception_handling_test.rb +279 -364
- metadata +24 -24
- data/views/exception_handling/mailer/exception_notification.html.erb +0 -92
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1538b60821d54ce39c0d24c94378f147f3c1cdea
|
4
|
+
data.tar.gz: d34346f81571519472db2dfd77d94fec6e31cdec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f588ceffb08a99941eb044c48c1de3d843fd9dfdfa6863bb778e95e099a2a7b29ad9081e66d4ec36ffe1cae2c91028d812c2af173e06ba444502ca41fe3c1829
|
7
|
+
data.tar.gz: 0f376e25489540e95224a17c0b1a86ddeb1a7a1fe544f8391c3deef4a74c66068170510ef1f733e83e936461cdb7230214774c8b62397ec4fd1d45f3e6bb76eb
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
# This rubocop config file inherits from our centralized style-guide repository.
|
2
|
+
# If you are looking to update the ruby style guide, be sure to both update the rubocop config
|
3
|
+
# as well as the README.md
|
4
|
+
# https://github.com/Invoca/style-guide/tree/master/ruby
|
5
|
+
inherit_from: https://raw.githubusercontent.com/Invoca/style-guide/master/ruby/.rubocop.yml
|
data/Gemfile
CHANGED
@@ -1,19 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
# Specify your gem's dependencies in attr_default.gemspec
|
4
6
|
gemspec
|
5
7
|
|
6
|
-
gem 'hobo_support', '2.0.1', git: 'git@github.com:Invoca/hobosupport', ref: 'b9086322274b474a2b5bae507c4885e55d4aa050'
|
7
|
-
gem 'invoca-utils', git: 'git@github.com:Invoca/invoca-utils', ref: '891b8f7e1af0f6324bf85601046907143122e204'
|
8
|
-
gem 'activesupport', '>= 4.2.11.1'
|
9
|
-
gem 'actionpack', '>= 4.2.11.1'
|
10
8
|
gem 'actionmailer', '>= 4.2.11.1'
|
9
|
+
gem 'actionpack', '>= 4.2.11.1'
|
10
|
+
gem 'activesupport', '>= 4.2.11.1'
|
11
11
|
|
12
12
|
group :development do
|
13
|
+
gem 'pry'
|
13
14
|
gem 'rake', '>=0.9'
|
14
|
-
gem 'shoulda', '> 3.1.1'
|
15
15
|
gem 'rr'
|
16
|
-
gem '
|
16
|
+
gem 'rubocop'
|
17
|
+
gem 'shoulda', '> 3.1.1'
|
17
18
|
end
|
18
19
|
|
19
20
|
group :test do
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,3 @@
|
|
1
|
-
GIT
|
2
|
-
remote: git@github.com:Invoca/hobosupport
|
3
|
-
revision: b9086322274b474a2b5bae507c4885e55d4aa050
|
4
|
-
ref: b9086322274b474a2b5bae507c4885e55d4aa050
|
5
|
-
specs:
|
6
|
-
hobo_support (2.0.1)
|
7
|
-
rails (~> 4.2.10)
|
8
|
-
|
9
1
|
GIT
|
10
2
|
remote: git@github.com:Invoca/honeybadger-ruby
|
11
3
|
revision: bb5f2b8a86e4147c38a6270d39ad610fab4dd5e6
|
@@ -13,17 +5,10 @@ GIT
|
|
13
5
|
specs:
|
14
6
|
honeybadger (3.3.1.pre.1)
|
15
7
|
|
16
|
-
GIT
|
17
|
-
remote: git@github.com:Invoca/invoca-utils
|
18
|
-
revision: 891b8f7e1af0f6324bf85601046907143122e204
|
19
|
-
ref: 891b8f7e1af0f6324bf85601046907143122e204
|
20
|
-
specs:
|
21
|
-
invoca-utils (0.0.3)
|
22
|
-
|
23
8
|
PATH
|
24
9
|
remote: .
|
25
10
|
specs:
|
26
|
-
exception_handling (2.
|
11
|
+
exception_handling (2.3.0.pre.1)
|
27
12
|
actionmailer (~> 4.2)
|
28
13
|
actionpack (~> 4.2)
|
29
14
|
activesupport (~> 4.2)
|
@@ -70,19 +55,25 @@ GEM
|
|
70
55
|
thread_safe (~> 0.3, >= 0.3.4)
|
71
56
|
tzinfo (~> 1.1)
|
72
57
|
arel (6.0.4)
|
58
|
+
ast (2.4.0)
|
73
59
|
builder (3.2.3)
|
74
60
|
coderay (1.1.2)
|
75
61
|
concurrent-ruby (1.1.5)
|
76
|
-
contextual_logger (0.
|
62
|
+
contextual_logger (0.3.1)
|
63
|
+
activesupport
|
77
64
|
json
|
78
65
|
crass (1.0.4)
|
79
66
|
erubis (2.7.0)
|
80
67
|
eventmachine (1.2.7)
|
81
68
|
globalid (0.4.2)
|
82
69
|
activesupport (>= 4.2.0)
|
70
|
+
hobo_support (2.2.6)
|
71
|
+
rails (~> 4.2.6)
|
83
72
|
i18n (0.9.5)
|
84
73
|
concurrent-ruby (~> 1.0)
|
85
|
-
|
74
|
+
invoca-utils (0.0.5)
|
75
|
+
jaro_winkler (1.5.3)
|
76
|
+
json (2.3.0)
|
86
77
|
loofah (2.2.3)
|
87
78
|
crass (~> 1.0.2)
|
88
79
|
nokogiri (>= 1.5.9)
|
@@ -92,8 +83,11 @@ GEM
|
|
92
83
|
mini_mime (1.0.1)
|
93
84
|
mini_portile2 (2.4.0)
|
94
85
|
minitest (5.11.3)
|
95
|
-
nokogiri (1.10.
|
86
|
+
nokogiri (1.10.4)
|
96
87
|
mini_portile2 (~> 2.4.0)
|
88
|
+
parallel (1.17.0)
|
89
|
+
parser (2.6.3.0)
|
90
|
+
ast (~> 2.4.0)
|
97
91
|
pry (0.12.2)
|
98
92
|
coderay (~> 1.1.0)
|
99
93
|
method_source (~> 0.9.0)
|
@@ -124,8 +118,17 @@ GEM
|
|
124
118
|
activesupport (= 4.2.11.1)
|
125
119
|
rake (>= 0.8.7)
|
126
120
|
thor (>= 0.18.1, < 2.0)
|
121
|
+
rainbow (3.0.0)
|
127
122
|
rake (12.3.2)
|
128
123
|
rr (1.2.1)
|
124
|
+
rubocop (0.74.0)
|
125
|
+
jaro_winkler (~> 1.5.1)
|
126
|
+
parallel (~> 1.10)
|
127
|
+
parser (>= 2.6)
|
128
|
+
rainbow (>= 2.2.2, < 4.0)
|
129
|
+
ruby-progressbar (~> 1.7)
|
130
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
131
|
+
ruby-progressbar (1.10.1)
|
129
132
|
shoulda (3.6.0)
|
130
133
|
shoulda-context (~> 1.0, >= 1.0.1)
|
131
134
|
shoulda-matchers (~> 3.0)
|
@@ -139,10 +142,11 @@ GEM
|
|
139
142
|
actionpack (>= 4.0)
|
140
143
|
activesupport (>= 4.0)
|
141
144
|
sprockets (>= 3.0.0)
|
142
|
-
thor (0.
|
145
|
+
thor (1.0.1)
|
143
146
|
thread_safe (0.3.6)
|
144
147
|
tzinfo (1.2.5)
|
145
148
|
thread_safe (~> 0.1)
|
149
|
+
unicode-display_width (1.6.0)
|
146
150
|
|
147
151
|
PLATFORMS
|
148
152
|
ruby
|
@@ -152,13 +156,12 @@ DEPENDENCIES
|
|
152
156
|
actionpack (>= 4.2.11.1)
|
153
157
|
activesupport (>= 4.2.11.1)
|
154
158
|
exception_handling!
|
155
|
-
hobo_support (= 2.0.1)!
|
156
159
|
honeybadger (= 3.3.1.pre.1)!
|
157
|
-
invoca-utils!
|
158
160
|
pry
|
159
161
|
rake (>= 0.9)
|
160
162
|
rr
|
163
|
+
rubocop
|
161
164
|
shoulda (> 3.1.1)
|
162
165
|
|
163
166
|
BUNDLED WITH
|
164
|
-
1.
|
167
|
+
1.17.2
|
data/README.md
CHANGED
@@ -31,7 +31,6 @@ For example:
|
|
31
31
|
|
32
32
|
# optional
|
33
33
|
ExceptionHandling.escalation_recipients = ['escalation@example.com']
|
34
|
-
ExceptionHandling.mailer_send_enabled = true # false, will disable exception emails
|
35
34
|
ExceptionHandling.filter_list_filename = "#{Rails.root}/config/exception_filters.yml"
|
36
35
|
ExceptionHandling.email_environment = Rails.env
|
37
36
|
ExceptionHandling.eventmachine_safe = false
|
data/Rakefile
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
require "bundler/gem_tasks"
|
3
5
|
require 'rake/testtask'
|
4
6
|
|
5
7
|
namespace :test do
|
6
|
-
|
7
8
|
Rake::TestTask.new do |t|
|
8
9
|
t.name = :unit
|
9
10
|
t.libs << "test"
|
@@ -11,8 +12,7 @@ namespace :test do
|
|
11
12
|
t.verbose = true
|
12
13
|
end
|
13
14
|
Rake::Task['test:unit'].comment = "Run the unit tests"
|
14
|
-
|
15
15
|
end
|
16
16
|
|
17
|
-
task :
|
18
|
-
task :
|
17
|
+
task test: 'test:unit'
|
18
|
+
task default: 'test'
|
data/exception_handling.gemspec
CHANGED
@@ -1,24 +1,26 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('lib/exception_handling/version', __dir__)
|
2
4
|
|
3
5
|
Gem::Specification.new do |spec|
|
4
6
|
spec.authors = ["Colin Kelley"]
|
5
7
|
spec.email = ["colindkelley@gmail.com"]
|
6
|
-
spec.description =
|
7
|
-
spec.summary =
|
8
|
+
spec.description = 'Exception handling logger/emailer'
|
9
|
+
spec.summary = "Invoca's exception handling logger/emailer layer, based on exception_notifier. Works with Rails or EventMachine or EventMachine+Synchrony."
|
8
10
|
spec.homepage = "https://github.com/Invoca/exception_handling"
|
9
11
|
|
10
|
-
spec.files = `git ls-files`.split(
|
11
|
-
spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
12
|
+
spec.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
13
|
+
spec.executables = spec.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
12
14
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/.*\.rb})
|
13
15
|
spec.name = "exception_handling"
|
14
16
|
spec.require_paths = ["lib"]
|
15
17
|
spec.version = ExceptionHandling::VERSION
|
16
18
|
|
17
|
-
spec.add_dependency 'eventmachine', '~> 1.0'
|
18
|
-
spec.add_dependency 'activesupport', '~> 4.2'
|
19
|
-
spec.add_dependency 'actionpack', '~> 4.2'
|
20
19
|
spec.add_dependency 'actionmailer', '~> 4.2'
|
21
|
-
spec.add_dependency '
|
22
|
-
spec.add_dependency '
|
20
|
+
spec.add_dependency 'actionpack', '~> 4.2'
|
21
|
+
spec.add_dependency 'activesupport', '~> 4.2'
|
23
22
|
spec.add_dependency 'contextual_logger'
|
23
|
+
spec.add_dependency 'eventmachine', '~> 1.0'
|
24
|
+
spec.add_dependency 'hobo_support'
|
25
|
+
spec.add_dependency 'invoca-utils', '~> 0.0'
|
24
26
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ExceptionHandling
|
2
4
|
class ExceptionCatalog
|
3
5
|
|
4
6
|
def initialize(filter_path)
|
5
7
|
@filter_path = filter_path
|
6
|
-
@filters = {
|
8
|
+
@filters = {}
|
7
9
|
@filters_last_modified_time = nil
|
8
10
|
end
|
9
11
|
|
@@ -21,7 +23,6 @@ module ExceptionHandling
|
|
21
23
|
load_file
|
22
24
|
end
|
23
25
|
end
|
24
|
-
|
25
26
|
rescue => ex # any exceptions
|
26
27
|
# DO NOT CALL ExceptionHandling.log_error because this method is called from that. It can loop and cause mayhem.
|
27
28
|
ExceptionHandling.write_exception_to_log(ex, "ExceptionCatalog#refresh_filters: #{@filter_path}", Time.now.to_i)
|
@@ -30,9 +31,9 @@ module ExceptionHandling
|
|
30
31
|
def load_file
|
31
32
|
@filters_last_modified_time = last_modified_time # make race condition fall on the side of reloading unnecessarily next time rather than missing a set of changes
|
32
33
|
|
33
|
-
filters = YAML
|
34
|
+
filters = YAML.load_file(@filter_path)
|
34
35
|
filter_hash_values = filters.map { |filter_name, regexes| [filter_name.to_sym, ExceptionDescription.new(filter_name.to_sym, regexes.symbolize_keys)] }
|
35
|
-
@filters = Hash[
|
36
|
+
@filters = Hash[filter_hash_values]
|
36
37
|
end
|
37
38
|
|
38
39
|
def last_modified_time
|
@@ -1,59 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ExceptionHandling
|
2
4
|
class ExceptionDescription
|
3
|
-
MATCH_SECTIONS =
|
5
|
+
MATCH_SECTIONS = [:error, :request, :session, :environment, :backtrace, :event_response].freeze
|
4
6
|
|
5
7
|
CONFIGURATION_SECTIONS = {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
}
|
8
|
+
send_to_honeybadger: false, # should be sent to honeybadger?
|
9
|
+
send_metric: true, # should the metric be sent.
|
10
|
+
metric_name: nil, # Will be derived from section name if not passed
|
11
|
+
notes: nil # Will be included in exception email if set, used to keep notes and relevant links
|
12
|
+
}.freeze
|
12
13
|
|
13
|
-
attr_reader :filter_name, :
|
14
|
+
attr_reader :filter_name, :send_to_honeybadger, :send_metric, :metric_name, :notes
|
14
15
|
|
15
16
|
def initialize(filter_name, configuration)
|
16
17
|
@filter_name = filter_name
|
17
18
|
|
18
19
|
invalid_sections = configuration.except(*(CONFIGURATION_SECTIONS.keys + MATCH_SECTIONS))
|
19
|
-
invalid_sections.empty? or raise ArgumentError, "Unknown section: #{invalid_sections.keys.join(
|
20
|
+
invalid_sections.empty? or raise ArgumentError, "Unknown section: #{invalid_sections.keys.join(',')}"
|
20
21
|
|
21
22
|
@configuration = CONFIGURATION_SECTIONS.merge(configuration)
|
22
|
-
@send_email = @configuration[:send_email]
|
23
23
|
@send_to_honeybadger = @configuration[:send_to_honeybadger]
|
24
24
|
@send_metric = @configuration[:send_metric]
|
25
|
-
@metric_name = (@configuration[:metric_name] || @filter_name
|
25
|
+
@metric_name = (@configuration[:metric_name] || @filter_name).to_s.gsub(" ", "_")
|
26
26
|
@notes = @configuration[:notes]
|
27
27
|
|
28
|
-
regex_config = @configuration.reject { |k,v| k.in?(CONFIGURATION_SECTIONS.keys) || v.blank? }
|
28
|
+
regex_config = @configuration.reject { |k, v| k.in?(CONFIGURATION_SECTIONS.keys) || v.blank? }
|
29
29
|
|
30
|
-
@regexes = Hash[regex_config.map { |section, regex| [section, Regexp.new(regex, Regexp::IGNORECASE | Regexp::MULTILINE)
|
30
|
+
@regexes = Hash[regex_config.map { |section, regex| [section, Regexp.new(regex, Regexp::IGNORECASE | Regexp::MULTILINE)] }]
|
31
31
|
|
32
32
|
!@regexes.empty? or raise ArgumentError, "Filter #{filter_name} has all blank regexes: #{configuration.inspect}"
|
33
33
|
end
|
34
34
|
|
35
35
|
def exception_data
|
36
36
|
{
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
"send_metric" => send_metric,
|
38
|
+
"metric_name" => metric_name,
|
39
|
+
"notes" => notes
|
40
40
|
}
|
41
41
|
end
|
42
42
|
|
43
43
|
def match?(exception_data)
|
44
44
|
@regexes.all? do |section, regex|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
case target = exception_data[section.to_s] || exception_data[section]
|
46
|
+
when String
|
47
|
+
regex =~ target
|
48
|
+
when Array
|
49
|
+
target.any? { |row| row =~ regex }
|
50
|
+
when Hash
|
51
|
+
target[:to_s] =~ regex
|
52
|
+
when NilClass
|
53
|
+
false
|
54
|
+
else
|
55
|
+
raise "Unexpected class #{exception_data[section].class.name}"
|
56
|
+
end
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ExceptionHandling
|
2
4
|
class ExceptionInfo
|
3
5
|
|
@@ -6,47 +8,45 @@ module ExceptionHandling
|
|
6
8
|
/^QUERY_/,
|
7
9
|
/^REQUEST_/,
|
8
10
|
/^SERVER_/
|
9
|
-
]
|
10
|
-
|
11
|
-
ENVIRONMENT_OMIT =(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
HTTP_ACCEPT: */*
|
16
|
-
|
17
|
-
|
18
|
-
HTTP_ACCEPT_ENCODING: gzip,
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
TERM:
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
SECTIONS = [:request, :session, :environment, :backtrace, :event_response]
|
49
|
-
HONEYBADGER_CONTEXT_SECTIONS = [:timestamp, :error_class, :exception_context, :server, :scm_revision, :notes, :user_details, :request, :session, :environment, :backtrace, :event_response]
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
ENVIRONMENT_OMIT = <<~EOS.split("\n")
|
14
|
+
CONTENT_TYPE: application/x-www-form-urlencoded
|
15
|
+
GATEWAY_INTERFACE: CGI/1.2
|
16
|
+
HTTP_ACCEPT: */*
|
17
|
+
HTTP_ACCEPT: */*, text/javascript, text/html, application/xml, text/xml, */*
|
18
|
+
HTTP_ACCEPT_CHARSET: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
19
|
+
HTTP_ACCEPT_ENCODING: gzip, deflate
|
20
|
+
HTTP_ACCEPT_ENCODING: gzip,deflate
|
21
|
+
HTTP_ACCEPT_LANGUAGE: en-us
|
22
|
+
HTTP_CACHE_CONTROL: no-cache
|
23
|
+
HTTP_CONNECTION: Keep-Alive
|
24
|
+
HTTP_HOST: www.invoca.com
|
25
|
+
HTTP_MAX_FORWARDS: 10
|
26
|
+
HTTP_UA_CPU: x86
|
27
|
+
HTTP_VERSION: HTTP/1.1
|
28
|
+
HTTP_X_FORWARDED_HOST: www.invoca.com
|
29
|
+
HTTP_X_FORWARDED_SERVER: www2.invoca.com
|
30
|
+
HTTP_X_REQUESTED_WITH: XMLHttpRequest
|
31
|
+
LANG:
|
32
|
+
PATH: /sbin:/usr/sbin:/bin:/usr/bin
|
33
|
+
PWD: /
|
34
|
+
RAILS_ENV: production
|
35
|
+
RAW_POST_DATA: id=500
|
36
|
+
REMOTE_ADDR: 10.251.34.225
|
37
|
+
SCRIPT_NAME: /
|
38
|
+
SERVER_NAME: www.invoca.com
|
39
|
+
SERVER_PORT: 80
|
40
|
+
SERVER_PROTOCOL: HTTP/1.1
|
41
|
+
SERVER_SOFTWARE: Mongrel 1.1.4
|
42
|
+
SHLVL: 1
|
43
|
+
TERM: linux
|
44
|
+
TERM: xterm-color
|
45
|
+
_: /usr/bin/mongrel_cluster_ctl
|
46
|
+
EOS
|
47
|
+
|
48
|
+
SECTIONS = [:request, :session, :environment, :backtrace, :event_response].freeze
|
49
|
+
HONEYBADGER_CONTEXT_SECTIONS = [:timestamp, :error_class, :exception_context, :server, :scm_revision, :notes, :user_details, :request, :session, :environment, :backtrace, :event_response].freeze
|
50
50
|
|
51
51
|
attr_reader :exception, :controller, :exception_context, :timestamp
|
52
52
|
|
@@ -71,13 +71,19 @@ EOF
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def send_to_honeybadger?
|
74
|
-
ExceptionHandling.
|
74
|
+
ExceptionHandling.honeybadger_defined? && (!exception_description || exception_description.send_to_honeybadger)
|
75
75
|
end
|
76
76
|
|
77
77
|
def honeybadger_context_data
|
78
78
|
@honeybadger_context_data ||= enhanced_data_to_honeybadger_context
|
79
79
|
end
|
80
80
|
|
81
|
+
def controller_name
|
82
|
+
@controller_name ||= if @controller
|
83
|
+
@controller.request.parameters.with_indifferent_access[:controller]
|
84
|
+
end.to_s
|
85
|
+
end
|
86
|
+
|
81
87
|
private
|
82
88
|
|
83
89
|
def controller_from_context(exception_context)
|
@@ -88,10 +94,10 @@ EOF
|
|
88
94
|
exception_message = @exception.message.to_s
|
89
95
|
data = ActiveSupport::HashWithIndifferentAccess.new
|
90
96
|
data[:error_class] = @exception.class.name
|
91
|
-
data[:error_string]= "#{data[:error_class]}: #{ExceptionHandling.encode_utf8(exception_message)}"
|
97
|
+
data[:error_string] = "#{data[:error_class]}: #{ExceptionHandling.encode_utf8(exception_message)}"
|
92
98
|
data[:timestamp] = @timestamp
|
93
99
|
data[:backtrace] = ExceptionHandling.clean_backtrace(@exception)
|
94
|
-
if @exception_context
|
100
|
+
if @exception_context&.is_a?(Hash)
|
95
101
|
# if we are a hash, then we got called from the DebugExceptions rack middleware filter
|
96
102
|
# and we need to do some things different to get the info we want
|
97
103
|
data[:error] = "#{data[:error_class]}: #{ExceptionHandling.encode_utf8(exception_message)}"
|
@@ -118,7 +124,8 @@ EOF
|
|
118
124
|
end
|
119
125
|
|
120
126
|
def enhance_exception_data(data)
|
121
|
-
return if !
|
127
|
+
return if !ExceptionHandling.custom_data_hook
|
128
|
+
|
122
129
|
begin
|
123
130
|
ExceptionHandling.custom_data_hook.call(data)
|
124
131
|
rescue Exception => ex
|
@@ -131,28 +138,29 @@ EOF
|
|
131
138
|
def normalize_exception_data(data)
|
132
139
|
if data[:location].nil?
|
133
140
|
data[:location] = {}
|
134
|
-
if data[:request]
|
141
|
+
if data[:request]&.key?(:params)
|
135
142
|
data[:location][:controller] = data[:request][:params]['controller']
|
136
143
|
data[:location][:action] = data[:request][:params]['action']
|
137
144
|
end
|
138
145
|
end
|
139
|
-
if data[:backtrace]
|
146
|
+
if data[:backtrace]&.first
|
140
147
|
first_line = data[:backtrace].first
|
141
148
|
|
142
149
|
# template exceptions have the line number and filename as the first element in backtrace
|
143
|
-
if matched = first_line.match(
|
144
|
-
backtrace_hash = {
|
145
|
-
|
146
|
-
|
150
|
+
if (matched = first_line.match(/on line #(\d*) of (.*)/i))
|
151
|
+
backtrace_hash = {
|
152
|
+
line: matched[1],
|
153
|
+
file: matched[2]
|
154
|
+
}
|
147
155
|
else
|
148
|
-
backtrace_hash = Hash[* [:file, :line].zip(
|
156
|
+
backtrace_hash = Hash[* [:file, :line].zip(first_line.split(':')[0..1]).flatten]
|
149
157
|
end
|
150
158
|
|
151
|
-
data[:location].merge!(
|
159
|
+
data[:location].merge!(backtrace_hash)
|
152
160
|
end
|
153
161
|
end
|
154
162
|
|
155
|
-
def clean_exception_data(
|
163
|
+
def clean_exception_data(data)
|
156
164
|
if (as_array = data[:backtrace].to_a).size == 1
|
157
165
|
data[:backtrace] = as_array.first.to_s.split(/\n\s*/)
|
158
166
|
end
|
@@ -197,16 +205,16 @@ EOF
|
|
197
205
|
def extract_and_merge_controller_data(data)
|
198
206
|
if @controller
|
199
207
|
data[:request] = {
|
200
|
-
params:
|
201
|
-
rails_root:
|
202
|
-
url:
|
208
|
+
params: @controller.request.parameters.to_hash,
|
209
|
+
rails_root: defined?(Rails) && defined?(Rails.root) ? Rails.root : "Rails.root not defined. Is this a test environment?",
|
210
|
+
url: @controller.complete_request_uri
|
203
211
|
}
|
204
212
|
data[:environment].merge!(@controller.request.env.to_hash)
|
205
213
|
|
206
214
|
@controller.session[:fault_in_session]
|
207
215
|
data[:session] = {
|
208
|
-
key:
|
209
|
-
data:
|
216
|
+
key: @controller.request.session_options[:id],
|
217
|
+
data: @controller.session.to_hash
|
210
218
|
}
|
211
219
|
end
|
212
220
|
end
|
@@ -236,22 +244,22 @@ EOF
|
|
236
244
|
end
|
237
245
|
end
|
238
246
|
|
239
|
-
def add_to_s(
|
240
|
-
data_section[:to_s] = dump_hash(
|
247
|
+
def add_to_s(data_section)
|
248
|
+
data_section[:to_s] = dump_hash(data_section)
|
241
249
|
end
|
242
250
|
|
243
|
-
def dump_hash(
|
244
|
-
result = ""
|
245
|
-
h
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
251
|
+
def dump_hash(h, indent_level = 0)
|
252
|
+
result = +""
|
253
|
+
h&.sort { |a, b| a.to_s <=> b.to_s }&.each do |key, value|
|
254
|
+
result << ' ' * (2 * indent_level)
|
255
|
+
result << "#{key}:"
|
256
|
+
case value
|
257
|
+
when Hash
|
258
|
+
result << "\n" << dump_hash(value, indent_level + 1)
|
259
|
+
else
|
260
|
+
result << " #{value}\n"
|
261
|
+
end
|
253
262
|
end
|
254
|
-
end unless h.nil?
|
255
263
|
result
|
256
264
|
end
|
257
265
|
|