hoodoo 2.1.2 → 2.2.0
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27f8a7c4aed490d7d8e01fb68469c393b094e1d83ab1100a700e330c2288e88d
|
4
|
+
data.tar.gz: ebf5032d0056a507db7bbaf63b51269469350e5e2189b5016d06a1012c88dd7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39ffe6dc1b31ff93b3cf5fb6424a253d107d7a9c4c1aeae789d8c04d6e6ebbec06dde7b42f9b411875b55d0722bc6571e9eb3432a148a8ac8b610dc1b96310b2
|
7
|
+
data.tar.gz: 44a537dcdcf8e7b905a4ac933a2497bd2c14598e2017b63b207baed5fcab4fdd511f17117b5a7a99e27f540f6745c5ade28eac50b4acd50d6354ab8a1c5bf5ee
|
@@ -57,6 +57,8 @@ module Hoodoo; module Services
|
|
57
57
|
def report( e, env )
|
58
58
|
opts = { :backtrace => Kernel.caller() }
|
59
59
|
opts[ :rack_env ] = env unless env.nil?
|
60
|
+
e = sanitize_object(e)
|
61
|
+
opts = sanitize_object(opts)
|
60
62
|
|
61
63
|
# Since an ExceptionReporter is already a "slow communicatory",
|
62
64
|
# Hoodoo is using threads for behaviour; we don't need the async
|
@@ -81,9 +83,37 @@ module Hoodoo; module Services
|
|
81
83
|
:environment_name => Hoodoo::Services::Middleware.environment,
|
82
84
|
:session => user_data_for( context ) || 'unknown'
|
83
85
|
}
|
86
|
+
e = sanitize_object(e)
|
87
|
+
opts = sanitize_object(opts)
|
84
88
|
|
85
89
|
Airbrake.notify_sync( e, opts )
|
86
90
|
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# Recursive sanitisation method for deeply nested hash objects, returning
|
95
|
+
# the same object in a non frozen state.
|
96
|
+
#
|
97
|
+
# Why do I exist?
|
98
|
+
#
|
99
|
+
# Due to an airbrake-ruby issue where client arguments can be mutated when within a hash,
|
100
|
+
# a recursive sanitisation process must therefore take place before our inputs are sent
|
101
|
+
# to Airbrake, ensuring no frozen hash objects are present.
|
102
|
+
#
|
103
|
+
# https://github.com/airbrake/airbrake-ruby/issues/281
|
104
|
+
#
|
105
|
+
def sanitize_object( object )
|
106
|
+
object = ( object.dup rescue object ) if object.frozen?
|
107
|
+
return object unless object.is_a?( Hash )
|
108
|
+
|
109
|
+
sanitize_hash( object )
|
110
|
+
end
|
111
|
+
|
112
|
+
def sanitize_hash( object )
|
113
|
+
object.each do | key, value |
|
114
|
+
object[key] = sanitize_object( value )
|
115
|
+
end
|
116
|
+
end
|
87
117
|
end
|
88
118
|
|
89
119
|
end
|
data/lib/hoodoo/version.rb
CHANGED
@@ -12,11 +12,11 @@ module Hoodoo
|
|
12
12
|
# The Hoodoo gem version. If this changes, be sure to re-run
|
13
13
|
# <tt>bundle install</tt> or <tt>bundle update</tt>.
|
14
14
|
#
|
15
|
-
VERSION = '2.
|
15
|
+
VERSION = '2.2.0'
|
16
16
|
|
17
17
|
# The Hoodoo gem date. If this changes, be sure to re-run
|
18
18
|
# <tt>bundle install</tt> or <tt>bundle update</tt>.
|
19
19
|
#
|
20
|
-
DATE = '2017-11-
|
20
|
+
DATE = '2017-11-09'
|
21
21
|
|
22
22
|
end
|
@@ -16,33 +16,104 @@ describe Hoodoo::Services::Middleware::ExceptionReporting::AirbrakeReporter do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
context '#report' do
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
expect(
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
context 'with Airbrake mocks' do
|
20
|
+
it 'calls Airbrake correctly without an "env"' do
|
21
|
+
ex = RuntimeError.new( 'A' )
|
22
|
+
|
23
|
+
expect( Airbrake ).to receive( :notify_sync ).once do | e, opts |
|
24
|
+
expect( e ).to be_a( Exception )
|
25
|
+
expect( opts ).to be_a( Hash )
|
26
|
+
expect( opts ).to have_key( :backtrace )
|
27
|
+
expect( opts ).to_not have_key( :rack_env )
|
28
|
+
end
|
29
|
+
|
30
|
+
Hoodoo::Services::Middleware::ExceptionReporting.report( ex )
|
27
31
|
end
|
28
32
|
|
29
|
-
|
33
|
+
it 'calls Airbrake correctly with an "env"' do
|
34
|
+
ex = RuntimeError.new( 'A' )
|
35
|
+
mock_env = { 'rack' => 'request' }
|
36
|
+
|
37
|
+
expect( Airbrake ).to receive( :notify_sync ).once do | e, opts |
|
38
|
+
expect( e ).to be_a( Exception )
|
39
|
+
|
40
|
+
expect( opts ).to be_a( Hash )
|
41
|
+
expect( opts ).to have_key( :backtrace )
|
42
|
+
|
43
|
+
expect( opts[ :rack_env ] ).to eq( mock_env )
|
44
|
+
end
|
45
|
+
|
46
|
+
Hoodoo::Services::Middleware::ExceptionReporting.report( ex, mock_env )
|
47
|
+
end
|
30
48
|
end
|
31
49
|
|
32
|
-
|
33
|
-
|
34
|
-
|
50
|
+
context 'without Airbrake mocks' do
|
51
|
+
|
52
|
+
# Airbrake does not allow the default notifier to be reconfigured, so we
|
53
|
+
# must set some dummy values here just once within this Airbrake-specific
|
54
|
+
# integration test. Without this, non-mocked tests do not run much of the
|
55
|
+
# Airbrake code that, over time, we have discovered should be tested.
|
56
|
+
#
|
57
|
+
before :all do
|
58
|
+
Airbrake.configure do | config |
|
59
|
+
config.project_id = '123456'
|
60
|
+
config.project_key = Hoodoo::UUID.generate()
|
61
|
+
end
|
62
|
+
end
|
35
63
|
|
36
|
-
|
37
|
-
|
64
|
+
before :each do
|
65
|
+
WebMock.enable!
|
38
66
|
|
39
|
-
|
40
|
-
|
67
|
+
stub_request( :post, /airbrake\.io\/api/ ).
|
68
|
+
to_return( :body => "{}",
|
69
|
+
:status => 201,
|
70
|
+
:headers => { 'Content-Length' => 2 } )
|
71
|
+
end
|
72
|
+
|
73
|
+
after :each do
|
74
|
+
WebMock.reset!
|
75
|
+
WebMock.disable!
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'can send frozen exceptions' do
|
79
|
+
ex = RuntimeError.new( 'A' )
|
80
|
+
|
81
|
+
# Be sure that the adaptero called Airbrake and that Airbrake did try
|
82
|
+
# to internally send the message (which we'll catch with WebMock via
|
83
|
+
# the "before :each" filter above).
|
84
|
+
#
|
85
|
+
expect( Airbrake ).to receive( :notify_sync ).once.and_call_original
|
86
|
+
expect_any_instance_of( Airbrake::SyncSender ).to receive( :send ).once.and_call_original
|
41
87
|
|
42
|
-
|
88
|
+
# There shouldn't be any need to handle exceptions inside the
|
89
|
+
# communicator pool underneath the adaptor.
|
90
|
+
#
|
91
|
+
expect_any_instance_of( Hoodoo::Communicators::Pool ).to_not receive( :handle_exception )
|
92
|
+
|
93
|
+
Hoodoo::Services::Middleware::ExceptionReporting.report( ex.freeze() )
|
94
|
+
Hoodoo::Services::Middleware::ExceptionReporting.wait()
|
43
95
|
end
|
44
96
|
|
45
|
-
|
97
|
+
it 'can send frozen data large enough to require truncation' do
|
98
|
+
ex = RuntimeError.new( 'A' )
|
99
|
+
mock_env = { 'rack' => 'request' }
|
100
|
+
|
101
|
+
1.upto( Airbrake::Notice::PAYLOAD_MAX_SIZE + 10 ) do | i |
|
102
|
+
mock_env[ Hoodoo::UUID.generate() ] = i
|
103
|
+
end
|
104
|
+
|
105
|
+
# See previous test (above) for an explanation of the expectations
|
106
|
+
# below.
|
107
|
+
|
108
|
+
expect( Airbrake ).to receive( :notify_sync ).once.and_call_original
|
109
|
+
expect_any_instance_of( Airbrake::Truncator ).to receive( :truncate_object ).at_least( :once ).and_call_original
|
110
|
+
expect_any_instance_of( Airbrake::SyncSender ).to receive( :send ).once.and_call_original
|
111
|
+
|
112
|
+
expect_any_instance_of( Hoodoo::Communicators::Pool ).to_not receive( :handle_exception )
|
113
|
+
|
114
|
+
Hoodoo::Services::Middleware::ExceptionReporting.report( ex, mock_env.freeze() )
|
115
|
+
Hoodoo::Services::Middleware::ExceptionReporting.wait()
|
116
|
+
end
|
46
117
|
end
|
47
118
|
end
|
48
119
|
|
data/spec/spec_helper.rb
CHANGED
@@ -19,6 +19,16 @@ end
|
|
19
19
|
|
20
20
|
require 'byebug'
|
21
21
|
|
22
|
+
# Stubbing Net::HTTP with WebMock - disabled by default; only enable for
|
23
|
+
# tests where you need it, as real Net::HTTP connections are used in many
|
24
|
+
# other tests and must not be mocked.
|
25
|
+
#
|
26
|
+
# https://github.com/bblimke/webmock
|
27
|
+
|
28
|
+
require 'webmock/rspec'
|
29
|
+
|
30
|
+
WebMock.disable!
|
31
|
+
|
22
32
|
# The ActiveRecord extensions need testing in the context of a database. I
|
23
33
|
# did consider NullDB - https://github.com/nulldb/nulldb - but this was too
|
24
34
|
# far from 'the real thing' for my liking. Instead, we use SQLite in memory
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hoodoo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Loyalty New Zealand
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-11-
|
11
|
+
date: 2017-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dalli
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '3.5'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.1'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '3.1'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: activerecord
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -212,28 +226,28 @@ dependencies:
|
|
212
226
|
requirements:
|
213
227
|
- - "~>"
|
214
228
|
- !ruby/object:Gem::Version
|
215
|
-
version: '
|
229
|
+
version: '2.6'
|
216
230
|
type: :development
|
217
231
|
prerelease: false
|
218
232
|
version_requirements: !ruby/object:Gem::Requirement
|
219
233
|
requirements:
|
220
234
|
- - "~>"
|
221
235
|
- !ruby/object:Gem::Version
|
222
|
-
version: '
|
236
|
+
version: '2.6'
|
223
237
|
- !ruby/object:Gem::Dependency
|
224
238
|
name: airbrake
|
225
239
|
requirement: !ruby/object:Gem::Requirement
|
226
240
|
requirements:
|
227
241
|
- - "~>"
|
228
242
|
- !ruby/object:Gem::Version
|
229
|
-
version: '
|
243
|
+
version: '7.1'
|
230
244
|
type: :development
|
231
245
|
prerelease: false
|
232
246
|
version_requirements: !ruby/object:Gem::Requirement
|
233
247
|
requirements:
|
234
248
|
- - "~>"
|
235
249
|
- !ruby/object:Gem::Version
|
236
|
-
version: '
|
250
|
+
version: '7.1'
|
237
251
|
- !ruby/object:Gem::Dependency
|
238
252
|
name: le
|
239
253
|
requirement: !ruby/object:Gem::Requirement
|
@@ -518,7 +532,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
518
532
|
requirements:
|
519
533
|
- - ">="
|
520
534
|
- !ruby/object:Gem::Version
|
521
|
-
version: 2.2.
|
535
|
+
version: 2.2.8
|
522
536
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
523
537
|
requirements:
|
524
538
|
- - ">="
|
@@ -526,7 +540,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
526
540
|
version: '0'
|
527
541
|
requirements: []
|
528
542
|
rubyforge_project:
|
529
|
-
rubygems_version: 2.7.
|
543
|
+
rubygems_version: 2.7.2
|
530
544
|
signing_key:
|
531
545
|
specification_version: 4
|
532
546
|
summary: Opinionated APIs
|