airbrake 9.0.2 → 9.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/airbrake/rails.rb +2 -0
- data/lib/airbrake/rails/action_controller_notify_subscriber.rb +6 -22
- data/lib/airbrake/rails/action_controller_performance_breakdown_subscriber.rb +8 -27
- data/lib/airbrake/rails/action_controller_route_subscriber.rb +17 -25
- data/lib/airbrake/rails/active_record_subscriber.rb +11 -7
- data/lib/airbrake/rails/app.rb +33 -0
- data/lib/airbrake/rails/backtrace_cleaner.rb +10 -0
- data/lib/airbrake/rails/event.rb +71 -0
- data/lib/airbrake/rails/net_http.rb +23 -0
- data/lib/airbrake/version.rb +1 -1
- data/spec/apps/rails/dummy_app.rb +14 -1
- data/spec/apps/rails/logs/32.log +16886 -0
- data/spec/apps/rails/logs/52.log +1017 -0
- data/spec/integration/rails/rails_spec.rb +30 -1
- data/spec/unit/rails/action_controller_notify_subscriber_spec.rb +43 -0
- data/spec/unit/rails/action_controller_performance_breakdown_subscriber_spec.rb +21 -100
- data/spec/unit/rails/action_controller_route_subscriber_spec.rb +84 -0
- data/spec/unit/rails/active_record_subscriber_spec.rb +70 -0
- metadata +12 -2
@@ -262,7 +262,7 @@ RSpec.describe "Rails integration specs" do
|
|
262
262
|
hash_including(
|
263
263
|
route: '/crash(.:format)',
|
264
264
|
method: 'GET',
|
265
|
-
func: '
|
265
|
+
func: 'call',
|
266
266
|
file: 'lib/airbrake/rails/active_record_subscriber.rb',
|
267
267
|
line: anything
|
268
268
|
)
|
@@ -305,5 +305,34 @@ RSpec.describe "Rails integration specs" do
|
|
305
305
|
|
306
306
|
get '/breakdown'
|
307
307
|
end
|
308
|
+
|
309
|
+
context "when response format is */*" do
|
310
|
+
it "normalizes it to :html" do
|
311
|
+
expect(Airbrake).to receive(:notify_performance_breakdown)
|
312
|
+
.with(hash_including(response_type: :html))
|
313
|
+
get '/breakdown', {}, 'HTTP_ACCEPT' => '*/*'
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context "when db_runtime is nil" do
|
318
|
+
it "omits the db group" do
|
319
|
+
expect(Airbrake).to receive(:notify_performance_breakdown)
|
320
|
+
.with(hash_including(groups: { view: be > 0 }))
|
321
|
+
get '/breakdown_view_only'
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
context "when an action performs a HTTP request" do
|
326
|
+
let!(:example_request) do
|
327
|
+
stub_request(:get, 'http://example.com').to_return(body: '')
|
328
|
+
end
|
329
|
+
|
330
|
+
it "includes the http breakdown" do
|
331
|
+
expect(Airbrake).to receive(:notify_performance_breakdown)
|
332
|
+
.with(hash_including(groups: { view: be > 0, http: be > 0 }))
|
333
|
+
get '/breakdown_http'
|
334
|
+
expect(example_request).to have_been_made
|
335
|
+
end
|
336
|
+
end
|
308
337
|
end
|
309
338
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'airbrake/rails/action_controller_notify_subscriber'
|
2
|
+
|
3
|
+
RSpec.describe Airbrake::Rails::ActionControllerNotifySubscriber do
|
4
|
+
after { Airbrake::Rack::RequestStore.clear }
|
5
|
+
|
6
|
+
describe "#call" do
|
7
|
+
let(:event) { double(Airbrake::Rails::Event) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(Airbrake::Rails::Event).to receive(:new).and_return(event)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when there are no routes in the request store" do
|
14
|
+
it "doesn't notify requests" do
|
15
|
+
expect(Airbrake).not_to receive(:notify_request)
|
16
|
+
subject.call([])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when there's a route in the request store" do
|
21
|
+
before do
|
22
|
+
Airbrake::Rack::RequestStore[:routes] = {
|
23
|
+
'/test-route' => { method: 'GET', response_type: :html }
|
24
|
+
}
|
25
|
+
|
26
|
+
expect(event).to receive(:method).and_return('GET')
|
27
|
+
expect(event).to receive(:status_code).and_return(200)
|
28
|
+
expect(event).to receive(:time).and_return(Time.now)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "sends request info to Airbrake" do
|
32
|
+
expect(Airbrake).to receive(:notify_request).with(
|
33
|
+
hash_including(
|
34
|
+
method: 'GET',
|
35
|
+
route: '/test-route',
|
36
|
+
status_code: 200
|
37
|
+
)
|
38
|
+
)
|
39
|
+
subject.call([])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,6 +1,13 @@
|
|
1
1
|
require 'airbrake/rails/action_controller_performance_breakdown_subscriber'
|
2
2
|
|
3
3
|
RSpec.describe Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber do
|
4
|
+
let(:app) { double(Airbrake::Rails::App) }
|
5
|
+
let(:event) { double(Airbrake::Rails::Event) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
allow(Airbrake::Rails::Event).to receive(:new).and_return(event)
|
9
|
+
end
|
10
|
+
|
4
11
|
after { Airbrake::Rack::RequestStore.clear }
|
5
12
|
|
6
13
|
context "when routes are not set in the request store" do
|
@@ -13,7 +20,7 @@ RSpec.describe Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber d
|
|
13
20
|
end
|
14
21
|
|
15
22
|
context "when there are no routes in the request store" do
|
16
|
-
before { Airbrake::Rack::RequestStore[:routes] =
|
23
|
+
before { Airbrake::Rack::RequestStore[:routes] = {} }
|
17
24
|
|
18
25
|
it "doesn't send performance breakdown info" do
|
19
26
|
expect(Airbrake).not_to receive(:notify_performance_breakdown)
|
@@ -22,121 +29,35 @@ RSpec.describe Airbrake::Rails::ActionControllerPerformanceBreakdownSubscriber d
|
|
22
29
|
end
|
23
30
|
|
24
31
|
context "when there's a route in the request store" do
|
25
|
-
let(:event) do
|
26
|
-
OpenStruct.new(
|
27
|
-
payload: {
|
28
|
-
format: :html,
|
29
|
-
view_runtime: 0.5,
|
30
|
-
db_runtime: 0.5
|
31
|
-
}
|
32
|
-
)
|
33
|
-
end
|
34
|
-
|
35
32
|
before do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
expect(
|
40
|
-
stub_const('ActiveSupport::Notifications::Event', event_dbl)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "sends performance info to Airbrake" do
|
44
|
-
expect(Airbrake).to receive(:notify_performance_breakdown).with(
|
45
|
-
hash_including(
|
46
|
-
route: '/test-route',
|
47
|
-
method: 'GET',
|
48
|
-
response_type: :html,
|
49
|
-
groups: { db: 0.5, view: 0.5 }
|
50
|
-
)
|
51
|
-
)
|
52
|
-
subject.call([])
|
53
|
-
end
|
54
|
-
|
55
|
-
context "and when view_runtime is nil" do
|
56
|
-
before { event.payload[:view_runtime] = nil }
|
57
|
-
|
58
|
-
it "omits view_runtime" do
|
59
|
-
expect(Airbrake).to receive(:notify_performance_breakdown).with(
|
60
|
-
hash_including(
|
61
|
-
route: '/test-route',
|
62
|
-
method: 'GET',
|
63
|
-
response_type: :html,
|
64
|
-
groups: { db: 0.5 }
|
65
|
-
)
|
66
|
-
)
|
67
|
-
subject.call([])
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
context "and when db_runtime is nil" do
|
72
|
-
before { event.payload[:db_runtime] = nil }
|
73
|
-
|
74
|
-
it "omits db_runtime" do
|
75
|
-
expect(Airbrake).to receive(:notify_performance_breakdown).with(
|
76
|
-
hash_including(
|
77
|
-
route: '/test-route',
|
78
|
-
method: 'GET',
|
79
|
-
response_type: :html,
|
80
|
-
groups: { view: 0.5 }
|
81
|
-
)
|
82
|
-
)
|
83
|
-
subject.call([])
|
84
|
-
end
|
33
|
+
expect(event).to receive(:groups).and_return(db: 0.5, view: 0.5)
|
34
|
+
expect(event).to receive(:method).and_return('GET')
|
35
|
+
expect(event).to receive(:response_type).and_return(:html)
|
36
|
+
expect(event).to receive(:time).and_return(Time.new)
|
85
37
|
end
|
86
38
|
|
87
|
-
context "when
|
88
|
-
before
|
89
|
-
|
90
|
-
|
91
|
-
expect(Airbrake).to receive(:notify_performance_breakdown).with(
|
92
|
-
hash_including(
|
93
|
-
route: '/test-route',
|
39
|
+
context "when request store routes have extra groups" do
|
40
|
+
before do
|
41
|
+
Airbrake::Rack::RequestStore[:routes] = {
|
42
|
+
'/test-route' => {
|
94
43
|
method: 'GET',
|
95
44
|
response_type: :html,
|
96
|
-
groups: {
|
97
|
-
|
98
|
-
|
99
|
-
subject.call([])
|
45
|
+
groups: { http: 0.5 }
|
46
|
+
}
|
47
|
+
}
|
100
48
|
end
|
101
|
-
end
|
102
49
|
|
103
|
-
|
104
|
-
before { event.payload[:view_runtime] = 0 }
|
105
|
-
|
106
|
-
it "omits view_runtime" do
|
50
|
+
it "sends performance info to Airbrake with extra groups" do
|
107
51
|
expect(Airbrake).to receive(:notify_performance_breakdown).with(
|
108
52
|
hash_including(
|
109
53
|
route: '/test-route',
|
110
54
|
method: 'GET',
|
111
55
|
response_type: :html,
|
112
|
-
groups: { db: 0.5 }
|
56
|
+
groups: { db: 0.5, view: 0.5, http: 0.5 }
|
113
57
|
)
|
114
58
|
)
|
115
59
|
subject.call([])
|
116
60
|
end
|
117
61
|
end
|
118
|
-
|
119
|
-
context "when db_runtime and view_runtime are both zero" do
|
120
|
-
before do
|
121
|
-
event.payload[:db_runtime] = 0
|
122
|
-
event.payload[:view_runtime] = 0
|
123
|
-
end
|
124
|
-
|
125
|
-
it "doesn't notify Airbrake" do
|
126
|
-
expect(Airbrake).not_to receive(:notify_performance_breakdown)
|
127
|
-
subject.call([])
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
context "when response format is */*" do
|
132
|
-
before { event.payload[:format] = "*/*" }
|
133
|
-
|
134
|
-
it "normalizes it to :html" do
|
135
|
-
expect(Airbrake).to receive(:notify_performance_breakdown).with(
|
136
|
-
hash_including(response_type: :html)
|
137
|
-
)
|
138
|
-
subject.call([])
|
139
|
-
end
|
140
|
-
end
|
141
62
|
end
|
142
63
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'airbrake/rails/action_controller_route_subscriber'
|
3
|
+
|
4
|
+
RSpec.describe Airbrake::Rails::ActionControllerRouteSubscriber do
|
5
|
+
describe "#call" do
|
6
|
+
let(:app) { double(Airbrake::Rails::App) }
|
7
|
+
let(:event) { double(Airbrake::Rails::Event) }
|
8
|
+
|
9
|
+
let(:event_params) do
|
10
|
+
[
|
11
|
+
'start_processing.action_controller',
|
12
|
+
Time.new,
|
13
|
+
Time.new,
|
14
|
+
'123',
|
15
|
+
{ method: 'HEAD', path: '/crash' }
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
before do
|
20
|
+
allow(Airbrake::Rails::App).to receive(:new).and_return(app)
|
21
|
+
allow(Airbrake::Rails::Event).to receive(:new).and_return(event)
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when request store has the :routes key" do
|
25
|
+
let(:routes) do
|
26
|
+
[Airbrake::Rails::App::Route.new('/crash', 'DummyController', 'crash')]
|
27
|
+
end
|
28
|
+
|
29
|
+
before do
|
30
|
+
allow(app).to receive(:routes).and_return(routes)
|
31
|
+
allow(event).to receive(:params).and_return(params)
|
32
|
+
allow(event).to receive(:method).and_return('HEAD')
|
33
|
+
allow(event).to receive(:response_type).and_return(:html)
|
34
|
+
|
35
|
+
Airbrake::Rack::RequestStore[:routes] = {}
|
36
|
+
end
|
37
|
+
|
38
|
+
after { Airbrake::Rack::RequestStore.clear }
|
39
|
+
|
40
|
+
context "and when the route can be found" do
|
41
|
+
let(:params) do
|
42
|
+
OpenStruct.new(controller: 'DummyController', action: 'crash')
|
43
|
+
end
|
44
|
+
|
45
|
+
it "stores a route in the request store under :routes" do
|
46
|
+
subject.call(event_params)
|
47
|
+
expect(Airbrake::Rack::RequestStore[:routes])
|
48
|
+
.to eq('/crash' => { method: 'HEAD', response_type: :html, groups: {} })
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "and when the event controller can't be found" do
|
53
|
+
let(:params) do
|
54
|
+
OpenStruct.new(controller: 'BananaController', action: 'crash')
|
55
|
+
end
|
56
|
+
|
57
|
+
it "doesn't store any routes in the request store under :routes" do
|
58
|
+
subject.call(event_params)
|
59
|
+
expect(Airbrake::Rack::RequestStore[:routes]).to be_empty
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "and when the event action can't be found" do
|
64
|
+
let(:params) do
|
65
|
+
OpenStruct.new(controller: 'DummyController', action: 'banana')
|
66
|
+
end
|
67
|
+
|
68
|
+
it "doesn't store any routes in the request store under :routes" do
|
69
|
+
subject.call(event_params)
|
70
|
+
expect(Airbrake::Rack::RequestStore[:routes]).to be_empty
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when request store doesn't have the :routes key" do
|
76
|
+
before { Airbrake::Rack::RequestStore.clear }
|
77
|
+
|
78
|
+
it "doesn't store any routes in the request store" do
|
79
|
+
subject.call(event_params)
|
80
|
+
expect(Airbrake::Rack::RequestStore[:routes]).to be_nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'airbrake/rails/active_record_subscriber'
|
2
|
+
|
3
|
+
RSpec.describe Airbrake::Rails::ActiveRecordSubscriber do
|
4
|
+
after { Airbrake::Rack::RequestStore.clear }
|
5
|
+
|
6
|
+
describe "#call" do
|
7
|
+
let(:event) { double(Airbrake::Rails::Event) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(Airbrake::Rails::Event).to receive(:new).and_return(event)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when there are no routes in the request store" do
|
14
|
+
it "doesn't notify requests" do
|
15
|
+
expect(Airbrake).not_to receive(:notify_query)
|
16
|
+
subject.call([])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when there's a route in the request store" do
|
21
|
+
before do
|
22
|
+
Airbrake::Rack::RequestStore[:routes] = {
|
23
|
+
'/test-route' => { method: 'GET', response_type: :html }
|
24
|
+
}
|
25
|
+
|
26
|
+
allow(event).to receive(:sql).and_return('SELECT * FROM bananas')
|
27
|
+
allow(event).to receive(:time).and_return(Time.now)
|
28
|
+
allow(event).to receive(:end).and_return(Time.now)
|
29
|
+
allow(Airbrake::Rails::BacktraceCleaner).to receive(:clean).and_return(
|
30
|
+
"/lib/pry/cli.rb:117:in `start'"
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "sends query info to Airbrake" do
|
35
|
+
expect(Airbrake).to receive(:notify_query).with(
|
36
|
+
hash_including(
|
37
|
+
method: 'GET',
|
38
|
+
route: '/test-route',
|
39
|
+
query: 'SELECT * FROM bananas',
|
40
|
+
func: 'start',
|
41
|
+
line: 117,
|
42
|
+
file: '/lib/pry/cli.rb'
|
43
|
+
)
|
44
|
+
)
|
45
|
+
subject.call([])
|
46
|
+
end
|
47
|
+
|
48
|
+
context "and when backtrace couldn't be parsed" do
|
49
|
+
before do
|
50
|
+
allow(Airbrake::Rails::BacktraceCleaner)
|
51
|
+
.to receive(:clean).and_return([])
|
52
|
+
end
|
53
|
+
|
54
|
+
it "sends empty func/file/line to Airbrake" do
|
55
|
+
expect(Airbrake).to receive(:notify_query).with(
|
56
|
+
hash_including(
|
57
|
+
method: 'GET',
|
58
|
+
route: '/test-route',
|
59
|
+
query: 'SELECT * FROM bananas',
|
60
|
+
func: nil,
|
61
|
+
line: nil,
|
62
|
+
file: nil
|
63
|
+
)
|
64
|
+
)
|
65
|
+
subject.call([])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: airbrake
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 9.0
|
4
|
+
version: 9.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Airbrake Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: airbrake-ruby
|
@@ -283,6 +283,10 @@ files:
|
|
283
283
|
- lib/airbrake/rails/active_job.rb
|
284
284
|
- lib/airbrake/rails/active_record.rb
|
285
285
|
- lib/airbrake/rails/active_record_subscriber.rb
|
286
|
+
- lib/airbrake/rails/app.rb
|
287
|
+
- lib/airbrake/rails/backtrace_cleaner.rb
|
288
|
+
- lib/airbrake/rails/event.rb
|
289
|
+
- lib/airbrake/rails/net_http.rb
|
286
290
|
- lib/airbrake/rake.rb
|
287
291
|
- lib/airbrake/rake/tasks.rb
|
288
292
|
- lib/airbrake/resque.rb
|
@@ -319,7 +323,10 @@ files:
|
|
319
323
|
- spec/unit/rack/user_filter_spec.rb
|
320
324
|
- spec/unit/rack/user_spec.rb
|
321
325
|
- spec/unit/rails/action_cable/notify_callback_spec.rb
|
326
|
+
- spec/unit/rails/action_controller_notify_subscriber_spec.rb
|
322
327
|
- spec/unit/rails/action_controller_performance_breakdown_subscriber_spec.rb
|
328
|
+
- spec/unit/rails/action_controller_route_subscriber_spec.rb
|
329
|
+
- spec/unit/rails/active_record_subscriber_spec.rb
|
323
330
|
- spec/unit/rake/tasks_spec.rb
|
324
331
|
- spec/unit/shoryuken_spec.rb
|
325
332
|
- spec/unit/sidekiq/retryable_jobs_filter_spec.rb
|
@@ -369,7 +376,10 @@ test_files:
|
|
369
376
|
- spec/unit/rack/user_spec.rb
|
370
377
|
- spec/unit/rack/route_filter_spec.rb
|
371
378
|
- spec/unit/rails/action_controller_performance_breakdown_subscriber_spec.rb
|
379
|
+
- spec/unit/rails/active_record_subscriber_spec.rb
|
372
380
|
- spec/unit/rails/action_cable/notify_callback_spec.rb
|
381
|
+
- spec/unit/rails/action_controller_notify_subscriber_spec.rb
|
382
|
+
- spec/unit/rails/action_controller_route_subscriber_spec.rb
|
373
383
|
- spec/integration/sinatra/sinatra_spec.rb
|
374
384
|
- spec/integration/rack/rack_spec.rb
|
375
385
|
- spec/integration/shared_examples/rack_examples.rb
|