appsignal 3.9.3-java → 3.10.0-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/.github/workflows/ci.yml +22 -19
- data/CHANGELOG.md +92 -0
- data/README.md +0 -1
- data/Rakefile +1 -1
- data/build_matrix.yml +10 -12
- data/gemfiles/webmachine1.gemfile +5 -4
- data/lib/appsignal/config.rb +4 -0
- data/lib/appsignal/environment.rb +6 -1
- data/lib/appsignal/helpers/instrumentation.rb +163 -1
- data/lib/appsignal/hooks/active_job.rb +1 -6
- data/lib/appsignal/integrations/padrino.rb +21 -25
- data/lib/appsignal/integrations/rake.rb +46 -12
- data/lib/appsignal/integrations/sidekiq.rb +1 -11
- data/lib/appsignal/integrations/webmachine.rb +15 -9
- data/lib/appsignal/rack/abstract_middleware.rb +49 -12
- data/lib/appsignal/rack/body_wrapper.rb +143 -0
- data/lib/appsignal/rack/generic_instrumentation.rb +5 -4
- data/lib/appsignal/rack/grape_middleware.rb +1 -1
- data/lib/appsignal/rack/hanami_middleware.rb +1 -1
- data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +1 -3
- data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -3
- data/lib/appsignal/rack/streaming_listener.rb +13 -59
- data/lib/appsignal/rack.rb +31 -0
- data/lib/appsignal/transaction.rb +50 -8
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +3 -1
- data/spec/lib/appsignal/config_spec.rb +1 -0
- data/spec/lib/appsignal/hooks/rake_spec.rb +100 -17
- data/spec/lib/appsignal/integrations/padrino_spec.rb +181 -131
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -2
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +65 -17
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +96 -8
- data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -17
- data/spec/lib/appsignal/rack/grape_middleware_spec.rb +1 -1
- data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +43 -120
- data/spec/lib/appsignal/transaction_spec.rb +163 -4
- data/spec/lib/appsignal_spec.rb +197 -6
- data/spec/support/mocks/dummy_app.rb +1 -1
- metadata +8 -4
- data/support/check_versions +0 -22
@@ -45,6 +45,11 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
45
45
|
expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
46
46
|
end
|
47
47
|
|
48
|
+
it "wraps the response body in a BodyWrapper subclass" do
|
49
|
+
_status, _headers, body = make_request
|
50
|
+
expect(body).to be_kind_of(Appsignal::Rack::BodyWrapper)
|
51
|
+
end
|
52
|
+
|
48
53
|
context "without an error" do
|
49
54
|
before { make_request }
|
50
55
|
|
@@ -56,8 +61,20 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
56
61
|
expect(last_transaction).to_not have_error
|
57
62
|
end
|
58
63
|
|
59
|
-
|
60
|
-
|
64
|
+
context "without :instrument_event_name option set" do
|
65
|
+
let(:options) { {} }
|
66
|
+
|
67
|
+
it "does not record an instrumentation event" do
|
68
|
+
expect(last_transaction).to_not include_event
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "with :instrument_event_name option set" do
|
73
|
+
let(:options) { { :instrument_event_name => "event_name.category" } }
|
74
|
+
|
75
|
+
it "records an instrumentation event" do
|
76
|
+
expect(last_transaction).to include_event(:name => "event_name.category")
|
77
|
+
end
|
61
78
|
end
|
62
79
|
|
63
80
|
it "completes the transaction" do
|
@@ -66,8 +83,8 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
66
83
|
.to be_kind_of(Appsignal::Transaction::NilTransaction)
|
67
84
|
end
|
68
85
|
|
69
|
-
context "when
|
70
|
-
let(:options) { { :
|
86
|
+
context "when instrument_event_name option is nil" do
|
87
|
+
let(:options) { { :instrument_event_name => nil } }
|
71
88
|
|
72
89
|
it "does not record an instrumentation event" do
|
73
90
|
expect(last_transaction).to_not include_events
|
@@ -148,21 +165,61 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
148
165
|
end
|
149
166
|
|
150
167
|
context "with appsignal.route env" do
|
168
|
+
before { env["appsignal.route"] = "POST /my-route" }
|
169
|
+
|
151
170
|
it "reports the appsignal.route value as the action name" do
|
152
|
-
env["appsignal.route"] = "POST /my-route"
|
153
171
|
make_request
|
154
172
|
|
155
173
|
expect(last_transaction).to have_action("POST /my-route")
|
156
174
|
end
|
175
|
+
|
176
|
+
it "prints a deprecation warning" do
|
177
|
+
err_stream = std_stream
|
178
|
+
capture_std_streams(std_stream, err_stream) do
|
179
|
+
make_request
|
180
|
+
end
|
181
|
+
|
182
|
+
expect(err_stream.read).to include(
|
183
|
+
"Setting the action name with the request env 'appsignal.route' is deprecated."
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "logs a deprecation warning" do
|
188
|
+
logs = capture_logs { make_request }
|
189
|
+
expect(logs).to contains_log(
|
190
|
+
:warn,
|
191
|
+
"Setting the action name with the request env 'appsignal.route' is deprecated."
|
192
|
+
)
|
193
|
+
end
|
157
194
|
end
|
158
195
|
|
159
196
|
context "with appsignal.action env" do
|
160
|
-
|
161
|
-
|
197
|
+
before { env["appsignal.action"] = "POST /my-action" }
|
198
|
+
|
199
|
+
it "reports the appsignal.action value as the action name" do
|
162
200
|
make_request
|
163
201
|
|
164
202
|
expect(last_transaction).to have_action("POST /my-action")
|
165
203
|
end
|
204
|
+
|
205
|
+
it "prints a deprecation warning" do
|
206
|
+
err_stream = std_stream
|
207
|
+
capture_std_streams(std_stream, err_stream) do
|
208
|
+
make_request
|
209
|
+
end
|
210
|
+
|
211
|
+
expect(err_stream.read).to include(
|
212
|
+
"Setting the action name with the request env 'appsignal.action' is deprecated."
|
213
|
+
)
|
214
|
+
end
|
215
|
+
|
216
|
+
it "logs a deprecation warning" do
|
217
|
+
logs = capture_logs { make_request }
|
218
|
+
expect(logs).to contains_log(
|
219
|
+
:warn,
|
220
|
+
"Setting the action name with the request env 'appsignal.action' is deprecated."
|
221
|
+
)
|
222
|
+
end
|
166
223
|
end
|
167
224
|
|
168
225
|
describe "request metadata" do
|
@@ -274,8 +331,10 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
274
331
|
end
|
275
332
|
|
276
333
|
context "with parent instrumentation" do
|
334
|
+
let(:transaction) { http_request_transaction }
|
277
335
|
before do
|
278
|
-
env[Appsignal::Rack::APPSIGNAL_TRANSACTION] =
|
336
|
+
env[Appsignal::Rack::APPSIGNAL_TRANSACTION] = transaction
|
337
|
+
set_current_transaction(transaction)
|
279
338
|
end
|
280
339
|
|
281
340
|
it "uses the existing transaction" do
|
@@ -284,6 +343,35 @@ describe Appsignal::Rack::AbstractMiddleware do
|
|
284
343
|
expect { make_request }.to_not(change { created_transactions.count })
|
285
344
|
end
|
286
345
|
|
346
|
+
it "wraps the response body in a BodyWrapper subclass" do
|
347
|
+
_status, _headers, body = make_request
|
348
|
+
expect(body).to be_kind_of(Appsignal::Rack::BodyWrapper)
|
349
|
+
|
350
|
+
body.to_ary
|
351
|
+
response_events =
|
352
|
+
last_transaction.to_h["events"].count do |event|
|
353
|
+
event["name"] == "process_response_body.rack"
|
354
|
+
end
|
355
|
+
expect(response_events).to eq(1)
|
356
|
+
end
|
357
|
+
|
358
|
+
context "when response body is already a BodyWrapper subclass" do
|
359
|
+
let(:body) { Appsignal::Rack::BodyWrapper.wrap(["hello!"], transaction) }
|
360
|
+
let(:app) { DummyApp.new { [200, {}, body] } }
|
361
|
+
|
362
|
+
it "doesn't wrap the body again" do
|
363
|
+
_status, _headers, body = make_request
|
364
|
+
expect(body).to eq(body)
|
365
|
+
|
366
|
+
body.to_ary
|
367
|
+
response_events =
|
368
|
+
last_transaction.to_h["events"].count do |event|
|
369
|
+
event["name"] == "process_response_body.rack"
|
370
|
+
end
|
371
|
+
expect(response_events).to eq(1)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
287
375
|
context "with error" do
|
288
376
|
let(:app) { lambda { |_env| raise ExampleException, "error message" } }
|
289
377
|
|
@@ -0,0 +1,263 @@
|
|
1
|
+
describe Appsignal::Rack::BodyWrapper do
|
2
|
+
let(:transaction) { http_request_transaction }
|
3
|
+
before do
|
4
|
+
start_agent
|
5
|
+
set_current_transaction(transaction)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "with a body that supports all possible features" do
|
9
|
+
it "reduces the supported methods to just each()" do
|
10
|
+
# which is the safest thing to do, since the body is likely broken
|
11
|
+
fake_body = double(
|
12
|
+
:each => nil,
|
13
|
+
:call => nil,
|
14
|
+
:to_ary => [],
|
15
|
+
:to_path => "/tmp/foo.bin",
|
16
|
+
:close => nil
|
17
|
+
)
|
18
|
+
|
19
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
20
|
+
expect(wrapped).to respond_to(:each)
|
21
|
+
expect(wrapped).to_not respond_to(:to_ary)
|
22
|
+
expect(wrapped).to_not respond_to(:call)
|
23
|
+
expect(wrapped).to respond_to(:close)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "with a body only supporting each()" do
|
28
|
+
it "wraps with appropriate class" do
|
29
|
+
fake_body = double(:each => nil)
|
30
|
+
|
31
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
32
|
+
expect(wrapped).to respond_to(:each)
|
33
|
+
expect(wrapped).to_not respond_to(:to_ary)
|
34
|
+
expect(wrapped).to_not respond_to(:call)
|
35
|
+
expect(wrapped).to respond_to(:close)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "reads out the body in full using each" do
|
39
|
+
fake_body = double
|
40
|
+
expect(fake_body).to receive(:each).once.and_yield("a").and_yield("b").and_yield("c")
|
41
|
+
|
42
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
43
|
+
expect { |b| wrapped.each(&b) }.to yield_successive_args("a", "b", "c")
|
44
|
+
|
45
|
+
expect(transaction).to include_event(
|
46
|
+
"name" => "process_response_body.rack",
|
47
|
+
"title" => "Process Rack response body (#each)"
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns an Enumerator if each() gets called without a block" do
|
52
|
+
fake_body = double
|
53
|
+
expect(fake_body).to receive(:each).once.and_yield("a").and_yield("b").and_yield("c")
|
54
|
+
|
55
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
56
|
+
enum = wrapped.each
|
57
|
+
expect(enum).to be_kind_of(Enumerator)
|
58
|
+
expect { |b| enum.each(&b) }.to yield_successive_args("a", "b", "c")
|
59
|
+
|
60
|
+
expect(transaction).to_not include_event("name" => "process_response_body.rack")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "sets the exception raised inside each() on the transaction" do
|
64
|
+
fake_body = double
|
65
|
+
expect(fake_body).to receive(:each).once.and_raise(ExampleException, "error message")
|
66
|
+
|
67
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
68
|
+
expect do
|
69
|
+
expect { |b| wrapped.each(&b) }.to yield_control
|
70
|
+
end.to raise_error(ExampleException, "error message")
|
71
|
+
|
72
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "closes the body and tracks an instrumentation event when it gets closed" do
|
76
|
+
fake_body = double(:close => nil)
|
77
|
+
expect(fake_body).to receive(:each).once.and_yield("a").and_yield("b").and_yield("c")
|
78
|
+
|
79
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
80
|
+
expect { |b| wrapped.each(&b) }.to yield_successive_args("a", "b", "c")
|
81
|
+
wrapped.close
|
82
|
+
|
83
|
+
expect(transaction).to include_event("name" => "close_response_body.rack")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "with a body supporting both each() and call" do
|
88
|
+
it "wraps with the wrapper that conceals call() and exposes each" do
|
89
|
+
fake_body = double
|
90
|
+
allow(fake_body).to receive(:each)
|
91
|
+
allow(fake_body).to receive(:call)
|
92
|
+
|
93
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
94
|
+
expect(wrapped).to respond_to(:each)
|
95
|
+
expect(wrapped).to_not respond_to(:to_ary)
|
96
|
+
expect(wrapped).to_not respond_to(:call)
|
97
|
+
expect(wrapped).to_not respond_to(:to_path)
|
98
|
+
expect(wrapped).to respond_to(:close)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "with a body supporting both to_ary and each" do
|
103
|
+
let(:fake_body) { double(:each => nil, :to_ary => []) }
|
104
|
+
|
105
|
+
it "wraps with appropriate class" do
|
106
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
107
|
+
expect(wrapped).to respond_to(:each)
|
108
|
+
expect(wrapped).to respond_to(:to_ary)
|
109
|
+
expect(wrapped).to_not respond_to(:call)
|
110
|
+
expect(wrapped).to_not respond_to(:to_path)
|
111
|
+
expect(wrapped).to respond_to(:close)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "reads out the body in full using each" do
|
115
|
+
expect(fake_body).to receive(:each).once.and_yield("a").and_yield("b").and_yield("c")
|
116
|
+
|
117
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
118
|
+
expect { |b| wrapped.each(&b) }.to yield_successive_args("a", "b", "c")
|
119
|
+
|
120
|
+
expect(transaction).to include_event(
|
121
|
+
"name" => "process_response_body.rack",
|
122
|
+
"title" => "Process Rack response body (#each)"
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "sets the exception raised inside each() into the Appsignal transaction" do
|
127
|
+
expect(fake_body).to receive(:each).once.and_raise(ExampleException, "error message")
|
128
|
+
|
129
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
130
|
+
expect do
|
131
|
+
expect { |b| wrapped.each(&b) }.to yield_control
|
132
|
+
end.to raise_error(ExampleException, "error message")
|
133
|
+
|
134
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
135
|
+
end
|
136
|
+
|
137
|
+
it "reads out the body in full using to_ary" do
|
138
|
+
expect(fake_body).to receive(:to_ary).and_return(["one", "two", "three"])
|
139
|
+
|
140
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
141
|
+
expect(wrapped.to_ary).to eq(["one", "two", "three"])
|
142
|
+
|
143
|
+
expect(transaction).to include_event(
|
144
|
+
"name" => "process_response_body.rack",
|
145
|
+
"title" => "Process Rack response body (#to_ary)"
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "sends the exception raised inside to_ary() into the Appsignal and closes transaction" do
|
150
|
+
fake_body = double
|
151
|
+
allow(fake_body).to receive(:each)
|
152
|
+
expect(fake_body).to receive(:to_ary).once.and_raise(ExampleException, "error message")
|
153
|
+
expect(fake_body).to_not receive(:close) # Per spec we expect the body has closed itself
|
154
|
+
|
155
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
156
|
+
expect do
|
157
|
+
wrapped.to_ary
|
158
|
+
end.to raise_error(ExampleException, "error message")
|
159
|
+
|
160
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "with a body supporting both to_path and each" do
|
165
|
+
let(:fake_body) { double(:each => nil, :to_path => nil) }
|
166
|
+
|
167
|
+
it "wraps with appropriate class" do
|
168
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
169
|
+
expect(wrapped).to respond_to(:each)
|
170
|
+
expect(wrapped).to_not respond_to(:to_ary)
|
171
|
+
expect(wrapped).to_not respond_to(:call)
|
172
|
+
expect(wrapped).to respond_to(:to_path)
|
173
|
+
expect(wrapped).to respond_to(:close)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "reads out the body in full using each()" do
|
177
|
+
expect(fake_body).to receive(:each).once.and_yield("a").and_yield("b").and_yield("c")
|
178
|
+
|
179
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
180
|
+
expect { |b| wrapped.each(&b) }.to yield_successive_args("a", "b", "c")
|
181
|
+
|
182
|
+
expect(transaction).to include_event(
|
183
|
+
"name" => "process_response_body.rack",
|
184
|
+
"title" => "Process Rack response body (#each)"
|
185
|
+
)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "sets the exception raised inside each() into the Appsignal transaction" do
|
189
|
+
expect(fake_body).to receive(:each).once.and_raise(ExampleException, "error message")
|
190
|
+
|
191
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
192
|
+
expect do
|
193
|
+
expect { |b| wrapped.each(&b) }.to yield_control
|
194
|
+
end.to raise_error(ExampleException, "error message")
|
195
|
+
|
196
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
197
|
+
end
|
198
|
+
|
199
|
+
it "sets the exception raised inside to_path() into the Appsignal transaction" do
|
200
|
+
allow(fake_body).to receive(:to_path).once.and_raise(ExampleException, "error message")
|
201
|
+
|
202
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
203
|
+
expect do
|
204
|
+
wrapped.to_path
|
205
|
+
end.to raise_error(ExampleException, "error message")
|
206
|
+
|
207
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
208
|
+
end
|
209
|
+
|
210
|
+
it "exposes to_path to the sender" do
|
211
|
+
allow(fake_body).to receive(:to_path).and_return("/tmp/file.bin")
|
212
|
+
|
213
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
214
|
+
expect(wrapped.to_path).to eq("/tmp/file.bin")
|
215
|
+
|
216
|
+
expect(transaction).to include_event(
|
217
|
+
"name" => "process_response_body.rack",
|
218
|
+
"title" => "Process Rack response body (#to_path)"
|
219
|
+
)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "with a body only supporting call()" do
|
224
|
+
let(:fake_body) { double(:call => nil) }
|
225
|
+
|
226
|
+
it "wraps with appropriate class" do
|
227
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
228
|
+
expect(wrapped).to_not respond_to(:each)
|
229
|
+
expect(wrapped).to_not respond_to(:to_ary)
|
230
|
+
expect(wrapped).to respond_to(:call)
|
231
|
+
expect(wrapped).to_not respond_to(:to_path)
|
232
|
+
expect(wrapped).to respond_to(:close)
|
233
|
+
end
|
234
|
+
|
235
|
+
it "passes the stream into the call() of the body" do
|
236
|
+
fake_rack_stream = double("stream")
|
237
|
+
expect(fake_body).to receive(:call).with(fake_rack_stream)
|
238
|
+
|
239
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
240
|
+
wrapped.call(fake_rack_stream)
|
241
|
+
|
242
|
+
expect(transaction).to include_event(
|
243
|
+
"name" => "process_response_body.rack",
|
244
|
+
"title" => "Process Rack response body (#call)"
|
245
|
+
)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "sets the exception raised inside call() into the Appsignal transaction" do
|
249
|
+
fake_rack_stream = double
|
250
|
+
allow(fake_body).to receive(:call)
|
251
|
+
.with(fake_rack_stream)
|
252
|
+
.and_raise(ExampleException, "error message")
|
253
|
+
|
254
|
+
wrapped = described_class.wrap(fake_body, transaction)
|
255
|
+
|
256
|
+
expect do
|
257
|
+
wrapped.call(fake_rack_stream)
|
258
|
+
end.to raise_error(ExampleException, "error message")
|
259
|
+
|
260
|
+
expect(transaction).to have_error("ExampleException", "error message")
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
@@ -1,28 +1,81 @@
|
|
1
|
-
describe Appsignal::Rack::GenericInstrumentation do
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
describe "Appsignal::Rack::GenericInstrumentation" do
|
2
|
+
describe "Appsignal::Rack::GenericInstrumentation constant" do
|
3
|
+
let(:err_stream) { std_stream }
|
4
|
+
let(:stderr) { err_stream.read }
|
5
|
+
before do
|
6
|
+
if Appsignal::Rack.const_defined?(:GenericInstrumentation)
|
7
|
+
hide_const "Appsignal::Rack::GenericInstrumentation"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns the Rack::GenericInstrumentation constant" do
|
12
|
+
silence do
|
13
|
+
expect(Appsignal::Rack::GenericInstrumentation)
|
14
|
+
.to be(Appsignal::Rack::GenericInstrumentationAlias)
|
15
|
+
end
|
16
|
+
end
|
5
17
|
|
6
|
-
|
7
|
-
|
18
|
+
it "prints a deprecation warning to STDERR" do
|
19
|
+
capture_std_streams(std_stream, err_stream) do
|
20
|
+
Appsignal::Rack::GenericInstrumentation
|
21
|
+
end
|
8
22
|
|
9
|
-
|
10
|
-
|
11
|
-
|
23
|
+
expect(stderr).to include(
|
24
|
+
"appsignal WARNING: The constant Appsignal::Rack::GenericInstrumentation " \
|
25
|
+
"has been deprecated."
|
26
|
+
)
|
27
|
+
end
|
12
28
|
|
13
|
-
|
14
|
-
|
15
|
-
|
29
|
+
it "logs a warning" do
|
30
|
+
logs =
|
31
|
+
capture_logs do
|
32
|
+
silence do
|
33
|
+
Appsignal::Rack::GenericInstrumentation
|
34
|
+
end
|
35
|
+
end
|
16
36
|
|
17
|
-
expect(
|
37
|
+
expect(logs).to contains_log(
|
38
|
+
:warn,
|
39
|
+
"The constant Appsignal::Rack::GenericInstrumentation has been deprecated."
|
40
|
+
)
|
18
41
|
end
|
19
42
|
end
|
20
43
|
|
21
|
-
|
22
|
-
|
23
|
-
|
44
|
+
describe "middleware" do
|
45
|
+
let(:app) { double(:call => true) }
|
46
|
+
let(:env) { Rack::MockRequest.env_for("/some/path") }
|
47
|
+
let(:middleware) { Appsignal::Rack::GenericInstrumentation.new(app, {}) }
|
48
|
+
|
49
|
+
before(:context) { start_agent }
|
50
|
+
around { |example| keep_transactions { example.run } }
|
51
|
+
|
52
|
+
def make_request(env)
|
53
|
+
middleware.call(env)
|
54
|
+
end
|
55
|
+
|
56
|
+
context "without an exception" do
|
57
|
+
it "reports a process_action.generic event" do
|
58
|
+
make_request(env)
|
59
|
+
|
60
|
+
expect(last_transaction).to include_event("name" => "process_action.generic")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "with action name env" do
|
65
|
+
it "reports the appsignal.action env as the action name" do
|
66
|
+
env["appsignal.action"] = "MyAction"
|
67
|
+
make_request(env)
|
68
|
+
|
69
|
+
expect(last_transaction).to have_action("MyAction")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "without action name metadata" do
|
74
|
+
it "reports 'unknown' as the action name" do
|
75
|
+
make_request(env)
|
24
76
|
|
25
|
-
|
77
|
+
expect(last_transaction).to have_action("unknown")
|
78
|
+
end
|
26
79
|
end
|
27
80
|
end
|
28
81
|
end
|
@@ -5,7 +5,7 @@ if DependencyHelper.grape_present?
|
|
5
5
|
let(:err_stream) { std_stream }
|
6
6
|
let(:stderr) { err_stream.read }
|
7
7
|
|
8
|
-
it "returns the
|
8
|
+
it "returns the Rack::GrapeMiddleware constant calling the Grape::Middleware constant" do
|
9
9
|
silence { expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware) }
|
10
10
|
end
|
11
11
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
describe Appsignal::Rack::InstrumentationMiddleware do
|
2
|
+
let(:app) { DummyApp.new }
|
3
|
+
let(:env) { Rack::MockRequest.env_for("/some/path") }
|
4
|
+
let(:middleware) { described_class.new(app, {}) }
|
5
|
+
|
6
|
+
before { start_agent }
|
7
|
+
around { |example| keep_transactions { example.run } }
|
8
|
+
|
9
|
+
def make_request(env)
|
10
|
+
middleware.call(env)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "without an exception" do
|
14
|
+
it "reports a process_request_middleware.rack event" do
|
15
|
+
make_request(env)
|
16
|
+
|
17
|
+
expect(last_transaction).to include_event("name" => "process_request_middleware.rack")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "with custom action name" do
|
22
|
+
let(:app) { DummyApp.new { |_env| Appsignal.set_action("MyAction") } }
|
23
|
+
|
24
|
+
it "reports the custom action name" do
|
25
|
+
make_request(env)
|
26
|
+
|
27
|
+
expect(last_transaction).to have_action("MyAction")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "without action name metadata" do
|
32
|
+
it "reports no action name" do
|
33
|
+
make_request(env)
|
34
|
+
|
35
|
+
expect(last_transaction).to_not have_action
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|