temescal 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/temescal/configuration.rb +10 -0
- data/lib/temescal/error.rb +1 -1
- data/lib/temescal/monitors.rb +10 -0
- data/lib/temescal/response.rb +2 -2
- data/lib/temescal/version.rb +1 -1
- data/spec/lib/temescal/configuration_spec.rb +3 -3
- data/spec/lib/temescal/error_spec.rb +21 -21
- data/spec/lib/temescal/middleware_spec.rb +33 -17
- data/spec/lib/temescal/monitors_spec.rb +30 -12
- data/spec/spec_helper.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99d0eb1cb114d96a76bdc45a6f31beb902d05028
|
4
|
+
data.tar.gz: 823a730b2904628aa8db967e31fed3d4630faad3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b43e4795769e8de711b82ba6395d885eb01c8c653f4ad433b7dbbc42c118e55d2d00ae9dd0f96acf4638b05de2660ace17984a5fd90c03265058a75a7afc4df
|
7
|
+
data.tar.gz: 5afc871cd1ffa133dacae0eb0e32ae7b8d1b8b8b581a431e02019dee9330cb7a0d531f3aa8dda12efbc6ddb43552e9b8c16e6adfd3824b348beca0850d8984da
|
data/README.md
CHANGED
@@ -43,6 +43,7 @@ The services currently supported are:
|
|
43
43
|
* [Airbrake](https://airbrake.io/)
|
44
44
|
* [Bugsnag](https://bugsnag.com/)
|
45
45
|
* [New Relic](http://newrelic.com/)
|
46
|
+
* [Honeybadger](https://www.honeybadger.io/)
|
46
47
|
|
47
48
|
If you use a different monitoring service that you'd like to see supported, feel free to submit an issue. Better yet, pull requests are more than welcome!
|
48
49
|
|
@@ -51,7 +52,7 @@ Note that you'll need the gem for your monitor installed and configured for your
|
|
51
52
|
## Configuration
|
52
53
|
Temescal provides several configuration options for you. You can set these options when configuring the middleware for your application.
|
53
54
|
|
54
|
-
`monitors` to set the monitors you'd like to use with Temescal. It takes symbols of monitor names (currently `:airbrake`, `:bugsnag`, and `:
|
55
|
+
`monitors` to set the monitors you'd like to use with Temescal. It takes symbols of monitor names (currently `:airbrake`, `:bugsnag`, `:new_relic`, and `:honeybadger`).
|
55
56
|
|
56
57
|
`raise_errors` to set whether you'd like to override Temescal and raise all errors without rendering a Temescal response. Set to `true` to enable.
|
57
58
|
|
@@ -10,6 +10,9 @@ module Temescal
|
|
10
10
|
# Public: Setter for raise_errors option.
|
11
11
|
attr_writer :raise_errors
|
12
12
|
|
13
|
+
# Public: Setter for meta_key option.
|
14
|
+
attr_writer :meta_key
|
15
|
+
|
13
16
|
# Public: Getter/Setter for default JSON message.
|
14
17
|
attr_accessor :default_message
|
15
18
|
|
@@ -53,6 +56,13 @@ module Temescal
|
|
53
56
|
@ignored_errors = errors.flatten
|
54
57
|
end
|
55
58
|
|
59
|
+
# Public: Getter for meta_key option.
|
60
|
+
#
|
61
|
+
# Returns the meta_key option or simply "meta" if null.
|
62
|
+
def meta_key
|
63
|
+
@meta_key || "meta"
|
64
|
+
end
|
65
|
+
|
56
66
|
private
|
57
67
|
|
58
68
|
# Private: Converts a snake cased Symbol to a camel cased String.
|
data/lib/temescal/error.rb
CHANGED
data/lib/temescal/monitors.rb
CHANGED
@@ -41,5 +41,15 @@ module Temescal
|
|
41
41
|
::Bugsnag.notify exception
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
# Public: Reporting strategy for Honeybadger.
|
46
|
+
class Honeybadger < MonitorsStrategy
|
47
|
+
# Public: Reports an exception to Honeybadger.
|
48
|
+
#
|
49
|
+
# exception - The caught exception.
|
50
|
+
def self.report(exception)
|
51
|
+
::Honeybadger.notify exception
|
52
|
+
end
|
53
|
+
end
|
44
54
|
end
|
45
55
|
end
|
data/lib/temescal/response.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "json"
|
2
2
|
|
3
3
|
module Temescal
|
4
4
|
module Response
|
@@ -11,7 +11,7 @@ module Temescal
|
|
11
11
|
def self.build(error)
|
12
12
|
[
|
13
13
|
{
|
14
|
-
|
14
|
+
$_temescal_configuration.meta_key => {
|
15
15
|
status: error.status,
|
16
16
|
error: error.type,
|
17
17
|
message: error.message
|
data/lib/temescal/version.rb
CHANGED
@@ -7,8 +7,8 @@ class Temescal::Monitors::FooMonitor; end
|
|
7
7
|
describe Temescal::Configuration do
|
8
8
|
let(:config) { Temescal::Configuration.new }
|
9
9
|
|
10
|
-
|
11
|
-
it "
|
10
|
+
describe "#monitors=" do
|
11
|
+
it "adds a list of valid monitor classes to the monitors array from snake-cased arguments" do
|
12
12
|
config.monitors = :monitor, :fake_monitor, :foo_monitor
|
13
13
|
|
14
14
|
expect(config.monitors).to eq [
|
@@ -18,7 +18,7 @@ describe Temescal::Configuration do
|
|
18
18
|
]
|
19
19
|
end
|
20
20
|
|
21
|
-
it "
|
21
|
+
it "raises an error if a monitor strategy is invalid" do
|
22
22
|
expect { config.monitors = :foo }.to raise_error(NameError, /Foo is not a valid monitoring strategy/)
|
23
23
|
end
|
24
24
|
end
|
@@ -10,70 +10,70 @@ describe Temescal::Error do
|
|
10
10
|
$_temescal_configuration = Temescal::Configuration.new
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
it "
|
15
|
-
Temescal::Configuration.
|
13
|
+
describe "#message" do
|
14
|
+
it "returns the configured default message if it is set in the configuration" do
|
15
|
+
allow_any_instance_of(Temescal::Configuration).to receive(:default_message).and_return("Some other message.")
|
16
16
|
|
17
17
|
expect(error.message).to eq "Some other message."
|
18
18
|
end
|
19
19
|
|
20
|
-
it "
|
20
|
+
it "returns the exception's message if the default message is not configured" do
|
21
21
|
expect(error.message).to eq "Foobar"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
it "
|
25
|
+
describe "#status" do
|
26
|
+
it "returns 404 if the exception is an ActiveRecord::RecordNotFound" do
|
27
27
|
exception = ActiveRecord::RecordNotFound.new
|
28
28
|
error = Temescal::Error.new(exception)
|
29
29
|
|
30
30
|
expect(error.status).to eq 404
|
31
31
|
end
|
32
32
|
|
33
|
-
it "
|
33
|
+
it "returns 404 if the exception is a Sinatra::NotFound" do
|
34
34
|
exception = Sinatra::NotFound.new
|
35
35
|
error = Temescal::Error.new(exception)
|
36
36
|
|
37
37
|
expect(error.status).to eq 404
|
38
38
|
end
|
39
39
|
|
40
|
-
it "
|
41
|
-
exception.
|
40
|
+
it "returns the exception's status code if assigned" do
|
41
|
+
allow(exception).to receive(:http_status).and_return(403)
|
42
42
|
|
43
43
|
expect(error.status).to eq 403
|
44
44
|
end
|
45
45
|
|
46
|
-
it "
|
46
|
+
it "returns 500 for all other exceptions" do
|
47
47
|
expect(error.status).to eq 500
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
|
-
it "
|
53
|
-
exception.
|
51
|
+
describe "#formatted" do
|
52
|
+
it "returns a String formatted for log output" do
|
53
|
+
allow(exception).to receive(:backtrace).and_return(["Line 1", "Line 2"])
|
54
54
|
|
55
55
|
expect(error.formatted).to eq "\nStandardError: Foobar\n Line 1\n Line 2\n\n"
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
|
-
it "
|
59
|
+
describe "#type" do
|
60
|
+
it "returns the exception's class name" do
|
61
61
|
expect(error.type).to eq "StandardError"
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
|
65
|
+
describe "#ignore?" do
|
66
66
|
before do
|
67
|
-
Temescal::Configuration.
|
67
|
+
allow_any_instance_of(Temescal::Configuration).to receive(:ignored_errors).and_return([TypeError])
|
68
68
|
end
|
69
69
|
|
70
|
-
it "
|
70
|
+
it "returns true if the exception type is configured as an ignored error" do
|
71
71
|
error = Temescal::Error.new(TypeError.new)
|
72
|
-
expect(error.ignore?).to
|
72
|
+
expect(error.ignore?).to be true
|
73
73
|
end
|
74
74
|
|
75
|
-
it "
|
76
|
-
expect(error.ignore?).to
|
75
|
+
it "returns false if the exception type is not an ignored error" do
|
76
|
+
expect(error.ignore?).to be false
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -12,7 +12,7 @@ describe Temescal::Middleware do
|
|
12
12
|
Temescal::Middleware.new(app)
|
13
13
|
end
|
14
14
|
|
15
|
-
it "
|
15
|
+
it "renders the application's response" do
|
16
16
|
code, _, _ = middleware.call env_for('http://foobar.com')
|
17
17
|
|
18
18
|
expect(code).to eq 200
|
@@ -21,8 +21,8 @@ describe Temescal::Middleware do
|
|
21
21
|
|
22
22
|
context "Bad response" do
|
23
23
|
before do
|
24
|
-
Temescal::Monitors::NewRelic.
|
25
|
-
$stderr.
|
24
|
+
allow(Temescal::Monitors::NewRelic).to receive(:report)
|
25
|
+
allow($stderr).to receive(:print)
|
26
26
|
|
27
27
|
# Travis automatically sets RACK_ENV=test
|
28
28
|
# Need to override for tests to run correctly.
|
@@ -38,27 +38,27 @@ describe Temescal::Middleware do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
it "
|
41
|
+
it "responds with a 500 if the exception does not have a http_status attribute" do
|
42
42
|
code, _, _ = middleware.call env_for("http://foobar.com")
|
43
43
|
|
44
44
|
expect(code).to eq 500
|
45
45
|
end
|
46
46
|
|
47
|
-
it "
|
48
|
-
StandardError.
|
47
|
+
it "responds with the appropriate status if the exception has a http_status attribute" do
|
48
|
+
allow_any_instance_of(StandardError).to receive(:http_status).and_return(403)
|
49
49
|
|
50
50
|
code, _, _ = middleware.call env_for("http://foobar.com")
|
51
51
|
|
52
52
|
expect(code).to eq 403
|
53
53
|
end
|
54
54
|
|
55
|
-
it "
|
55
|
+
it "sets the correct content type header" do
|
56
56
|
_, headers, _ = middleware.call env_for("http://foobar.com")
|
57
57
|
|
58
58
|
expect(headers["Content-Type"]).to eq "application/json"
|
59
59
|
end
|
60
60
|
|
61
|
-
it "
|
61
|
+
it "renders a JSON response for the error" do
|
62
62
|
_, _, response = middleware.call env_for("http://foobar.com")
|
63
63
|
|
64
64
|
json = JSON.parse(response.first)["meta"]
|
@@ -67,20 +67,20 @@ describe Temescal::Middleware do
|
|
67
67
|
expect(json["message"]).to eq "Foobar"
|
68
68
|
end
|
69
69
|
|
70
|
-
it "
|
70
|
+
it "logs the error" do
|
71
71
|
expect($stderr).to receive(:print).with(an_instance_of String)
|
72
72
|
|
73
73
|
middleware.call env_for("http://foobar.com")
|
74
74
|
end
|
75
75
|
|
76
|
-
it "
|
76
|
+
it "reports the error to the specified monitors" do
|
77
77
|
expect(Temescal::Monitors::NewRelic).to receive(:report).with(an_instance_of StandardError)
|
78
78
|
|
79
79
|
middleware.call env_for("http://foobar.com")
|
80
80
|
end
|
81
81
|
|
82
82
|
context "with default_message set" do
|
83
|
-
it "
|
83
|
+
it "builds a response with the specified message instead of the exception message" do
|
84
84
|
middleware = Temescal::Middleware.new(app) do |config|
|
85
85
|
config.default_message = "An error has occured - we'll get on it right away!"
|
86
86
|
end
|
@@ -93,7 +93,7 @@ describe Temescal::Middleware do
|
|
93
93
|
end
|
94
94
|
|
95
95
|
context "with a Sinatra::NotFound error" do
|
96
|
-
it "
|
96
|
+
it "builds a response with a 404 status code" do
|
97
97
|
app = ->(env) { raise Sinatra::NotFound.new }
|
98
98
|
middleware = Temescal::Middleware.new(app)
|
99
99
|
|
@@ -104,7 +104,7 @@ describe Temescal::Middleware do
|
|
104
104
|
end
|
105
105
|
|
106
106
|
context "with an ActiveRecord::RecordNotFound error" do
|
107
|
-
it "
|
107
|
+
it "builds a response with a 404 status code" do
|
108
108
|
app = ->(env) { raise ActiveRecord::RecordNotFound.new }
|
109
109
|
middleware = Temescal::Middleware.new(app)
|
110
110
|
|
@@ -122,23 +122,39 @@ describe Temescal::Middleware do
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
-
it "
|
125
|
+
it "does not log an ignored error type" do
|
126
126
|
expect($stderr).to_not receive(:print).with(an_instance_of String)
|
127
127
|
|
128
128
|
middleware.call env_for("http://foobar.com")
|
129
129
|
end
|
130
130
|
|
131
|
-
it "
|
131
|
+
it "does not report an ignored error type" do
|
132
132
|
expect(Temescal::Monitors::NewRelic).to_not receive(:report).with(an_instance_of StandardError)
|
133
133
|
|
134
134
|
middleware.call env_for("http://foobar.com")
|
135
135
|
end
|
136
136
|
end
|
137
|
+
|
138
|
+
context "with custom meta key set" do
|
139
|
+
let(:middleware) do
|
140
|
+
Temescal::Middleware.new(app) do |config|
|
141
|
+
config.meta_key = "not_meta"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
it "builds a response with the custom key" do
|
146
|
+
_, _, response = middleware.call env_for("http://foobar.com")
|
147
|
+
|
148
|
+
response = JSON.parse(response.first)
|
149
|
+
|
150
|
+
expect(response["not_meta"]).to_not be_nil
|
151
|
+
end
|
152
|
+
end
|
137
153
|
end
|
138
154
|
|
139
155
|
context "Override middleware to raise exception" do
|
140
156
|
before do
|
141
|
-
$stderr.
|
157
|
+
allow($stderr).to receive(:print)
|
142
158
|
end
|
143
159
|
|
144
160
|
let(:app) { ->(env) { raise StandardError.new("Foobar") } }
|
@@ -149,7 +165,7 @@ describe Temescal::Middleware do
|
|
149
165
|
end
|
150
166
|
end
|
151
167
|
|
152
|
-
it "
|
168
|
+
it "raises the error" do
|
153
169
|
expect { middleware.call env_for("http://foobar.com") }.to raise_error StandardError
|
154
170
|
end
|
155
171
|
end
|
@@ -4,34 +4,52 @@ describe Temescal::Monitors do
|
|
4
4
|
let(:exception) { StandardError.new }
|
5
5
|
|
6
6
|
context "MonitorsStrategy" do
|
7
|
-
|
8
|
-
|
7
|
+
describe '.report' do
|
8
|
+
it "raises an error" do
|
9
|
+
expect { Temescal::Monitors::MonitorsStrategy.report(exception) }.to raise_error(NotImplementedError)
|
10
|
+
end
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
14
|
context "Airbrake" do
|
13
|
-
|
14
|
-
Airbrake
|
15
|
+
describe '.report' do
|
16
|
+
it "sends the exception to Airbrake" do
|
17
|
+
allow(Airbrake).to receive(:send_notice)
|
15
18
|
|
16
|
-
|
19
|
+
expect(Airbrake).to receive(:notify).with(exception)
|
17
20
|
|
18
|
-
|
21
|
+
Temescal::Monitors::Airbrake.report exception
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
|
22
26
|
context "NewRelic" do
|
23
|
-
|
24
|
-
|
27
|
+
describe '.report' do
|
28
|
+
it "sends the exception to New Relic" do
|
29
|
+
expect(NewRelic::Agent).to receive(:notice_error).with(exception)
|
25
30
|
|
26
|
-
|
31
|
+
Temescal::Monitors::NewRelic.report exception
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
29
35
|
|
30
36
|
context 'Bugsnag' do
|
31
|
-
|
32
|
-
|
37
|
+
describe '.report' do
|
38
|
+
it "sends the exception to Bugsnag" do
|
39
|
+
expect(Bugsnag).to receive(:notify).with(exception)
|
33
40
|
|
34
|
-
|
41
|
+
Temescal::Monitors::Bugsnag.report exception
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'Honeybadger' do
|
47
|
+
describe '.report' do
|
48
|
+
it "sends the exception to Honeybadger" do
|
49
|
+
expect(Honeybadger).to receive(:notify).with(exception)
|
50
|
+
|
51
|
+
Temescal::Monitors::Honeybadger.report exception
|
52
|
+
end
|
35
53
|
end
|
36
54
|
end
|
37
55
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,7 +3,7 @@ if ENV["CI"]
|
|
3
3
|
Coveralls.wear!
|
4
4
|
else
|
5
5
|
require "awesome_print"
|
6
|
-
require "pry-
|
6
|
+
require "pry-byebug"
|
7
7
|
|
8
8
|
require "simplecov"
|
9
9
|
SimpleCov.start
|
@@ -14,6 +14,7 @@ require "rack"
|
|
14
14
|
require "airbrake"
|
15
15
|
require "newrelic_rpm"
|
16
16
|
require "bugsnag"
|
17
|
+
require "honeybadger"
|
17
18
|
|
18
19
|
require "active_record"
|
19
20
|
require "sinatra"
|
@@ -21,7 +22,6 @@ require "sinatra"
|
|
21
22
|
require "temescal"
|
22
23
|
|
23
24
|
RSpec.configure do |config|
|
24
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
25
25
|
config.run_all_when_everything_filtered = true
|
26
26
|
config.filter_run :focus
|
27
27
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: temescal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todd Bealmear
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -81,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
81
|
version: '0'
|
82
82
|
requirements: []
|
83
83
|
rubyforge_project:
|
84
|
-
rubygems_version: 2.2.
|
84
|
+
rubygems_version: 2.2.2
|
85
85
|
signing_key:
|
86
86
|
specification_version: 4
|
87
87
|
summary: Rack Middleware for gracefully handling exceptions for JSON APIs.
|