appsignal 1.4.0.beta.1 → 2.0.0.beta.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 +40 -17
- data/README.md +6 -5
- data/ext/agent.yml +11 -11
- data/lib/appsignal.rb +20 -19
- data/lib/appsignal/cli.rb +5 -7
- data/lib/appsignal/cli/diagnose.rb +133 -41
- data/lib/appsignal/cli/notify_of_deploy.rb +26 -11
- data/lib/appsignal/config.rb +9 -5
- data/lib/appsignal/integrations/grape.rb +23 -16
- data/lib/appsignal/js_exception_transaction.rb +3 -3
- data/lib/appsignal/marker.rb +4 -3
- data/lib/appsignal/rack/js_exception_catcher.rb +11 -4
- data/lib/appsignal/utils.rb +0 -12
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/capistrano2_spec.rb +7 -7
- data/spec/lib/appsignal/capistrano3_spec.rb +7 -7
- data/spec/lib/appsignal/cli/diagnose_spec.rb +329 -22
- data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +144 -96
- data/spec/lib/appsignal/cli_spec.rb +1 -18
- data/spec/lib/appsignal/config_spec.rb +27 -2
- data/spec/lib/appsignal/hooks/rake_spec.rb +35 -52
- data/spec/lib/appsignal/integrations/grape_spec.rb +172 -63
- data/spec/lib/appsignal/js_exception_transaction_spec.rb +76 -36
- data/spec/lib/appsignal/marker_spec.rb +5 -5
- data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +49 -9
- data/spec/lib/appsignal_spec.rb +18 -7
- data/spec/support/helpers/cli_helpers.rb +17 -0
- data/spec/support/helpers/env_helpers.rb +2 -1
- metadata +5 -6
- data/lib/appsignal/params_sanitizer.rb +0 -13
- data/lib/tasks/diag.rake +0 -79
@@ -1,92 +1,201 @@
|
|
1
1
|
if DependencyHelper.grape_present?
|
2
|
-
require
|
2
|
+
require "appsignal/integrations/grape"
|
3
3
|
|
4
4
|
describe Appsignal::Grape::Middleware do
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
let(:app) do
|
6
|
+
Class.new(::Grape::API) do
|
7
|
+
format :json
|
8
|
+
post :ping do
|
9
|
+
{ :message => "Hello world!" }
|
10
|
+
end
|
11
|
+
end
|
8
12
|
end
|
9
|
-
|
10
|
-
let(:app) { double(:call => true) }
|
11
|
-
let(:api_endpoint) { double(:options => options) }
|
12
|
-
let(:options) { {
|
13
|
-
:for => 'Api::PostPut',
|
14
|
-
:method => ['POST'],
|
15
|
-
:path => ['ping']
|
16
|
-
}}
|
13
|
+
let(:api_endpoint) { app.endpoints.first }
|
17
14
|
let(:env) do
|
18
|
-
http_request_env_with_data
|
15
|
+
http_request_env_with_data \
|
16
|
+
"api.endpoint" => api_endpoint,
|
17
|
+
"REQUEST_METHOD" => "POST",
|
18
|
+
:path => "/ping"
|
19
|
+
end
|
20
|
+
let(:middleware) { Appsignal::Grape::Middleware.new(api_endpoint) }
|
21
|
+
around do |example|
|
22
|
+
GrapeExample = Module.new
|
23
|
+
GrapeExample.send(:const_set, :Api, app)
|
24
|
+
example.run
|
25
|
+
Object.send(:remove_const, :GrapeExample)
|
19
26
|
end
|
20
|
-
let(:middleware) { Appsignal::Grape::Middleware.new(app) }
|
21
27
|
|
22
28
|
describe "#call" do
|
23
|
-
context "when
|
24
|
-
before
|
29
|
+
context "when AppSignal is not active" do
|
30
|
+
before(:all) do
|
31
|
+
Appsignal.config = nil
|
32
|
+
Appsignal::Hooks.load_hooks
|
33
|
+
end
|
25
34
|
|
26
|
-
it "
|
27
|
-
expect(
|
35
|
+
it "creates no transaction" do
|
36
|
+
expect(Appsignal::Transaction).to_not receive(:create)
|
28
37
|
end
|
29
|
-
end
|
30
38
|
|
31
|
-
|
32
|
-
|
39
|
+
it "calls the endpoint normally" do
|
40
|
+
expect(api_endpoint).to receive(:call).with(env)
|
41
|
+
end
|
33
42
|
|
34
|
-
|
35
|
-
|
43
|
+
after { middleware.call(env) }
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when AppSignal is active" do
|
47
|
+
let(:transaction) { http_request_transaction }
|
48
|
+
before :all do
|
49
|
+
Appsignal.config = project_fixture_config
|
50
|
+
expect(Appsignal.active?).to be_true
|
51
|
+
end
|
52
|
+
before do
|
53
|
+
expect(Appsignal::Transaction).to receive(:create).with(
|
54
|
+
kind_of(String),
|
55
|
+
Appsignal::Transaction::HTTP_REQUEST,
|
56
|
+
kind_of(::Rack::Request)
|
57
|
+
).and_return(transaction)
|
36
58
|
end
|
37
59
|
|
38
|
-
|
39
|
-
|
60
|
+
context "without error" do
|
61
|
+
it "calls the endpoint" do
|
62
|
+
expect(api_endpoint).to receive(:call).with(env)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "sets metadata" do
|
66
|
+
expect(transaction).to receive(:set_http_or_background_queue_start)
|
67
|
+
expect(transaction).to receive(:set_action).with("POST::GrapeExample::Api#/ping")
|
68
|
+
expect(transaction).to receive(:set_metadata).with("path", "/ping")
|
69
|
+
expect(transaction).to receive(:set_metadata).with("method", "POST")
|
70
|
+
end
|
71
|
+
|
72
|
+
after { middleware.call(env) }
|
40
73
|
end
|
41
|
-
end
|
42
74
|
|
43
|
-
|
44
|
-
|
75
|
+
context "with error" do
|
76
|
+
let(:app) do
|
77
|
+
Class.new(::Grape::API) do
|
78
|
+
format :json
|
79
|
+
post :ping do
|
80
|
+
raise VerySpecificError
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
45
84
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
Appsignal::Transaction::HTTP_REQUEST,
|
53
|
-
kind_of(::Rack::Request)
|
54
|
-
).and_return(
|
55
|
-
double(
|
56
|
-
:set_action => nil,
|
57
|
-
:set_http_or_background_queue_start => nil,
|
58
|
-
:set_metadata => nil
|
59
|
-
)
|
60
|
-
)
|
61
|
-
end
|
85
|
+
it "sets metadata" do
|
86
|
+
expect(transaction).to receive(:set_http_or_background_queue_start)
|
87
|
+
expect(transaction).to receive(:set_action).with("POST::GrapeExample::Api#/ping")
|
88
|
+
expect(transaction).to receive(:set_metadata).with("path", "/ping")
|
89
|
+
expect(transaction).to receive(:set_metadata).with("method", "POST")
|
90
|
+
end
|
62
91
|
|
63
|
-
|
64
|
-
|
65
|
-
|
92
|
+
it "sets the error" do
|
93
|
+
expect(transaction).to receive(:set_error).with(kind_of(VerySpecificError))
|
94
|
+
end
|
66
95
|
|
67
|
-
|
68
|
-
|
69
|
-
let(:app) do
|
70
|
-
double.tap do |d|
|
71
|
-
d.stub(:call).and_raise(error)
|
96
|
+
after do
|
97
|
+
expect { middleware.call(env) }.to raise_error VerySpecificError
|
72
98
|
end
|
73
99
|
end
|
74
100
|
|
75
|
-
|
76
|
-
|
101
|
+
context "with route_param" do
|
102
|
+
let(:app) do
|
103
|
+
Class.new(::Grape::API) do
|
104
|
+
format :json
|
105
|
+
resource :users do
|
106
|
+
route_param :id do
|
107
|
+
get do
|
108
|
+
{ :name => "Tom" }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
let(:env) do
|
115
|
+
http_request_env_with_data \
|
116
|
+
"api.endpoint" => api_endpoint,
|
117
|
+
"REQUEST_METHOD" => "GET",
|
118
|
+
:path => ""
|
119
|
+
end
|
120
|
+
|
121
|
+
it "sets non-unique route_param path" do
|
122
|
+
expect(transaction).to receive(:set_action).with("GET::GrapeExample::Api#/users/:id/")
|
123
|
+
expect(transaction).to receive(:set_metadata).with("path", "/users/:id/")
|
124
|
+
expect(transaction).to receive(:set_metadata).with("method", "GET")
|
125
|
+
end
|
126
|
+
|
127
|
+
after { middleware.call(env) }
|
77
128
|
end
|
78
|
-
end
|
79
129
|
|
80
|
-
|
81
|
-
|
82
|
-
|
130
|
+
context "with namespaced path" do
|
131
|
+
context "with symbols" do
|
132
|
+
let(:app) do
|
133
|
+
Class.new(::Grape::API) do
|
134
|
+
format :json
|
135
|
+
namespace :v1 do
|
136
|
+
namespace :beta do
|
137
|
+
post :ping do
|
138
|
+
{ :message => "Hello namespaced world!" }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
it "sets namespaced path" do
|
146
|
+
expect(transaction).to receive(:set_action).with("POST::GrapeExample::Api#/v1/beta/ping")
|
147
|
+
expect(transaction).to receive(:set_metadata).with("path", "/v1/beta/ping")
|
148
|
+
expect(transaction).to receive(:set_metadata).with("method", "POST")
|
149
|
+
end
|
150
|
+
end
|
83
151
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
152
|
+
context "with strings" do
|
153
|
+
context "without / prefix" do
|
154
|
+
let(:app) do
|
155
|
+
Class.new(::Grape::API) do
|
156
|
+
format :json
|
157
|
+
namespace "v1" do
|
158
|
+
namespace "beta" do
|
159
|
+
post "ping" do
|
160
|
+
{ :message => "Hello namespaced world!" }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
it "sets namespaced path" do
|
168
|
+
expect(transaction).to receive(:set_action).with("POST::GrapeExample::Api#/v1/beta/ping")
|
169
|
+
expect(transaction).to receive(:set_metadata).with("path", "/v1/beta/ping")
|
170
|
+
expect(transaction).to receive(:set_metadata).with("method", "POST")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context "with / prefix" do
|
175
|
+
let(:app) do
|
176
|
+
Class.new(::Grape::API) do
|
177
|
+
format :json
|
178
|
+
namespace "/v1" do
|
179
|
+
namespace "/beta" do
|
180
|
+
post "/ping" do
|
181
|
+
{ :message => "Hello namespaced world!" }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
it "sets namespaced path" do
|
189
|
+
expect(transaction).to receive(:set_action).with("POST::GrapeExample::Api#/v1/beta/ping")
|
190
|
+
expect(transaction).to receive(:set_metadata).with("path", "/v1/beta/ping")
|
191
|
+
expect(transaction).to receive(:set_metadata).with("method", "POST")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
88
195
|
|
89
|
-
|
196
|
+
after { middleware.call(env) }
|
197
|
+
end
|
198
|
+
end
|
90
199
|
end
|
91
200
|
end
|
92
201
|
end
|
@@ -21,22 +21,22 @@ describe Appsignal::JSExceptionTransaction do
|
|
21
21
|
|
22
22
|
describe "#initialize" do
|
23
23
|
it "should call all required methods" do
|
24
|
-
expect(
|
24
|
+
expect(Appsignal::Extension).to receive(:start_transaction).with('123abc', 'frontend', 0).and_return(1)
|
25
25
|
|
26
|
-
expect(
|
27
|
-
expect(
|
28
|
-
expect(
|
29
|
-
expect(
|
26
|
+
expect(transaction).to receive(:set_action)
|
27
|
+
expect(transaction).to receive(:set_metadata)
|
28
|
+
expect(transaction).to receive(:set_error)
|
29
|
+
expect(transaction).to receive(:set_sample_data)
|
30
30
|
|
31
31
|
transaction.send :initialize, data
|
32
32
|
|
33
|
-
expect(
|
33
|
+
expect(transaction.ext).to_not be_nil
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
describe "#
|
38
|
-
it "should call `Appsignal::Extension.
|
39
|
-
expect(
|
37
|
+
describe "#set_action" do
|
38
|
+
it "should call `Appsignal::Extension.set_action`" do
|
39
|
+
expect(transaction.ext).to receive(:set_action).with(
|
40
40
|
'ExceptionIncidentComponent'
|
41
41
|
)
|
42
42
|
|
@@ -45,43 +45,83 @@ describe Appsignal::JSExceptionTransaction do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
describe "#set_metadata" do
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
it "should call `Appsignal::Extension.set_transaction_metadata`" do
|
49
|
+
expect(transaction.ext).to receive(:set_metadata).with(
|
50
|
+
'path',
|
51
|
+
'foo.bar/moo'
|
52
|
+
)
|
53
|
+
|
54
|
+
transaction.set_metadata
|
55
|
+
end
|
56
56
|
end
|
57
57
|
|
58
58
|
describe "#set_error" do
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
59
|
+
it "should call `Appsignal::Extension.set_transaction_error`" do
|
60
|
+
expect(transaction.ext).to receive(:set_error).with(
|
61
|
+
'TypeError',
|
62
|
+
'foo is not a valid method',
|
63
|
+
Appsignal::Utils.data_generate(['foo.bar/js:11:1', 'foo.bar/js:22:2'])
|
64
|
+
)
|
65
|
+
|
66
|
+
transaction.set_error
|
67
|
+
end
|
68
68
|
end
|
69
69
|
|
70
70
|
describe "#set_sample_data" do
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
71
|
+
it "should call `Appsignal::Extension.set_transaction_error_data`" do
|
72
|
+
expect(transaction.ext).to receive(:set_sample_data).with(
|
73
|
+
'tags',
|
74
|
+
Appsignal::Utils.data_generate(['tag1'])
|
75
|
+
)
|
76
|
+
|
77
|
+
transaction.set_sample_data
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when sending just the name" do
|
82
|
+
let(:data) { {'name' => 'TypeError'} }
|
83
|
+
|
84
|
+
describe "#set_action" do
|
85
|
+
it "should not call `Appsignal::Extension.set_action`" do
|
86
|
+
expect(transaction.ext).to_not receive(:set_action)
|
87
|
+
|
88
|
+
transaction.set_action
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#set_metadata" do
|
93
|
+
it "should not call `Appsignal::Extension.set_transaction_metadata`" do
|
94
|
+
expect(transaction.ext).to_not receive(:set_metadata)
|
95
|
+
|
96
|
+
transaction.set_metadata
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#set_error" do
|
101
|
+
it "should call `Appsignal::Extension.set_transaction_error` with just the name" do
|
102
|
+
expect(transaction.ext).to receive(:set_error).with(
|
103
|
+
'TypeError',
|
104
|
+
'',
|
105
|
+
Appsignal::Utils.data_generate([])
|
106
|
+
)
|
107
|
+
|
108
|
+
transaction.set_error
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#set_sample_data" do
|
113
|
+
it "should not call `Appsignal::Extension.set_transaction_error_data`" do
|
114
|
+
expect(transaction.ext).to_not receive(:set_sample_data)
|
115
|
+
|
116
|
+
transaction.set_sample_data
|
117
|
+
end
|
118
|
+
end
|
79
119
|
end
|
80
120
|
|
81
121
|
describe "#complete!" do
|
82
122
|
it "should call all required methods" do
|
83
|
-
expect(
|
84
|
-
expect(
|
123
|
+
expect(transaction.ext).to receive(:finish)
|
124
|
+
expect(transaction.ext).to receive(:complete)
|
85
125
|
transaction.complete!
|
86
126
|
end
|
87
127
|
end
|
@@ -30,8 +30,8 @@ describe Appsignal::Marker do
|
|
30
30
|
it "outputs success" do
|
31
31
|
output = out_stream.string
|
32
32
|
expect(output).to include \
|
33
|
-
'Notifying
|
34
|
-
'
|
33
|
+
'Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman',
|
34
|
+
'AppSignal has been notified of this deploy!'
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -44,11 +44,11 @@ describe Appsignal::Marker do
|
|
44
44
|
it "outputs failure" do
|
45
45
|
output = out_stream.string
|
46
46
|
expect(output).to include \
|
47
|
-
'Notifying
|
48
|
-
"Something went wrong while trying to notify
|
47
|
+
'Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman',
|
48
|
+
"Something went wrong while trying to notify AppSignal: 500 at "\
|
49
49
|
"#{config[:endpoint]}/1/markers"
|
50
50
|
expect(output).to_not include \
|
51
|
-
'
|
51
|
+
'AppSignal has been notified of this deploy!'
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -12,7 +12,7 @@ describe Appsignal::Rack::JSExceptionCatcher do
|
|
12
12
|
|
13
13
|
describe "#initialize" do
|
14
14
|
it "should log to the logger" do
|
15
|
-
expect(
|
15
|
+
expect(Appsignal.logger).to receive(:debug)
|
16
16
|
.with('Initializing Appsignal::Rack::JSExceptionCatcher')
|
17
17
|
|
18
18
|
Appsignal::Rack::JSExceptionCatcher.new(app, options)
|
@@ -26,7 +26,7 @@ describe Appsignal::Rack::JSExceptionCatcher do
|
|
26
26
|
let(:env) { {'PATH_INFO' => '/foo'} }
|
27
27
|
|
28
28
|
it "should call the next middleware" do
|
29
|
-
expect(
|
29
|
+
expect(app).to receive(:call).with(env)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -35,16 +35,23 @@ describe Appsignal::Rack::JSExceptionCatcher do
|
|
35
35
|
let(:env) do
|
36
36
|
{
|
37
37
|
'PATH_INFO' => '/appsignal_error_catcher',
|
38
|
-
'rack.input' => double(:read => '{"
|
38
|
+
'rack.input' => double(:read => '{"name": "error"}')
|
39
39
|
}
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should create a JSExceptionTransaction" do
|
43
|
-
expect(
|
44
|
-
.with({'
|
43
|
+
expect(Appsignal::JSExceptionTransaction).to receive(:new)
|
44
|
+
.with({'name' => 'error'})
|
45
45
|
.and_return(transaction)
|
46
46
|
|
47
|
-
expect(
|
47
|
+
expect(transaction).to receive(:complete!)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return 200" do
|
51
|
+
allow( Appsignal::JSExceptionTransaction).to receive(:new)
|
52
|
+
.and_return(transaction)
|
53
|
+
|
54
|
+
expect(catcher.call(env)).to eql([200, {}, []])
|
48
55
|
end
|
49
56
|
|
50
57
|
context "when `frontend_error_catching_path` is different" do
|
@@ -55,16 +62,49 @@ describe Appsignal::Rack::JSExceptionCatcher do
|
|
55
62
|
end
|
56
63
|
|
57
64
|
it "should not create a transaction" do
|
58
|
-
expect(
|
65
|
+
expect(Appsignal::JSExceptionTransaction).to_not receive(:new)
|
59
66
|
end
|
60
67
|
|
61
68
|
it "should call the next middleware" do
|
62
|
-
expect(
|
69
|
+
expect(app).to receive(:call).with(env)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "when `name` is empty" do
|
74
|
+
let(:env) do
|
75
|
+
{
|
76
|
+
'PATH_INFO' => '/appsignal_error_catcher',
|
77
|
+
'rack.input' => double(:read => '{"name": ""}')
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should not create a transaction" do
|
82
|
+
expect(Appsignal::JSExceptionTransaction).to_not receive(:new)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return 422" do
|
86
|
+
expect(catcher.call(env)).to eql([422, {}, []])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when `name` doesn't exist" do
|
91
|
+
let(:env) do
|
92
|
+
{
|
93
|
+
'PATH_INFO' => '/appsignal_error_catcher',
|
94
|
+
'rack.input' => double(:read => '{"foo": ""}')
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should not create a transaction" do
|
99
|
+
expect(Appsignal::JSExceptionTransaction).to_not receive(:new)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should return 422" do
|
103
|
+
expect(catcher.call(env)).to eql([422, {}, []])
|
63
104
|
end
|
64
105
|
end
|
65
106
|
end
|
66
107
|
|
67
108
|
after { catcher.call(env) }
|
68
109
|
end
|
69
|
-
|
70
110
|
end
|