safely_block 0.1.0 → 0.1.1
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/CHANGELOG.md +5 -0
- data/README.md +25 -19
- data/lib/safely/core.rb +57 -0
- data/lib/safely/version.rb +3 -0
- data/lib/safely_block.rb +1 -43
- data/safely_block.gemspec +4 -4
- data/test/safely_test.rb +22 -0
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ba20f765b3e7d5a3a42de0c5376d06f2fa1a123
|
4
|
+
data.tar.gz: 100cf5b7ab1a8fba676b64e7914908d7d23f8276
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c781fdff6e44069440281ba046b853e97a187c0ef59110231c4571113abd6451f15ecbb94484b7c53afcd0c2d07e24f8ddd28a3cd1ed843611dfcb2d97b73ee2
|
7
|
+
data.tar.gz: 1d261002fdf45d8fe088a75203ce55e61467aefb41547abbbad2ae617384f3f9bb3579b3ea961e24369daa21666dcd91803fde2eb8c9accd9a41521f1625d765
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,30 +1,28 @@
|
|
1
1
|
# Safely
|
2
2
|
|
3
|
-
Unexpected data can cause errors in production - don’t let it bring down the system
|
4
|
-
|
5
3
|
```ruby
|
6
4
|
safely do
|
7
5
|
# keep going if this code fails
|
8
6
|
end
|
9
7
|
```
|
10
8
|
|
11
|
-
Exceptions are rescued and reported to your favorite reporting service.
|
9
|
+
Exceptions are rescued and automatically reported to your favorite reporting service.
|
12
10
|
|
13
|
-
In development and test environments, exceptions are raised so you can fix them.
|
11
|
+
In development and test environments, exceptions are raised so you can fix them.
|
14
12
|
|
15
|
-
##
|
13
|
+
## Use It Everywhere
|
16
14
|
|
17
|
-
|
15
|
+
“Oh no, analytics brought down search”
|
18
16
|
|
19
17
|
```ruby
|
20
|
-
safely {
|
18
|
+
safely { track_search(params) }
|
21
19
|
```
|
22
20
|
|
23
|
-
|
21
|
+
“Recommendations stopped updating because of one bad user”
|
24
22
|
|
25
23
|
```ruby
|
26
|
-
|
27
|
-
safely {
|
24
|
+
users.each do |user|
|
25
|
+
safely { update_recommendations(user) }
|
28
26
|
end
|
29
27
|
```
|
30
28
|
|
@@ -32,18 +30,10 @@ Also aliased as `yolo`.
|
|
32
30
|
|
33
31
|
## Features
|
34
32
|
|
35
|
-
Throttle reporting with:
|
36
|
-
|
37
|
-
```ruby
|
38
|
-
safely sample: 1000 do
|
39
|
-
# reports ~ 1/1000 errors
|
40
|
-
end
|
41
|
-
```
|
42
|
-
|
43
33
|
Specify a default value to return on exceptions
|
44
34
|
|
45
35
|
```ruby
|
46
|
-
|
36
|
+
show_banner = safely(default: true) { show_banner_logic }
|
47
37
|
```
|
48
38
|
|
49
39
|
Raise specific exceptions
|
@@ -70,6 +60,16 @@ Silence exceptions
|
|
70
60
|
safely(silence: ActiveRecord::RecordNotUnique) { code }
|
71
61
|
```
|
72
62
|
|
63
|
+
Throttle reporting with:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
safely throttle: {limit: 10, period: 1.minute} do
|
67
|
+
# reports only first 10 exceptions each minute
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
**Note:** The throttle limit is approximate and per process.
|
72
|
+
|
73
73
|
## Reporting
|
74
74
|
|
75
75
|
Reports exceptions to a variety of services out of the box thanks to [Errbase](https://github.com/ankane/errbase).
|
@@ -96,6 +96,12 @@ By default, exception messages are prefixed with `[safely]`. This makes it easie
|
|
96
96
|
Safely.tag = false
|
97
97
|
```
|
98
98
|
|
99
|
+
To report exceptions manually:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
Safely.report_exception(e)
|
103
|
+
```
|
104
|
+
|
99
105
|
## Installation
|
100
106
|
|
101
107
|
Add this line to your application’s Gemfile:
|
data/lib/safely/core.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "safely/version"
|
2
|
+
require "errbase"
|
3
|
+
require "digest"
|
4
|
+
|
5
|
+
module Safely
|
6
|
+
class << self
|
7
|
+
attr_accessor :raise_envs, :tag, :report_exception_method, :throttle_counter
|
8
|
+
attr_writer :env
|
9
|
+
|
10
|
+
def report_exception(e)
|
11
|
+
report_exception_method.call(e)
|
12
|
+
end
|
13
|
+
|
14
|
+
def env
|
15
|
+
@env ||= ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
16
|
+
end
|
17
|
+
|
18
|
+
def throttled?(e, options)
|
19
|
+
return false unless options
|
20
|
+
key = "#{options[:key] || Digest::MD5.hexdigest([e.class.name, e.message, e.backtrace.join("\n")].join("/"))}/#{(Time.now.to_i / options[:period]) * options[:period]}"
|
21
|
+
throttle_counter.clear if throttle_counter.size > 1000 # prevent from growing indefinitely
|
22
|
+
(throttle_counter[key] += 1) > options[:limit]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
DEFAULT_EXCEPTION_METHOD = proc do |e|
|
27
|
+
e = e.dup # leave original exception unmodified
|
28
|
+
e.message.prepend("[safely] ") if e.message && Safely.tag
|
29
|
+
Errbase.report(e)
|
30
|
+
end
|
31
|
+
|
32
|
+
self.tag = true
|
33
|
+
self.report_exception_method = DEFAULT_EXCEPTION_METHOD
|
34
|
+
self.raise_envs = %w(development test)
|
35
|
+
# not thread-safe, but we don't need to be exact
|
36
|
+
self.throttle_counter = Hash.new(0)
|
37
|
+
|
38
|
+
module Methods
|
39
|
+
def safely(options = {})
|
40
|
+
yield
|
41
|
+
rescue *Array(options[:only] || StandardError) => e
|
42
|
+
raise e if Array(options[:except]).any? { |c| e.is_a?(c) }
|
43
|
+
raise e if Safely.raise_envs.include?(Safely.env)
|
44
|
+
sample = options[:sample]
|
45
|
+
if sample ? rand < 1.0 / sample : true
|
46
|
+
begin
|
47
|
+
Safely.report_exception(e) unless Array(options[:silence]).any? { |c| e.is_a?(c) } || Safely.throttled?(e, options[:throttle])
|
48
|
+
rescue => e2
|
49
|
+
$stderr.puts "FAIL-SAFE #{e2.class.name}: #{e2.message}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
options[:default]
|
53
|
+
end
|
54
|
+
alias_method :yolo, :safely
|
55
|
+
end
|
56
|
+
extend Methods
|
57
|
+
end
|
data/lib/safely_block.rb
CHANGED
@@ -1,45 +1,3 @@
|
|
1
|
-
require "
|
2
|
-
|
3
|
-
module Safely
|
4
|
-
VERSION = "0.1.0"
|
5
|
-
|
6
|
-
class << self
|
7
|
-
attr_accessor :env, :raise_envs, :tag, :report_exception_method
|
8
|
-
|
9
|
-
def report_exception(e)
|
10
|
-
report_exception_method.call(e)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
DEFAULT_EXCEPTION_METHOD = proc do |e|
|
15
|
-
e = e.dup # leave original exception unmodified
|
16
|
-
e.message.prepend("[safely] ") if e.message && Safely.tag
|
17
|
-
Errbase.report(e)
|
18
|
-
end
|
19
|
-
|
20
|
-
self.env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
|
21
|
-
self.tag = true
|
22
|
-
self.report_exception_method = DEFAULT_EXCEPTION_METHOD
|
23
|
-
self.raise_envs = %w(development test)
|
24
|
-
|
25
|
-
module Methods
|
26
|
-
def safely(options = {})
|
27
|
-
yield
|
28
|
-
rescue *Array(options[:only] || StandardError) => e
|
29
|
-
raise e if Array(options[:except]).any? { |c| e.is_a?(c) }
|
30
|
-
raise e if Safely.raise_envs.include?(Safely.env)
|
31
|
-
sample = options[:sample]
|
32
|
-
if sample ? rand < 1.0 / sample : true
|
33
|
-
begin
|
34
|
-
Safely.report_exception(e) unless Array(options[:silence]).any? { |c| e.is_a?(c) }
|
35
|
-
rescue => e2
|
36
|
-
$stderr.puts "FAIL-SAFE #{e2.class.name}: #{e2.message}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
options[:default]
|
40
|
-
end
|
41
|
-
alias_method :yolo, :safely
|
42
|
-
end
|
43
|
-
end
|
1
|
+
require "safely/core"
|
44
2
|
|
45
3
|
Object.send :include, Safely::Methods
|
data/safely_block.gemspec
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "
|
4
|
+
require "safely/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "safely_block"
|
8
8
|
spec.version = Safely::VERSION
|
9
9
|
spec.authors = ["Andrew Kane"]
|
10
10
|
spec.email = ["andrew@chartkick.com"]
|
11
|
-
spec.summary = "
|
12
|
-
spec.description = "
|
13
|
-
spec.homepage = "https://github.com/ankane/
|
11
|
+
spec.summary = "Awesome exception handling"
|
12
|
+
spec.description = "Awesome exception handling"
|
13
|
+
spec.homepage = "https://github.com/ankane/safely"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
data/test/safely_test.rb
CHANGED
@@ -82,4 +82,26 @@ class TestSafely < Minitest::Test
|
|
82
82
|
end
|
83
83
|
assert_equal "FAIL-SAFE RuntimeError: oops\n", err
|
84
84
|
end
|
85
|
+
|
86
|
+
def test_throttle
|
87
|
+
count = 0
|
88
|
+
Safely.report_exception_method = proc { |e| count += 1 }
|
89
|
+
5.times do |n|
|
90
|
+
safely throttle: {limit: 2, period: 3600} do
|
91
|
+
raise Safely::TestError
|
92
|
+
end
|
93
|
+
end
|
94
|
+
assert_equal 2, count
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_throttle_key
|
98
|
+
count = 0
|
99
|
+
Safely.report_exception_method = proc { |e| count += 1 }
|
100
|
+
5.times do |n|
|
101
|
+
safely throttle: {limit: 2, period: 3600, key: "boom#{n % 2}"} do
|
102
|
+
raise Safely::TestError
|
103
|
+
end
|
104
|
+
end
|
105
|
+
assert_equal 4, count
|
106
|
+
end
|
85
107
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safely_block
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: errbase
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '5'
|
69
|
-
description:
|
69
|
+
description: Awesome exception handling
|
70
70
|
email:
|
71
71
|
- andrew@chartkick.com
|
72
72
|
executables: []
|
@@ -79,11 +79,13 @@ files:
|
|
79
79
|
- LICENSE.txt
|
80
80
|
- README.md
|
81
81
|
- Rakefile
|
82
|
+
- lib/safely/core.rb
|
83
|
+
- lib/safely/version.rb
|
82
84
|
- lib/safely_block.rb
|
83
85
|
- safely_block.gemspec
|
84
86
|
- test/safely_test.rb
|
85
87
|
- test/test_helper.rb
|
86
|
-
homepage: https://github.com/ankane/
|
88
|
+
homepage: https://github.com/ankane/safely
|
87
89
|
licenses:
|
88
90
|
- MIT
|
89
91
|
metadata: {}
|
@@ -103,10 +105,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
105
|
version: '0'
|
104
106
|
requirements: []
|
105
107
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.
|
108
|
+
rubygems_version: 2.6.1
|
107
109
|
signing_key:
|
108
110
|
specification_version: 4
|
109
|
-
summary:
|
111
|
+
summary: Awesome exception handling
|
110
112
|
test_files:
|
111
113
|
- test/safely_test.rb
|
112
114
|
- test/test_helper.rb
|