robustly 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +66 -16
- data/lib/robustly.rb +21 -15
- data/lib/robustly/version.rb +1 -1
- data/test/robustly_test.rb +14 -16
- metadata +3 -3
- data/.rubocop.yml +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9dbd670fd6832a14e2315b0195a6bb13381eaed8
|
4
|
+
data.tar.gz: 31b9a08a7b218feedafe11b15b4a000204e0c7b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 867d1290360d87b7835e8ed65159e29077ed26a896cc937284288a598e9871c048f031d1bad0bf02b399a16edbd77672bdeb0a4b56b37ff213d5ee7ee6d5a2e1
|
7
|
+
data.tar.gz: 161bc8ac868488b646f88268710d4476569b39992040c345f47e2cc17ac1122a2174e251a58fb4ac063303927a5c6a75ebcda5c4820944c36bc893c99d1eab3c
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Robustly
|
2
2
|
|
3
|
-
|
3
|
+
Unexpected data can cause errors in production - don’t let it bring down the system
|
4
4
|
|
5
5
|
```ruby
|
6
6
|
safely do
|
@@ -8,41 +8,55 @@ safely do
|
|
8
8
|
end
|
9
9
|
```
|
10
10
|
|
11
|
-
|
11
|
+
Exceptions are rescued and reported to your favorite reporting service.
|
12
12
|
|
13
|
-
|
13
|
+
In development and test environments, exceptions are raised so you can fix them. :smirk:
|
14
|
+
|
15
|
+
## Examples
|
16
|
+
|
17
|
+
Great for analytics
|
14
18
|
|
15
19
|
```ruby
|
16
|
-
|
17
|
-
# get crazy in here
|
18
|
-
end
|
20
|
+
safely { track_event("Search") }
|
19
21
|
```
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
Customize reporting with:
|
23
|
+
and background jobs
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
|
26
|
+
User.find_each do |user|
|
27
|
+
safely { cache_recommendations(user) }
|
28
|
+
end
|
27
29
|
```
|
28
30
|
|
29
|
-
|
31
|
+
Also aliased as `yolo`.
|
32
|
+
|
33
|
+
## Features
|
34
|
+
|
35
|
+
Throttle reporting with:
|
30
36
|
|
31
37
|
```ruby
|
32
|
-
safely
|
38
|
+
safely sample: 1000 do
|
33
39
|
# reports ~ 1/1000 errors
|
34
40
|
end
|
35
41
|
```
|
36
42
|
|
37
|
-
Specify a default value to return on
|
43
|
+
Specify a default value to return on exceptions
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
score = safely(default: 30) { calculate_score }
|
47
|
+
```
|
48
|
+
|
49
|
+
Raise specific exceptions
|
38
50
|
|
39
51
|
```ruby
|
40
|
-
safely
|
41
|
-
#
|
52
|
+
safely except: ActiveRecord::RecordNotUnique do
|
53
|
+
# all other exceptions will be rescued
|
42
54
|
end
|
43
55
|
```
|
44
56
|
|
45
|
-
|
57
|
+
Pass an array for multiple exception classes.
|
58
|
+
|
59
|
+
Rescue only specific exceptions
|
46
60
|
|
47
61
|
```ruby
|
48
62
|
safely only: ActiveRecord::RecordNotUnique do
|
@@ -50,6 +64,38 @@ safely only: ActiveRecord::RecordNotUnique do
|
|
50
64
|
end
|
51
65
|
```
|
52
66
|
|
67
|
+
Silence exceptions
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
safely(silence: ActiveRecord::RecordNotUnique) { code }
|
71
|
+
```
|
72
|
+
|
73
|
+
## Reporting
|
74
|
+
|
75
|
+
Reports exceptions to a variety of services out of the box thanks to [Errbase](https://github.com/ankane/errbase).
|
76
|
+
|
77
|
+
- [Rollbar](https://rollbar.com/)
|
78
|
+
- [Airbrake](https://airbrake.io/)
|
79
|
+
- [Exceptional](http://www.exceptional.io/)
|
80
|
+
- [Honeybadger](https://www.honeybadger.io/)
|
81
|
+
- [Sentry](https://getsentry.com/)
|
82
|
+
- [Raygun](https://raygun.io/)
|
83
|
+
- [Bugsnag](https://bugsnag.com/)
|
84
|
+
- [Appsignal](https://appsignal.com/)
|
85
|
+
- [Opbeat](https://opbeat.com/)
|
86
|
+
|
87
|
+
Customize reporting with:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
Robustly.report_exception_method = proc { |e| Rollbar.error(e) }
|
91
|
+
```
|
92
|
+
|
93
|
+
By default, exception messages are prefixed with `[safely]`. This makes it easier to spot rescued exceptions. Turn this off with:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
Robustly.tag = false
|
97
|
+
```
|
98
|
+
|
53
99
|
## Installation
|
54
100
|
|
55
101
|
Add this line to your application’s Gemfile:
|
@@ -58,6 +104,10 @@ Add this line to your application’s Gemfile:
|
|
58
104
|
gem 'robustly'
|
59
105
|
```
|
60
106
|
|
107
|
+
## History
|
108
|
+
|
109
|
+
View the [changelog](https://github.com/ankane/robustly/blob/master/CHANGELOG.md)
|
110
|
+
|
61
111
|
## Contributing
|
62
112
|
|
63
113
|
Everyone is encouraged to help improve this project. Here are a few ways you can help:
|
data/lib/robustly.rb
CHANGED
@@ -3,33 +3,39 @@ require "errbase"
|
|
3
3
|
|
4
4
|
module Robustly
|
5
5
|
class << self
|
6
|
-
attr_accessor :env, :report_exception_method
|
6
|
+
attr_accessor :env, :raise_envs, :tag, :report_exception_method
|
7
7
|
|
8
8
|
def report_exception(e)
|
9
9
|
report_exception_method.call(e)
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
13
|
-
|
12
|
+
|
13
|
+
DEFAULT_EXCEPTION_METHOD = proc do |e|
|
14
|
+
e = e.dup # leave original exception unmodified
|
15
|
+
e.message.prepend("[safely] ") if e.message && Robustly.tag
|
14
16
|
Errbase.report(e)
|
15
17
|
end
|
16
18
|
|
19
|
+
self.env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
|
20
|
+
self.tag = true
|
21
|
+
self.report_exception_method = DEFAULT_EXCEPTION_METHOD
|
22
|
+
self.raise_envs = %w(development test)
|
23
|
+
|
17
24
|
module Methods
|
18
25
|
def safely(options = {})
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
26
|
+
yield
|
27
|
+
rescue *Array(options[:only] || StandardError) => e
|
28
|
+
raise e if Array(options[:except]).any? { |c| e.is_a?(c) }
|
29
|
+
raise e if Robustly.raise_envs.include?(Robustly.env)
|
30
|
+
sample = options[:sample] || options[:throttle]
|
31
|
+
if sample ? rand < 1.0 / sample : true
|
32
|
+
begin
|
33
|
+
Robustly.report_exception(e) unless Array(options[:silence]).any? { |c| e.is_a?(c) }
|
34
|
+
rescue => e2
|
35
|
+
$stderr.puts "FAIL-SAFE #{e2.class.name}: #{e2.message}"
|
30
36
|
end
|
31
|
-
options[:default]
|
32
37
|
end
|
38
|
+
options[:default]
|
33
39
|
end
|
34
40
|
alias_method :yolo, :safely
|
35
41
|
alias_method :robustly, :safely # legacy
|
data/lib/robustly/version.rb
CHANGED
data/test/robustly_test.rb
CHANGED
@@ -3,7 +3,7 @@ require_relative "test_helper"
|
|
3
3
|
class TestRobustly < Minitest::Test
|
4
4
|
def setup
|
5
5
|
Robustly.env = "production"
|
6
|
-
Robustly.report_exception_method =
|
6
|
+
Robustly.report_exception_method = Robustly::DEFAULT_EXCEPTION_METHOD
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_safely_development_environment
|
@@ -46,35 +46,33 @@ class TestRobustly < Minitest::Test
|
|
46
46
|
assert mock.verify
|
47
47
|
end
|
48
48
|
|
49
|
-
def test_robustly
|
50
|
-
exception = Robustly::TestError.new
|
51
|
-
mock = MiniTest::Mock.new
|
52
|
-
mock.expect :report_exception, nil, [exception]
|
53
|
-
Robustly.report_exception_method = proc { |e| mock.report_exception(e) }
|
54
|
-
robustly do
|
55
|
-
raise exception
|
56
|
-
end
|
57
|
-
assert mock.verify
|
58
|
-
end
|
59
|
-
|
60
49
|
def test_return_value
|
61
50
|
assert_equal 1, safely { 1 }
|
62
|
-
assert_equal nil, safely { raise Robustly::TestError }
|
51
|
+
assert_equal nil, safely { raise Robustly::TestError, "Boom" }
|
63
52
|
end
|
64
53
|
|
65
54
|
def test_default
|
66
55
|
assert_equal 1, safely(default: 2) { 1 }
|
67
|
-
assert_equal 2, safely(default: 2) { raise Robustly::TestError }
|
56
|
+
assert_equal 2, safely(default: 2) { raise Robustly::TestError, "Boom" }
|
68
57
|
end
|
69
58
|
|
70
59
|
def test_only
|
71
60
|
assert_equal nil, safely(only: Robustly::TestError) { raise Robustly::TestError }
|
72
|
-
assert_raises(RuntimeError, "Boom") { safely(only: Robustly::TestError) { raise RuntimeError
|
61
|
+
assert_raises(RuntimeError, "Boom") { safely(only: Robustly::TestError) { raise RuntimeError, "Boom" } }
|
73
62
|
end
|
74
63
|
|
75
64
|
def test_only_array
|
76
65
|
assert_equal nil, safely(only: [Robustly::TestError]) { raise Robustly::TestError }
|
77
|
-
assert_raises(RuntimeError, "Boom") { safely(only: [Robustly::TestError]) { raise RuntimeError
|
66
|
+
assert_raises(RuntimeError, "Boom") { safely(only: [Robustly::TestError]) { raise RuntimeError, "Boom" } }
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_except
|
70
|
+
assert_raises(Robustly::TestError, "Boom") { safely(except: StandardError) { raise Robustly::TestError, "Boom" } }
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_silence
|
74
|
+
safely(silence: StandardError) { raise Robustly::TestError, "Boom" }
|
75
|
+
assert true
|
78
76
|
end
|
79
77
|
|
80
78
|
def test_failsafe
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robustly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: errbase
|
@@ -74,7 +74,7 @@ extensions: []
|
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
76
|
- ".gitignore"
|
77
|
-
-
|
77
|
+
- CHANGELOG.md
|
78
78
|
- Gemfile
|
79
79
|
- LICENSE.txt
|
80
80
|
- README.md
|
data/.rubocop.yml
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
Style/StringLiterals:
|
2
|
-
EnforcedStyle: double_quotes
|
3
|
-
|
4
|
-
Style/SpaceInsideHashLiteralBraces:
|
5
|
-
EnforcedStyle: no_space
|
6
|
-
|
7
|
-
Style/Documentation:
|
8
|
-
Enabled: false
|
9
|
-
|
10
|
-
Style/SignalException:
|
11
|
-
Enabled: false
|
12
|
-
|
13
|
-
Metrics/AbcSize:
|
14
|
-
Enabled: false
|
15
|
-
|
16
|
-
Metrics/BlockNesting:
|
17
|
-
Enabled: false
|
18
|
-
|
19
|
-
Metrics/ClassLength:
|
20
|
-
Enabled: false
|
21
|
-
|
22
|
-
Metrics/CyclomaticComplexity:
|
23
|
-
Enabled: false
|
24
|
-
|
25
|
-
Metrics/LineLength:
|
26
|
-
Enabled: false
|
27
|
-
|
28
|
-
Metrics/MethodLength:
|
29
|
-
Enabled: false
|
30
|
-
|
31
|
-
Metrics/PerceivedComplexity:
|
32
|
-
Enabled: false
|