appsignal 4.0.3-java → 4.0.5-java
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 +51 -0
- data/ext/agent.rb +27 -27
- data/lib/appsignal/check_in/cron.rb +2 -34
- data/lib/appsignal/check_in/scheduler.rb +192 -0
- data/lib/appsignal/check_in.rb +18 -0
- data/lib/appsignal/cli/diagnose.rb +1 -1
- data/lib/appsignal/config.rb +7 -0
- data/lib/appsignal/hooks/at_exit.rb +3 -1
- data/lib/appsignal/hooks/puma.rb +5 -1
- data/lib/appsignal/integrations/puma.rb +45 -0
- data/lib/appsignal/rack/abstract_middleware.rb +3 -47
- data/lib/appsignal/rack/body_wrapper.rb +15 -0
- data/lib/appsignal/rack/event_handler.rb +2 -0
- data/lib/appsignal/rack/hanami_middleware.rb +5 -1
- data/lib/appsignal/rack.rb +68 -0
- data/lib/appsignal/transmitter.rb +30 -7
- data/lib/appsignal/utils/ndjson.rb +15 -0
- data/lib/appsignal/utils.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +1 -0
- data/spec/lib/appsignal/check_in/cron_spec.rb +202 -0
- data/spec/lib/appsignal/check_in/scheduler_spec.rb +443 -0
- data/spec/lib/appsignal/config_spec.rb +13 -0
- data/spec/lib/appsignal/environment_spec.rb +1 -1
- data/spec/lib/appsignal/hooks/at_exit_spec.rb +22 -0
- data/spec/lib/appsignal/hooks/puma_spec.rb +31 -23
- data/spec/lib/appsignal/integrations/puma_spec.rb +150 -0
- data/spec/lib/appsignal/probes_spec.rb +1 -6
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +41 -122
- data/spec/lib/appsignal/rack/body_wrapper_spec.rb +29 -21
- data/spec/lib/appsignal/rack_spec.rb +180 -0
- data/spec/lib/appsignal/transmitter_spec.rb +48 -2
- data/spec/lib/appsignal_spec.rb +5 -0
- data/spec/spec_helper.rb +0 -7
- data/spec/support/helpers/config_helpers.rb +2 -1
- data/spec/support/helpers/take_at_most_helper.rb +21 -0
- data/spec/support/matchers/contains_log.rb +10 -3
- data/spec/support/mocks/hash_like.rb +10 -0
- data/spec/support/mocks/puma_mock.rb +43 -0
- metadata +11 -3
- data/spec/lib/appsignal/check_in_spec.rb +0 -136
@@ -0,0 +1,150 @@
|
|
1
|
+
require "appsignal/integrations/puma"
|
2
|
+
|
3
|
+
describe Appsignal::Integrations::PumaServer do
|
4
|
+
describe "#lowlevel_error" do
|
5
|
+
before do
|
6
|
+
stub_const("Puma", PumaMock)
|
7
|
+
stub_const("Puma::Server", puma_server)
|
8
|
+
start_agent
|
9
|
+
end
|
10
|
+
let(:queue_start_time) { fixed_time * 1_000 }
|
11
|
+
let(:env) do
|
12
|
+
Rack::MockRequest.env_for(
|
13
|
+
"/some/path",
|
14
|
+
"REQUEST_METHOD" => "GET",
|
15
|
+
:params => { "page" => 2, "query" => "lorem" },
|
16
|
+
"rack.session" => { "session" => "data", "user_id" => 123 },
|
17
|
+
"HTTP_X_REQUEST_START" => "t=#{queue_start_time.to_i}" # in milliseconds
|
18
|
+
)
|
19
|
+
end
|
20
|
+
let(:server) { Puma::Server.new }
|
21
|
+
let(:error) { ExampleException.new("error message") }
|
22
|
+
around { |example| keep_transactions { example.run } }
|
23
|
+
before { Appsignal::Hooks::PumaHook.new.install }
|
24
|
+
|
25
|
+
def lowlevel_error(error, env, status = nil)
|
26
|
+
result =
|
27
|
+
if status
|
28
|
+
server.lowlevel_error(error, env, status)
|
29
|
+
else
|
30
|
+
server.lowlevel_error(error, env)
|
31
|
+
end
|
32
|
+
# Transaction is normally closed by the EventHandler's RACK_AFTER_REPLY hook
|
33
|
+
last_transaction&.complete
|
34
|
+
result
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "error reporting" do
|
38
|
+
let(:puma_server) { default_puma_server_mock }
|
39
|
+
|
40
|
+
context "with active transaction" do
|
41
|
+
before { create_transaction }
|
42
|
+
|
43
|
+
it "reports the error to the transaction" do
|
44
|
+
expect do
|
45
|
+
lowlevel_error(error, env)
|
46
|
+
end.to_not(change { created_transactions.count })
|
47
|
+
|
48
|
+
expect(last_transaction).to have_error("ExampleException", "error message")
|
49
|
+
expect(last_transaction).to include_tags("reported_by" => "puma_lowlevel_error")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# This shouldn't happen if the EventHandler is set up correctly, but if
|
54
|
+
# it's not it will create a new transaction.
|
55
|
+
context "without active transaction" do
|
56
|
+
it "creates a new transaction with the error" do
|
57
|
+
expect do
|
58
|
+
lowlevel_error(error, env)
|
59
|
+
end.to change { created_transactions.count }.by(1)
|
60
|
+
|
61
|
+
expect(last_transaction).to have_error("ExampleException", "error message")
|
62
|
+
expect(last_transaction).to include_tags("reported_by" => "puma_lowlevel_error")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "doesn't report internal Puma errors" do
|
67
|
+
expect do
|
68
|
+
lowlevel_error(Puma::MiniSSL::SSLError.new("error message"), env)
|
69
|
+
lowlevel_error(Puma::HttpParserError.new("error message"), env)
|
70
|
+
lowlevel_error(Puma::HttpParserError501.new("error message"), env)
|
71
|
+
end.to_not(change { created_transactions.count })
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "request metadata" do
|
75
|
+
it "sets request metadata" do
|
76
|
+
lowlevel_error(error, env)
|
77
|
+
|
78
|
+
expect(last_transaction).to include_metadata(
|
79
|
+
"request_method" => "GET",
|
80
|
+
"method" => "GET",
|
81
|
+
"request_path" => "/some/path",
|
82
|
+
"path" => "/some/path"
|
83
|
+
)
|
84
|
+
expect(last_transaction).to include_environment(
|
85
|
+
"REQUEST_METHOD" => "GET",
|
86
|
+
"PATH_INFO" => "/some/path"
|
87
|
+
# and more, but we don't need to test Rack mock defaults
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "sets request parameters" do
|
92
|
+
lowlevel_error(error, env)
|
93
|
+
|
94
|
+
expect(last_transaction).to include_params(
|
95
|
+
"page" => "2",
|
96
|
+
"query" => "lorem"
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "sets session data" do
|
101
|
+
lowlevel_error(error, env)
|
102
|
+
|
103
|
+
expect(last_transaction).to include_session_data("session" => "data", "user_id" => 123)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "sets the queue start" do
|
107
|
+
lowlevel_error(error, env)
|
108
|
+
|
109
|
+
expect(last_transaction).to have_queue_start(queue_start_time)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "with Puma::Server#lowlevel_error accepting 3 arguments" do
|
115
|
+
let(:puma_server) { default_puma_server_mock }
|
116
|
+
|
117
|
+
it "calls the super class with 3 arguments" do
|
118
|
+
result = lowlevel_error(error, env, 501)
|
119
|
+
expect(result).to eq([501, {}, ""])
|
120
|
+
|
121
|
+
expect(last_transaction).to include_tags("response_status" => 501)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "with Puma::Server#lowlevel_error accepting 2 arguments" do
|
126
|
+
let(:puma_server) do
|
127
|
+
Class.new do
|
128
|
+
def lowlevel_error(_error, _env)
|
129
|
+
[500, {}, ""]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "calls the super class with 3 arguments" do
|
135
|
+
result = lowlevel_error(error, env)
|
136
|
+
expect(result).to eq([500, {}, ""])
|
137
|
+
|
138
|
+
expect(last_transaction).to include_tags("response_status" => 500)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def default_puma_server_mock
|
144
|
+
Class.new do
|
145
|
+
def lowlevel_error(_error, _env, status = 500)
|
146
|
+
[status, {}, ""]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -244,12 +244,7 @@ describe Appsignal::Probes do
|
|
244
244
|
end
|
245
245
|
|
246
246
|
describe ".unregister" do
|
247
|
-
|
248
|
-
let(:log) { log_contents(log_stream) }
|
249
|
-
before do
|
250
|
-
Appsignal.internal_logger = test_logger(log_stream)
|
251
|
-
speed_up_tests!
|
252
|
-
end
|
247
|
+
before { speed_up_tests! }
|
253
248
|
|
254
249
|
it "does not call the initialized probe after unregistering" do
|
255
250
|
probe1_calls = 0
|
@@ -1,19 +1,8 @@
|
|
1
1
|
describe Appsignal::Rack::AbstractMiddleware do
|
2
|
-
class HashLike < Hash
|
3
|
-
def initialize(value)
|
4
|
-
@value = value
|
5
|
-
end
|
6
|
-
|
7
|
-
def to_h
|
8
|
-
@value
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
2
|
let(:app) { DummyApp.new }
|
13
|
-
let(:request_path) { "/some/path" }
|
14
3
|
let(:env) do
|
15
4
|
Rack::MockRequest.env_for(
|
16
|
-
|
5
|
+
"/some/path",
|
17
6
|
"REQUEST_METHOD" => "GET",
|
18
7
|
:params => { "page" => 2, "query" => "lorem" },
|
19
8
|
"rack.session" => { "session" => "data", "user_id" => 123 }
|
@@ -174,13 +163,17 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
174
163
|
end
|
175
164
|
end
|
176
165
|
|
166
|
+
# Partial duplicate tests from Appsignal::Rack::ApplyRackRequest that
|
167
|
+
# ensure the request metadata is set on via the AbstractMiddleware.
|
177
168
|
describe "request metadata" do
|
178
169
|
it "sets request metadata" do
|
179
170
|
env.merge!("PATH_INFO" => "/some/path", "REQUEST_METHOD" => "GET")
|
180
171
|
make_request
|
181
172
|
|
182
173
|
expect(last_transaction).to include_metadata(
|
174
|
+
"request_method" => "GET",
|
183
175
|
"method" => "GET",
|
176
|
+
"request_path" => "/some/path",
|
184
177
|
"path" => "/some/path"
|
185
178
|
)
|
186
179
|
expect(last_transaction).to include_environment(
|
@@ -190,36 +183,6 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
190
183
|
)
|
191
184
|
end
|
192
185
|
|
193
|
-
context "with an invalid HTTP request method" do
|
194
|
-
it "stores the invalid HTTP request method" do
|
195
|
-
env["REQUEST_METHOD"] = "FOO"
|
196
|
-
make_request
|
197
|
-
|
198
|
-
expect(last_transaction).to include_metadata("method" => "FOO")
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
context "when fetching the request method raises an error" do
|
203
|
-
class BrokenRequestMethodRequest < Rack::Request
|
204
|
-
def request_method
|
205
|
-
raise "uh oh!"
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
let(:options) { { :request_class => BrokenRequestMethodRequest } }
|
210
|
-
|
211
|
-
it "does not store the invalid HTTP request method" do
|
212
|
-
env["REQUEST_METHOD"] = "FOO"
|
213
|
-
logs = capture_logs { make_request }
|
214
|
-
|
215
|
-
expect(last_transaction).to_not include_metadata("method" => anything)
|
216
|
-
expect(logs).to contains_log(
|
217
|
-
:error,
|
218
|
-
"Exception while fetching the HTTP request method: RuntimeError: uh oh"
|
219
|
-
)
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
186
|
it "sets request parameters" do
|
224
187
|
make_request
|
225
188
|
|
@@ -229,107 +192,63 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
229
192
|
)
|
230
193
|
end
|
231
194
|
|
232
|
-
context "when setting custom params" do
|
233
|
-
let(:app) do
|
234
|
-
DummyApp.new do |_env|
|
235
|
-
Appsignal::Transaction.current.set_params("custom" => "param")
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
it "allow custom request parameters to be set" do
|
240
|
-
make_request
|
241
|
-
|
242
|
-
expect(last_transaction).to include_params("custom" => "param")
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
context "when fetching the request method raises an error" do
|
247
|
-
class BrokenRequestParamsRequest < Rack::Request
|
248
|
-
def params
|
249
|
-
raise "uh oh!"
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
let(:options) do
|
254
|
-
{ :request_class => BrokenRequestParamsRequest, :params_method => :params }
|
255
|
-
end
|
256
|
-
|
257
|
-
it "does not store the invalid HTTP request method" do
|
258
|
-
logs = capture_logs { make_request }
|
259
|
-
|
260
|
-
expect(last_transaction).to_not include_params
|
261
|
-
expect(logs).to contains_log(
|
262
|
-
:error,
|
263
|
-
"Exception while fetching params " \
|
264
|
-
"from 'BrokenRequestParamsRequest#params': RuntimeError uh oh!"
|
265
|
-
)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
195
|
it "sets session data" do
|
270
196
|
make_request
|
271
197
|
|
272
198
|
expect(last_transaction).to include_session_data("session" => "data", "user_id" => 123)
|
273
199
|
end
|
274
200
|
|
275
|
-
|
276
|
-
|
277
|
-
make_request
|
278
|
-
|
279
|
-
expect(last_transaction).to include_session_data("hash-like" => "value", "user_id" => 123)
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
context "with queue start header" do
|
284
|
-
let(:queue_start_time) { fixed_time * 1_000 }
|
201
|
+
context "with queue start header" do
|
202
|
+
let(:queue_start_time) { fixed_time * 1_000 }
|
285
203
|
|
286
|
-
|
287
|
-
|
288
|
-
|
204
|
+
it "sets the queue start" do
|
205
|
+
env["HTTP_X_REQUEST_START"] = "t=#{queue_start_time.to_i}" # in milliseconds
|
206
|
+
make_request
|
289
207
|
|
290
|
-
|
208
|
+
expect(last_transaction).to have_queue_start(queue_start_time)
|
209
|
+
end
|
291
210
|
end
|
292
|
-
end
|
293
211
|
|
294
|
-
|
295
|
-
|
212
|
+
class SomeFilteredRequest
|
213
|
+
attr_reader :env
|
296
214
|
|
297
|
-
|
298
|
-
|
299
|
-
|
215
|
+
def initialize(env)
|
216
|
+
@env = env
|
217
|
+
end
|
300
218
|
|
301
|
-
|
302
|
-
|
303
|
-
|
219
|
+
def path
|
220
|
+
"/static/path"
|
221
|
+
end
|
304
222
|
|
305
|
-
|
306
|
-
|
307
|
-
|
223
|
+
def request_method
|
224
|
+
"GET"
|
225
|
+
end
|
308
226
|
|
309
|
-
|
310
|
-
|
311
|
-
|
227
|
+
def filtered_params
|
228
|
+
{ "abc" => "123" }
|
229
|
+
end
|
312
230
|
|
313
|
-
|
314
|
-
|
231
|
+
def session
|
232
|
+
{ "data" => "value" }
|
233
|
+
end
|
315
234
|
end
|
316
|
-
end
|
317
235
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
236
|
+
context "with overridden request class and params method" do
|
237
|
+
let(:options) do
|
238
|
+
{ :request_class => SomeFilteredRequest, :params_method => :filtered_params }
|
239
|
+
end
|
322
240
|
|
323
|
-
|
324
|
-
|
241
|
+
it "uses the overridden request class and params method to fetch params" do
|
242
|
+
make_request
|
325
243
|
|
326
|
-
|
327
|
-
|
244
|
+
expect(last_transaction).to include_params("abc" => "123")
|
245
|
+
end
|
328
246
|
|
329
|
-
|
330
|
-
|
247
|
+
it "uses the overridden request class to fetch session data" do
|
248
|
+
make_request
|
331
249
|
|
332
|
-
|
250
|
+
expect(last_transaction).to include_session_data("data" => "value")
|
251
|
+
end
|
333
252
|
end
|
334
253
|
end
|
335
254
|
|
@@ -5,23 +5,29 @@ describe Appsignal::Rack::BodyWrapper do
|
|
5
5
|
set_current_transaction(transaction)
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
it "forwards method calls to the body if the method doesn't exist" do
|
9
|
+
fake_body = double(
|
10
|
+
:body => ["some body"],
|
11
|
+
:some_method => :some_value
|
12
|
+
)
|
13
|
+
|
14
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
15
|
+
expect(wrapped).to respond_to(:body)
|
16
|
+
expect(wrapped.body).to eq(["some body"])
|
17
|
+
|
18
|
+
expect(wrapped).to respond_to(:some_method)
|
19
|
+
expect(wrapped.some_method).to eq(:some_value)
|
20
|
+
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
it "doesn't respond to methods the Rack::BodyProxy doesn't respond to" do
|
23
|
+
body = Rack::BodyProxy.new(["body"])
|
24
|
+
wrapped = described_class.wrap(body, transaction)
|
25
|
+
|
26
|
+
expect(wrapped).to_not respond_to(:to_str)
|
27
|
+
expect { wrapped.to_str }.to raise_error(NoMethodError)
|
28
|
+
|
29
|
+
expect(wrapped).to_not respond_to(:body)
|
30
|
+
expect { wrapped.body }.to raise_error(NoMethodError)
|
25
31
|
end
|
26
32
|
|
27
33
|
describe "with a body only supporting each()" do
|
@@ -97,15 +103,17 @@ describe Appsignal::Rack::BodyWrapper do
|
|
97
103
|
end
|
98
104
|
|
99
105
|
describe "with a body supporting both each() and call" do
|
100
|
-
it "wraps with the wrapper that
|
101
|
-
fake_body = double
|
102
|
-
|
103
|
-
|
106
|
+
it "wraps with the wrapper that exposes each" do
|
107
|
+
fake_body = double(
|
108
|
+
:each => true,
|
109
|
+
:call => "original call"
|
110
|
+
)
|
104
111
|
|
105
112
|
wrapped = described_class.wrap(fake_body, transaction)
|
106
113
|
expect(wrapped).to respond_to(:each)
|
107
114
|
expect(wrapped).to_not respond_to(:to_ary)
|
108
|
-
expect(wrapped).
|
115
|
+
expect(wrapped).to respond_to(:call)
|
116
|
+
expect(wrapped.call).to eq("original call")
|
109
117
|
expect(wrapped).to_not respond_to(:to_path)
|
110
118
|
expect(wrapped).to respond_to(:close)
|
111
119
|
end
|
@@ -61,3 +61,183 @@ describe Appsignal::Rack::Utils do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
64
|
+
|
65
|
+
describe Appsignal::Rack::ApplyRackRequest do
|
66
|
+
describe "#apply_to" do
|
67
|
+
let(:merged_env) do
|
68
|
+
Rack::MockRequest.env_for(
|
69
|
+
"/some/path",
|
70
|
+
{
|
71
|
+
"REQUEST_METHOD" => "GET",
|
72
|
+
:params => { "page" => 2, "query" => "lorem" },
|
73
|
+
"rack.session" => { "session" => "data", "user_id" => 123 }
|
74
|
+
}.merge(env)
|
75
|
+
)
|
76
|
+
end
|
77
|
+
let(:env) { {} }
|
78
|
+
let(:request) { ::Rack::Request.new(merged_env) }
|
79
|
+
let(:options) { {} }
|
80
|
+
let(:helper) { described_class.new(request, options) }
|
81
|
+
let(:transaction) { http_request_transaction }
|
82
|
+
before { start_agent }
|
83
|
+
|
84
|
+
def apply_to(transaction)
|
85
|
+
helper.apply_to(transaction)
|
86
|
+
transaction._sample
|
87
|
+
end
|
88
|
+
|
89
|
+
it "sets request metadata" do
|
90
|
+
apply_to(transaction)
|
91
|
+
|
92
|
+
expect(transaction).to include_metadata(
|
93
|
+
"method" => "GET",
|
94
|
+
"path" => "/some/path"
|
95
|
+
)
|
96
|
+
expect(transaction).to include_environment(
|
97
|
+
"REQUEST_METHOD" => "GET",
|
98
|
+
"PATH_INFO" => "/some/path"
|
99
|
+
# and more, but we don't need to test Rack mock defaults
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
context "with an invalid HTTP request method" do
|
104
|
+
let(:env) { { "REQUEST_METHOD" => "FOO" } }
|
105
|
+
|
106
|
+
it "stores the invalid HTTP request method" do
|
107
|
+
apply_to(transaction)
|
108
|
+
|
109
|
+
expect(transaction).to include_metadata("method" => "FOO")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when fetching the request method raises an error" do
|
114
|
+
class BrokenRequestMethodRequest < Rack::Request
|
115
|
+
def request_method
|
116
|
+
raise "uh oh!"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
let(:env) { { "REQUEST_METHOD" => "FOO" } }
|
121
|
+
let(:request) { BrokenRequestMethodRequest.new(merged_env) }
|
122
|
+
|
123
|
+
it "does not store the invalid HTTP request method" do
|
124
|
+
logs = capture_logs { apply_to(transaction) }
|
125
|
+
|
126
|
+
expect(transaction).to_not include_metadata("method" => anything)
|
127
|
+
expect(logs).to contains_log(
|
128
|
+
:error,
|
129
|
+
"Exception while fetching the HTTP request method: RuntimeError: uh oh"
|
130
|
+
)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "sets request parameters" do
|
135
|
+
apply_to(transaction)
|
136
|
+
|
137
|
+
expect(transaction).to include_params(
|
138
|
+
"page" => "2",
|
139
|
+
"query" => "lorem"
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
context "when params_method isn't set" do
|
144
|
+
let(:options) { { :params_method => nil } }
|
145
|
+
|
146
|
+
it "reports no params" do
|
147
|
+
apply_to(transaction)
|
148
|
+
|
149
|
+
expect(transaction).to_not include_params
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "when fetching the request method raises an error" do
|
154
|
+
class BrokenRequestParamsRequest < Rack::Request
|
155
|
+
def params
|
156
|
+
raise "uh oh!"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
let(:request) { BrokenRequestParamsRequest.new(merged_env) }
|
161
|
+
let(:options) { { :params_method => :params } }
|
162
|
+
|
163
|
+
it "does not store the invalid HTTP request method" do
|
164
|
+
logs = capture_logs { apply_to(transaction) }
|
165
|
+
|
166
|
+
expect(transaction).to_not include_params
|
167
|
+
expect(logs).to contains_log(
|
168
|
+
:error,
|
169
|
+
"Exception while fetching params " \
|
170
|
+
"from 'BrokenRequestParamsRequest#params': RuntimeError uh oh!"
|
171
|
+
)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
it "sets session data" do
|
176
|
+
apply_to(transaction)
|
177
|
+
|
178
|
+
expect(transaction).to include_session_data("session" => "data", "user_id" => 123)
|
179
|
+
end
|
180
|
+
|
181
|
+
context "with Hash-like session data" do
|
182
|
+
let(:env) { { "rack.session" => HashLike.new("hash-like" => "value", "user_id" => 123) } }
|
183
|
+
|
184
|
+
it "sets session data" do
|
185
|
+
apply_to(transaction)
|
186
|
+
|
187
|
+
expect(transaction).to include_session_data("hash-like" => "value", "user_id" => 123)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "with queue start header" do
|
192
|
+
let(:queue_start_time) { fixed_time * 1_000 }
|
193
|
+
let(:env) { { "HTTP_X_REQUEST_START" => "t=#{queue_start_time.to_i}" } } # in milliseconds
|
194
|
+
|
195
|
+
it "sets the queue start" do
|
196
|
+
apply_to(transaction)
|
197
|
+
|
198
|
+
expect(transaction).to have_queue_start(queue_start_time)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class RackFilteredRequest
|
203
|
+
attr_reader :env
|
204
|
+
|
205
|
+
def initialize(env)
|
206
|
+
@env = env
|
207
|
+
end
|
208
|
+
|
209
|
+
def path
|
210
|
+
"/static/path"
|
211
|
+
end
|
212
|
+
|
213
|
+
def request_method
|
214
|
+
"GET"
|
215
|
+
end
|
216
|
+
|
217
|
+
def filtered_params
|
218
|
+
{ "abc" => "123" }
|
219
|
+
end
|
220
|
+
|
221
|
+
def session
|
222
|
+
{ "data" => "value" }
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context "with overridden request class and params method" do
|
227
|
+
let(:request) { RackFilteredRequest.new(env) }
|
228
|
+
let(:options) { { :params_method => :filtered_params } }
|
229
|
+
|
230
|
+
it "uses the overridden request class and params method to fetch params" do
|
231
|
+
apply_to(transaction)
|
232
|
+
|
233
|
+
expect(transaction).to include_params("abc" => "123")
|
234
|
+
end
|
235
|
+
|
236
|
+
it "uses the overridden request class to fetch session data" do
|
237
|
+
apply_to(transaction)
|
238
|
+
|
239
|
+
expect(transaction).to include_session_data("data" => "value")
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|