appsignal 3.9.2-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 +3138 -0
- data/.rubocop.yml +28 -20
- data/.rubocop_todo.yml +7 -33
- data/CHANGELOG.md +130 -0
- data/README.md +0 -1
- data/Rakefile +80 -65
- data/appsignal.gemspec +1 -1
- data/build_matrix.yml +112 -184
- data/ext/base.rb +1 -1
- data/gemfiles/hanami-2.1.gemfile +7 -0
- data/gemfiles/webmachine1.gemfile +5 -4
- data/lib/appsignal/cli/diagnose.rb +1 -1
- data/lib/appsignal/config.rb +5 -1
- data/lib/appsignal/demo.rb +0 -1
- data/lib/appsignal/environment.rb +11 -2
- data/lib/appsignal/extension/jruby.rb +1 -1
- data/lib/appsignal/helpers/instrumentation.rb +164 -2
- data/lib/appsignal/hooks/active_job.rb +1 -6
- data/lib/appsignal/integrations/grape.rb +19 -47
- data/lib/appsignal/integrations/hanami.rb +8 -7
- data/lib/appsignal/integrations/padrino.rb +51 -52
- data/lib/appsignal/integrations/railtie.rb +0 -3
- data/lib/appsignal/integrations/rake.rb +46 -12
- data/lib/appsignal/integrations/sidekiq.rb +1 -11
- data/lib/appsignal/integrations/sinatra.rb +0 -1
- data/lib/appsignal/integrations/webmachine.rb +15 -9
- data/lib/appsignal/probes/gvl.rb +24 -2
- data/lib/appsignal/probes/sidekiq.rb +1 -1
- data/lib/appsignal/probes.rb +1 -1
- data/lib/appsignal/rack/abstract_middleware.rb +104 -33
- data/lib/appsignal/rack/body_wrapper.rb +143 -0
- data/lib/appsignal/rack/event_handler.rb +12 -3
- data/lib/appsignal/rack/generic_instrumentation.rb +5 -4
- data/lib/appsignal/rack/grape_middleware.rb +40 -0
- data/lib/appsignal/rack/hanami_middleware.rb +2 -12
- data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
- data/lib/appsignal/rack/rails_instrumentation.rb +14 -57
- 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/utils/integration_memory_logger.rb +78 -0
- data/lib/appsignal/utils.rb +1 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +36 -33
- data/spec/.rubocop.yml +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +1 -1
- data/spec/lib/appsignal/cli/install_spec.rb +3 -3
- data/spec/lib/appsignal/config_spec.rb +8 -5
- data/spec/lib/appsignal/demo_spec.rb +38 -41
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +86 -167
- data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +8 -20
- data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +38 -84
- data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +16 -37
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +4 -4
- data/spec/lib/appsignal/hooks/activejob_spec.rb +111 -200
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +54 -91
- data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +14 -32
- data/spec/lib/appsignal/hooks/excon_spec.rb +8 -12
- data/spec/lib/appsignal/hooks/net_http_spec.rb +7 -42
- data/spec/lib/appsignal/hooks/rake_spec.rb +107 -34
- data/spec/lib/appsignal/hooks/redis_client_spec.rb +18 -30
- data/spec/lib/appsignal/hooks/redis_spec.rb +10 -16
- data/spec/lib/appsignal/hooks/resque_spec.rb +42 -62
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +33 -74
- data/spec/lib/appsignal/integrations/hanami_spec.rb +79 -21
- data/spec/lib/appsignal/integrations/http_spec.rb +12 -20
- data/spec/lib/appsignal/integrations/net_http_spec.rb +33 -0
- data/spec/lib/appsignal/integrations/object_spec.rb +29 -36
- data/spec/lib/appsignal/integrations/padrino_spec.rb +190 -163
- data/spec/lib/appsignal/integrations/que_spec.rb +43 -70
- data/spec/lib/appsignal/integrations/railtie_spec.rb +26 -67
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +86 -160
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -3
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +77 -40
- data/spec/lib/appsignal/probes/gvl_spec.rb +80 -3
- data/spec/lib/appsignal/probes_spec.rb +7 -4
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +302 -105
- data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
- data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -78
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -27
- data/spec/lib/appsignal/rack/grape_middleware_spec.rb +234 -0
- data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +2 -16
- data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +67 -131
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +36 -44
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +44 -139
- data/spec/lib/appsignal/transaction_spec.rb +239 -94
- data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +163 -0
- data/spec/lib/appsignal_spec.rb +556 -344
- data/spec/support/helpers/dependency_helper.rb +6 -1
- data/spec/support/helpers/std_streams_helper.rb +1 -1
- data/spec/support/helpers/transaction_helpers.rb +8 -0
- data/spec/support/matchers/transaction.rb +185 -0
- data/spec/support/mocks/dummy_app.rb +20 -0
- data/spec/support/shared_examples/instrument.rb +17 -12
- data/spec/support/testing.rb +18 -9
- metadata +20 -11
- data/.semaphore/semaphore.yml +0 -2347
- data/script/lint_git +0 -22
- data/spec/lib/appsignal/integrations/grape_spec.rb +0 -239
- data/spec/support/matchers/be_completed.rb +0 -5
- data/support/check_versions +0 -22
- /data/gemfiles/{hanami.gemfile → hanami-2.0.gemfile} +0 -0
|
@@ -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
|
|
@@ -22,17 +22,19 @@ describe Appsignal::Rack::EventHandler do
|
|
|
22
22
|
event_handler_instance.on_start(request, response)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def on_error(error)
|
|
26
|
+
event_handler_instance.on_error(request, response, error)
|
|
27
|
+
end
|
|
28
|
+
|
|
25
29
|
describe "#on_start" do
|
|
26
30
|
it "creates a new transaction" do
|
|
27
31
|
expect { on_start }.to change { created_transactions.length }.by(1)
|
|
28
32
|
|
|
29
33
|
transaction = last_transaction
|
|
30
|
-
expect(transaction
|
|
31
|
-
|
|
32
|
-
"namespace" => Appsignal::Transaction::HTTP_REQUEST
|
|
33
|
-
)
|
|
34
|
+
expect(transaction).to have_id
|
|
35
|
+
expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
|
|
34
36
|
|
|
35
|
-
expect(Appsignal::Transaction.current).to eq(
|
|
37
|
+
expect(Appsignal::Transaction.current).to eq(transaction)
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
context "when the handler is nested in another EventHandler" do
|
|
@@ -119,21 +121,11 @@ describe Appsignal::Rack::EventHandler do
|
|
|
119
121
|
end
|
|
120
122
|
|
|
121
123
|
describe "#on_error" do
|
|
122
|
-
def on_error(error)
|
|
123
|
-
event_handler_instance.on_error(request, response, error)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
124
|
it "reports the error" do
|
|
127
125
|
on_start
|
|
128
126
|
on_error(ExampleStandardError.new("the error"))
|
|
129
127
|
|
|
130
|
-
expect(last_transaction
|
|
131
|
-
"error" => {
|
|
132
|
-
"name" => "ExampleStandardError",
|
|
133
|
-
"message" => "the error",
|
|
134
|
-
"backtrace" => kind_of(String)
|
|
135
|
-
}
|
|
136
|
-
)
|
|
128
|
+
expect(last_transaction).to have_error("ExampleStandardError", "the error")
|
|
137
129
|
end
|
|
138
130
|
|
|
139
131
|
context "when the handler is nested in another EventHandler" do
|
|
@@ -141,7 +133,7 @@ describe Appsignal::Rack::EventHandler do
|
|
|
141
133
|
on_start
|
|
142
134
|
described_class.new.on_error(request, response, ExampleStandardError.new("the error"))
|
|
143
135
|
|
|
144
|
-
expect(last_transaction
|
|
136
|
+
expect(last_transaction).to_not have_error
|
|
145
137
|
end
|
|
146
138
|
end
|
|
147
139
|
|
|
@@ -174,11 +166,9 @@ describe Appsignal::Rack::EventHandler do
|
|
|
174
166
|
|
|
175
167
|
on_finish
|
|
176
168
|
|
|
177
|
-
expect(last_transaction
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
"events" => []
|
|
181
|
-
)
|
|
169
|
+
expect(last_transaction).to_not have_action
|
|
170
|
+
expect(last_transaction).to_not include_events
|
|
171
|
+
expect(last_transaction).to include("sample_data" => {})
|
|
182
172
|
expect(last_transaction).to_not be_completed
|
|
183
173
|
end
|
|
184
174
|
|
|
@@ -186,18 +176,12 @@ describe Appsignal::Rack::EventHandler do
|
|
|
186
176
|
on_start
|
|
187
177
|
on_finish
|
|
188
178
|
|
|
189
|
-
expect(last_transaction
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
"
|
|
193
|
-
"sample_data" => hash_including(
|
|
194
|
-
"environment" => {
|
|
195
|
-
"REQUEST_METHOD" => "GET",
|
|
196
|
-
"PATH_INFO" => "/path"
|
|
197
|
-
}
|
|
198
|
-
)
|
|
179
|
+
expect(last_transaction).to_not have_action
|
|
180
|
+
expect(last_transaction).to include_environment(
|
|
181
|
+
"REQUEST_METHOD" => "GET",
|
|
182
|
+
"PATH_INFO" => "/path"
|
|
199
183
|
)
|
|
200
|
-
expect(last_transaction
|
|
184
|
+
expect(last_transaction).to have_queue_start(queue_start_time)
|
|
201
185
|
expect(last_transaction).to be_completed
|
|
202
186
|
end
|
|
203
187
|
|
|
@@ -206,18 +190,14 @@ describe Appsignal::Rack::EventHandler do
|
|
|
206
190
|
on_start
|
|
207
191
|
on_finish(request, nil)
|
|
208
192
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
"
|
|
214
|
-
|
|
215
|
-
"REQUEST_METHOD" => "GET",
|
|
216
|
-
"PATH_INFO" => "/path"
|
|
217
|
-
}
|
|
218
|
-
)
|
|
193
|
+
# The action is not set on purpose, as we can't set a normalized route
|
|
194
|
+
# It requires the app to set an action name
|
|
195
|
+
expect(last_transaction).to_not have_action
|
|
196
|
+
expect(last_transaction).to include_environment(
|
|
197
|
+
"REQUEST_METHOD" => "GET",
|
|
198
|
+
"PATH_INFO" => "/path"
|
|
219
199
|
)
|
|
220
|
-
expect(last_transaction
|
|
200
|
+
expect(last_transaction).to have_queue_start(queue_start_time)
|
|
221
201
|
expect(last_transaction).to be_completed
|
|
222
202
|
end
|
|
223
203
|
|
|
@@ -225,7 +205,7 @@ describe Appsignal::Rack::EventHandler do
|
|
|
225
205
|
on_start
|
|
226
206
|
on_finish(request, nil)
|
|
227
207
|
|
|
228
|
-
expect(last_transaction
|
|
208
|
+
expect(last_transaction).to_not include_tags("response_status" => anything)
|
|
229
209
|
end
|
|
230
210
|
|
|
231
211
|
it "does not report a response_status counter metric" do
|
|
@@ -235,6 +215,25 @@ describe Appsignal::Rack::EventHandler do
|
|
|
235
215
|
on_start
|
|
236
216
|
on_finish(request, nil)
|
|
237
217
|
end
|
|
218
|
+
|
|
219
|
+
context "with an error previously recorded by on_error" do
|
|
220
|
+
it "sets response status 500 as a tag" do
|
|
221
|
+
on_start
|
|
222
|
+
on_error(ExampleStandardError.new("the error"))
|
|
223
|
+
on_finish(request, nil)
|
|
224
|
+
|
|
225
|
+
expect(last_transaction).to include_tags("response_status" => 500)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it "increments the response status counter for response status 500" do
|
|
229
|
+
expect(Appsignal).to receive(:increment_counter)
|
|
230
|
+
.with(:response_status, 1, :status => 500, :namespace => :web)
|
|
231
|
+
|
|
232
|
+
on_start
|
|
233
|
+
on_error(ExampleStandardError.new("the error"))
|
|
234
|
+
on_finish(request, nil)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
238
237
|
end
|
|
239
238
|
|
|
240
239
|
context "with error inside on_finish handler" do
|
|
@@ -260,12 +259,10 @@ describe Appsignal::Rack::EventHandler do
|
|
|
260
259
|
on_start
|
|
261
260
|
described_class.new.on_finish(request, response)
|
|
262
261
|
|
|
263
|
-
expect(last_transaction
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
"events" => []
|
|
268
|
-
)
|
|
262
|
+
expect(last_transaction).to_not have_action
|
|
263
|
+
expect(last_transaction).to_not include_metadata
|
|
264
|
+
expect(last_transaction).to_not include_events
|
|
265
|
+
expect(last_transaction.to_h).to include("sample_data" => {})
|
|
269
266
|
expect(last_transaction).to_not be_completed
|
|
270
267
|
end
|
|
271
268
|
end
|
|
@@ -275,44 +272,50 @@ describe Appsignal::Rack::EventHandler do
|
|
|
275
272
|
last_transaction.set_action("My action")
|
|
276
273
|
on_finish
|
|
277
274
|
|
|
278
|
-
expect(last_transaction
|
|
279
|
-
"action" => "My action"
|
|
280
|
-
)
|
|
275
|
+
expect(last_transaction).to have_action("My action")
|
|
281
276
|
end
|
|
282
277
|
|
|
283
278
|
it "finishes the process_request.rack event" do
|
|
284
279
|
on_start
|
|
285
280
|
on_finish
|
|
286
281
|
|
|
287
|
-
expect(last_transaction
|
|
288
|
-
"events" => [
|
|
289
|
-
hash_including(
|
|
290
|
-
"name" => "process_request.rack",
|
|
291
|
-
"title" => "",
|
|
292
|
-
"body" => "",
|
|
293
|
-
"body_format" => Appsignal::EventFormatter::DEFAULT
|
|
294
|
-
)
|
|
295
|
-
]
|
|
296
|
-
)
|
|
282
|
+
expect(last_transaction).to include_event("name" => "process_request.rack")
|
|
297
283
|
end
|
|
298
284
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
285
|
+
context "with response" do
|
|
286
|
+
it "sets the response status as a tag" do
|
|
287
|
+
on_start
|
|
288
|
+
on_finish
|
|
302
289
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
"tags" => { "response_status" => 200 }
|
|
306
|
-
)
|
|
307
|
-
)
|
|
308
|
-
end
|
|
290
|
+
expect(last_transaction).to include_tags("response_status" => 200)
|
|
291
|
+
end
|
|
309
292
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
293
|
+
it "increments the response status counter for response status" do
|
|
294
|
+
expect(Appsignal).to receive(:increment_counter)
|
|
295
|
+
.with(:response_status, 1, :status => 200, :namespace => :web)
|
|
313
296
|
|
|
314
|
-
|
|
315
|
-
|
|
297
|
+
on_start
|
|
298
|
+
on_finish
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
context "with an error previously recorded by on_error" do
|
|
302
|
+
it "sets response status from the response as a tag" do
|
|
303
|
+
on_start
|
|
304
|
+
on_error(ExampleStandardError.new("the error"))
|
|
305
|
+
on_finish
|
|
306
|
+
|
|
307
|
+
expect(last_transaction).to include_tags("response_status" => 200)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it "increments the response status counter based on the response" do
|
|
311
|
+
expect(Appsignal).to receive(:increment_counter)
|
|
312
|
+
.with(:response_status, 1, :status => 200, :namespace => :web)
|
|
313
|
+
|
|
314
|
+
on_start
|
|
315
|
+
on_error(ExampleStandardError.new("the error"))
|
|
316
|
+
on_finish
|
|
317
|
+
end
|
|
318
|
+
end
|
|
316
319
|
end
|
|
317
320
|
|
|
318
321
|
it "logs an error in case of an error" do
|
|
@@ -1,38 +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
|
|
5
10
|
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
8
17
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
18
|
+
it "prints a deprecation warning to STDERR" do
|
|
19
|
+
capture_std_streams(std_stream, err_stream) do
|
|
20
|
+
Appsignal::Rack::GenericInstrumentation
|
|
21
|
+
end
|
|
12
22
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
expect(stderr).to include(
|
|
24
|
+
"appsignal WARNING: The constant Appsignal::Rack::GenericInstrumentation " \
|
|
25
|
+
"has been deprecated."
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "logs a warning" do
|
|
30
|
+
logs =
|
|
31
|
+
capture_logs do
|
|
32
|
+
silence do
|
|
33
|
+
Appsignal::Rack::GenericInstrumentation
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
expect(logs).to contains_log(
|
|
38
|
+
:warn,
|
|
39
|
+
"The constant Appsignal::Rack::GenericInstrumentation has been deprecated."
|
|
27
40
|
)
|
|
28
41
|
end
|
|
29
42
|
end
|
|
30
43
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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)
|
|
34
76
|
|
|
35
|
-
|
|
77
|
+
expect(last_transaction).to have_action("unknown")
|
|
78
|
+
end
|
|
36
79
|
end
|
|
37
80
|
end
|
|
38
81
|
end
|