appsignal 3.9.2-java → 3.10.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +3138 -0
  3. data/.rubocop.yml +28 -20
  4. data/.rubocop_todo.yml +7 -33
  5. data/CHANGELOG.md +130 -0
  6. data/README.md +0 -1
  7. data/Rakefile +80 -65
  8. data/appsignal.gemspec +1 -1
  9. data/build_matrix.yml +112 -184
  10. data/ext/base.rb +1 -1
  11. data/gemfiles/hanami-2.1.gemfile +7 -0
  12. data/gemfiles/webmachine1.gemfile +5 -4
  13. data/lib/appsignal/cli/diagnose.rb +1 -1
  14. data/lib/appsignal/config.rb +5 -1
  15. data/lib/appsignal/demo.rb +0 -1
  16. data/lib/appsignal/environment.rb +11 -2
  17. data/lib/appsignal/extension/jruby.rb +1 -1
  18. data/lib/appsignal/helpers/instrumentation.rb +164 -2
  19. data/lib/appsignal/hooks/active_job.rb +1 -6
  20. data/lib/appsignal/integrations/grape.rb +19 -47
  21. data/lib/appsignal/integrations/hanami.rb +8 -7
  22. data/lib/appsignal/integrations/padrino.rb +51 -52
  23. data/lib/appsignal/integrations/railtie.rb +0 -3
  24. data/lib/appsignal/integrations/rake.rb +46 -12
  25. data/lib/appsignal/integrations/sidekiq.rb +1 -11
  26. data/lib/appsignal/integrations/sinatra.rb +0 -1
  27. data/lib/appsignal/integrations/webmachine.rb +15 -9
  28. data/lib/appsignal/probes/gvl.rb +24 -2
  29. data/lib/appsignal/probes/sidekiq.rb +1 -1
  30. data/lib/appsignal/probes.rb +1 -1
  31. data/lib/appsignal/rack/abstract_middleware.rb +104 -33
  32. data/lib/appsignal/rack/body_wrapper.rb +143 -0
  33. data/lib/appsignal/rack/event_handler.rb +12 -3
  34. data/lib/appsignal/rack/generic_instrumentation.rb +5 -4
  35. data/lib/appsignal/rack/grape_middleware.rb +40 -0
  36. data/lib/appsignal/rack/hanami_middleware.rb +2 -12
  37. data/lib/appsignal/rack/instrumentation_middleware.rb +62 -0
  38. data/lib/appsignal/rack/rails_instrumentation.rb +14 -57
  39. data/lib/appsignal/rack/sinatra_instrumentation.rb +1 -3
  40. data/lib/appsignal/rack/streaming_listener.rb +13 -59
  41. data/lib/appsignal/rack.rb +31 -0
  42. data/lib/appsignal/transaction.rb +50 -8
  43. data/lib/appsignal/utils/integration_memory_logger.rb +78 -0
  44. data/lib/appsignal/utils.rb +1 -0
  45. data/lib/appsignal/version.rb +1 -1
  46. data/lib/appsignal.rb +36 -33
  47. data/spec/.rubocop.yml +1 -1
  48. data/spec/lib/appsignal/cli/diagnose_spec.rb +1 -1
  49. data/spec/lib/appsignal/cli/install_spec.rb +3 -3
  50. data/spec/lib/appsignal/config_spec.rb +8 -5
  51. data/spec/lib/appsignal/demo_spec.rb +38 -41
  52. data/spec/lib/appsignal/hooks/action_cable_spec.rb +86 -167
  53. data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +8 -20
  54. data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +38 -84
  55. data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +16 -37
  56. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +4 -4
  57. data/spec/lib/appsignal/hooks/activejob_spec.rb +111 -200
  58. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +54 -91
  59. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +14 -32
  60. data/spec/lib/appsignal/hooks/excon_spec.rb +8 -12
  61. data/spec/lib/appsignal/hooks/net_http_spec.rb +7 -42
  62. data/spec/lib/appsignal/hooks/rake_spec.rb +107 -34
  63. data/spec/lib/appsignal/hooks/redis_client_spec.rb +18 -30
  64. data/spec/lib/appsignal/hooks/redis_spec.rb +10 -16
  65. data/spec/lib/appsignal/hooks/resque_spec.rb +42 -62
  66. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +33 -74
  67. data/spec/lib/appsignal/integrations/hanami_spec.rb +79 -21
  68. data/spec/lib/appsignal/integrations/http_spec.rb +12 -20
  69. data/spec/lib/appsignal/integrations/net_http_spec.rb +33 -0
  70. data/spec/lib/appsignal/integrations/object_spec.rb +29 -36
  71. data/spec/lib/appsignal/integrations/padrino_spec.rb +190 -163
  72. data/spec/lib/appsignal/integrations/que_spec.rb +43 -70
  73. data/spec/lib/appsignal/integrations/railtie_spec.rb +26 -67
  74. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +86 -160
  75. data/spec/lib/appsignal/integrations/sinatra_spec.rb +10 -3
  76. data/spec/lib/appsignal/integrations/webmachine_spec.rb +77 -40
  77. data/spec/lib/appsignal/probes/gvl_spec.rb +80 -3
  78. data/spec/lib/appsignal/probes_spec.rb +7 -4
  79. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +302 -105
  80. data/spec/lib/appsignal/rack/body_wrapper_spec.rb +263 -0
  81. data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -78
  82. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +70 -27
  83. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +234 -0
  84. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +2 -16
  85. data/spec/lib/appsignal/rack/instrumentation_middleware_spec.rb +38 -0
  86. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +67 -131
  87. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +36 -44
  88. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +44 -139
  89. data/spec/lib/appsignal/transaction_spec.rb +239 -94
  90. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +163 -0
  91. data/spec/lib/appsignal_spec.rb +556 -344
  92. data/spec/support/helpers/dependency_helper.rb +6 -1
  93. data/spec/support/helpers/std_streams_helper.rb +1 -1
  94. data/spec/support/helpers/transaction_helpers.rb +8 -0
  95. data/spec/support/matchers/transaction.rb +185 -0
  96. data/spec/support/mocks/dummy_app.rb +20 -0
  97. data/spec/support/shared_examples/instrument.rb +17 -12
  98. data/spec/support/testing.rb +18 -9
  99. metadata +20 -11
  100. data/.semaphore/semaphore.yml +0 -2347
  101. data/script/lint_git +0 -22
  102. data/spec/lib/appsignal/integrations/grape_spec.rb +0 -239
  103. data/spec/support/matchers/be_completed.rb +0 -5
  104. data/support/check_versions +0 -22
  105. /data/gemfiles/{hanami.gemfile → hanami-2.0.gemfile} +0 -0
@@ -1,5 +1,5 @@
1
1
  describe Appsignal::Rack::AbstractMiddleware do
2
- let(:app) { double(:call => true) }
2
+ let(:app) { DummyApp.new }
3
3
  let(:request_path) { "/some/path" }
4
4
  let(:env) do
5
5
  Rack::MockRequest.env_for(
@@ -9,176 +9,292 @@ describe Appsignal::Rack::AbstractMiddleware do
9
9
  )
10
10
  end
11
11
  let(:options) { {} }
12
- let(:middleware) { Appsignal::Rack::AbstractMiddleware.new(app, options) }
12
+ let(:middleware) { described_class.new(app, options) }
13
13
 
14
14
  before(:context) { start_agent }
15
15
  around { |example| keep_transactions { example.run } }
16
16
 
17
- def make_request(env)
17
+ def make_request
18
18
  middleware.call(env)
19
19
  end
20
20
 
21
- def make_request_with_error(env, error)
22
- expect { make_request(env) }.to raise_error(error)
21
+ def make_request_with_error(error_class, error_message)
22
+ expect { make_request }.to raise_error(error_class, error_message)
23
23
  end
24
24
 
25
25
  describe "#call" do
26
- context "when appsignal is not active" do
26
+ context "when not active" do
27
27
  before { allow(Appsignal).to receive(:active?).and_return(false) }
28
28
 
29
- it "does not instrument requests" do
30
- expect { make_request(env) }.to_not(change { created_transactions.count })
29
+ it "does not instrument the request" do
30
+ expect { make_request }.to_not(change { created_transactions.count })
31
31
  end
32
32
 
33
33
  it "calls the next middleware in the stack" do
34
- expect(app).to receive(:call).with(env)
35
- make_request(env)
34
+ make_request
35
+ expect(app).to be_called
36
36
  end
37
37
  end
38
38
 
39
39
  context "when appsignal is active" do
40
40
  before { allow(Appsignal).to receive(:active?).and_return(true) }
41
41
 
42
- it "calls the next middleware in the stack" do
43
- make_request(env)
42
+ it "creates a transaction for the request" do
43
+ expect { make_request }.to(change { created_transactions.count }.by(1))
44
44
 
45
- expect(app).to have_received(:call).with(env)
45
+ expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
46
46
  end
47
47
 
48
- context "without an exception" do
49
- it "create a transaction for the request" do
50
- expect { make_request(env) }.to(change { created_transactions.count }.by(1))
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
51
52
 
52
- expect(last_transaction.to_h).to include(
53
- "namespace" => Appsignal::Transaction::HTTP_REQUEST,
54
- "action" => nil,
55
- "error" => nil
56
- )
53
+ context "without an error" do
54
+ before { make_request }
55
+
56
+ it "calls the next middleware in the stack" do
57
+ expect(app).to be_called
58
+ end
59
+
60
+ it "does not record an error" do
61
+ expect(last_transaction).to_not have_error
57
62
  end
58
63
 
59
- it "reports a process.abstract event" do
60
- make_request(env)
64
+ context "without :instrument_event_name option set" do
65
+ let(:options) { {} }
61
66
 
62
- expect(last_transaction.to_h).to include(
63
- "events" => [
64
- hash_including(
65
- "body" => "",
66
- "body_format" => Appsignal::EventFormatter::DEFAULT,
67
- "count" => 1,
68
- "name" => "process.abstract",
69
- "title" => ""
70
- )
71
- ]
72
- )
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
73
78
  end
74
79
 
75
80
  it "completes the transaction" do
76
- make_request(env)
77
81
  expect(last_transaction).to be_completed
82
+ expect(Appsignal::Transaction.current)
83
+ .to be_kind_of(Appsignal::Transaction::NilTransaction)
84
+ end
85
+
86
+ context "when instrument_event_name option is nil" do
87
+ let(:options) { { :instrument_event_name => nil } }
88
+
89
+ it "does not record an instrumentation event" do
90
+ expect(last_transaction).to_not include_events
91
+ end
78
92
  end
79
93
  end
80
94
 
81
- context "with an exception" do
95
+ context "with an error" do
82
96
  let(:error) { ExampleException.new("error message") }
83
- before do
84
- allow(app).to receive(:call).and_raise(error)
85
- expect { make_request_with_error(env, error) }
97
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
98
+
99
+ it "create a transaction for the request" do
100
+ expect { make_request_with_error(ExampleException, "error message") }
86
101
  .to(change { created_transactions.count }.by(1))
87
- end
88
102
 
89
- it "creates a transaction for the request and records the exception" do
90
- expect(last_transaction.to_h).to include(
91
- "error" => hash_including(
92
- "name" => "ExampleException",
93
- "message" => "error message"
94
- )
95
- )
103
+ expect(last_transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
96
104
  end
97
105
 
98
- it "completes the transaction" do
99
- expect(last_transaction).to be_completed
106
+ describe "error" do
107
+ before do
108
+ make_request_with_error(ExampleException, "error message")
109
+ end
110
+
111
+ it "records the error" do
112
+ expect(last_transaction).to have_error("ExampleException", "error message")
113
+ end
114
+
115
+ it "completes the transaction" do
116
+ expect(last_transaction).to be_completed
117
+ expect(Appsignal::Transaction.current)
118
+ .to be_kind_of(Appsignal::Transaction::NilTransaction)
119
+ end
120
+
121
+ context "with :report_errors set to false" do
122
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
123
+ let(:options) { { :report_errors => false } }
124
+
125
+ it "does not record the exception on the transaction" do
126
+ expect(last_transaction).to_not have_error
127
+ end
128
+ end
129
+
130
+ context "with :report_errors set to true" do
131
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
132
+ let(:options) { { :report_errors => true } }
133
+
134
+ it "records the exception on the transaction" do
135
+ expect(last_transaction).to have_error("ExampleException", "error message")
136
+ end
137
+ end
138
+
139
+ context "with :report_errors set to a lambda that returns false" do
140
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
141
+ let(:options) { { :report_errors => lambda { |_env| false } } }
142
+
143
+ it "does not record the exception on the transaction" do
144
+ expect(last_transaction).to_not have_error
145
+ end
146
+ end
147
+
148
+ context "with :report_errors set to a lambda that returns true" do
149
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
150
+ let(:options) { { :report_errors => lambda { |_env| true } } }
151
+
152
+ it "records the exception on the transaction" do
153
+ expect(last_transaction).to have_error("ExampleException", "error message")
154
+ end
155
+ end
100
156
  end
101
157
  end
102
158
 
103
159
  context "without action name metadata" do
104
160
  it "reports no action name" do
105
- make_request(env)
161
+ make_request
106
162
 
107
- expect(last_transaction.to_h).to include("action" => nil)
163
+ expect(last_transaction).to_not have_action
108
164
  end
109
165
  end
110
166
 
111
167
  context "with appsignal.route env" do
112
- before do
113
- env["appsignal.route"] = "POST /my-route"
114
- end
168
+ before { env["appsignal.route"] = "POST /my-route" }
115
169
 
116
170
  it "reports the appsignal.route value as the action name" do
117
- make_request(env)
171
+ make_request
172
+
173
+ expect(last_transaction).to have_action("POST /my-route")
174
+ end
118
175
 
119
- expect(last_transaction.to_h).to include("action" => "POST /my-route")
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
+ )
120
193
  end
121
194
  end
122
195
 
123
196
  context "with appsignal.action env" do
124
- before do
125
- env["appsignal.action"] = "POST /my-action"
197
+ before { env["appsignal.action"] = "POST /my-action" }
198
+
199
+ it "reports the appsignal.action value as the action name" do
200
+ make_request
201
+
202
+ expect(last_transaction).to have_action("POST /my-action")
126
203
  end
127
204
 
128
- it "reports the appsignal.route value as the action name" do
129
- make_request(env)
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
130
210
 
131
- expect(last_transaction.to_h).to include("action" => "POST /my-action")
211
+ expect(err_stream.read).to include(
212
+ "Setting the action name with the request env 'appsignal.action' is deprecated."
213
+ )
132
214
  end
133
- end
134
215
 
135
- describe "request metadata" do
136
- before do
137
- env.merge("PATH_INFO" => "/some/path", "REQUEST_METHOD" => "GET")
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
+ )
138
222
  end
223
+ end
139
224
 
225
+ describe "request metadata" do
140
226
  it "sets request metadata" do
141
- make_request(env)
142
-
143
- expect(last_transaction.to_h).to include(
144
- "metadata" => {
145
- "method" => "GET",
146
- "path" => "/some/path"
147
- },
148
- "sample_data" => hash_including(
149
- "environment" => hash_including(
150
- "REQUEST_METHOD" => "GET",
151
- "PATH_INFO" => "/some/path"
152
- # and more, but we don't need to test Rack mock defaults
153
- )
154
- )
227
+ env.merge!("PATH_INFO" => "/some/path", "REQUEST_METHOD" => "GET")
228
+ make_request
229
+
230
+ expect(last_transaction).to include_metadata(
231
+ "method" => "GET",
232
+ "path" => "/some/path"
155
233
  )
234
+ expect(last_transaction).to include_environment(
235
+ "REQUEST_METHOD" => "GET",
236
+ "PATH_INFO" => "/some/path"
237
+ # and more, but we don't need to test Rack mock defaults
238
+ )
239
+ end
240
+
241
+ context "with an invalid HTTP request method" do
242
+ it "stores the invalid HTTP request method" do
243
+ env["REQUEST_METHOD"] = "FOO"
244
+ make_request
245
+
246
+ expect(last_transaction).to include_metadata("method" => "FOO")
247
+ end
248
+ end
249
+
250
+ context "with fetching the request method raises an error" do
251
+ class BrokenRequestMethodRequest < Rack::Request
252
+ def request_method
253
+ raise "uh oh!"
254
+ end
255
+ end
256
+
257
+ let(:options) { { :request_class => BrokenRequestMethodRequest } }
258
+ it "does not store the invalid HTTP request method" do
259
+ env["REQUEST_METHOD"] = "FOO"
260
+ make_request
261
+
262
+ expect(last_transaction).to_not include_metadata("method" => anything)
263
+ end
156
264
  end
157
265
 
158
266
  it "sets request parameters" do
159
- make_request(env)
160
-
161
- expect(last_transaction.to_h).to include(
162
- "sample_data" => hash_including(
163
- "params" => hash_including(
164
- "page" => "2",
165
- "query" => "lorem"
166
- )
167
- )
267
+ make_request
268
+
269
+ expect(last_transaction).to include_params(
270
+ "page" => "2",
271
+ "query" => "lorem"
168
272
  )
169
273
  end
274
+
275
+ context "when setting custom params" do
276
+ let(:app) do
277
+ DummyApp.new do |_env|
278
+ Appsignal::Transaction.current.set_params("custom" => "param")
279
+ end
280
+ end
281
+
282
+ it "allow custom request parameters to be set" do
283
+ make_request
284
+
285
+ expect(last_transaction).to include_params("custom" => "param")
286
+ end
287
+ end
170
288
  end
171
289
 
172
290
  context "with queue start header" do
173
291
  let(:queue_start_time) { fixed_time * 1_000 }
174
- before do
175
- env["HTTP_X_REQUEST_START"] = "t=#{queue_start_time.to_i}" # in milliseconds
176
- end
177
292
 
178
293
  it "sets the queue start" do
179
- make_request(env)
294
+ env["HTTP_X_REQUEST_START"] = "t=#{queue_start_time.to_i}" # in milliseconds
295
+ make_request
180
296
 
181
- expect(last_transaction.ext.queue_start).to eq(queue_start_time)
297
+ expect(last_transaction).to have_queue_start(queue_start_time)
182
298
  end
183
299
  end
184
300
 
@@ -208,29 +324,66 @@ describe Appsignal::Rack::AbstractMiddleware do
208
324
  end
209
325
 
210
326
  it "uses the overridden request class and params method to fetch params" do
211
- make_request(env)
327
+ make_request
212
328
 
213
- expect(last_transaction.to_h).to include(
214
- "sample_data" => hash_including(
215
- "params" => { "abc" => "123" }
216
- )
217
- )
329
+ expect(last_transaction).to include_params("abc" => "123")
218
330
  end
219
331
  end
220
332
 
221
333
  context "with parent instrumentation" do
334
+ let(:transaction) { http_request_transaction }
222
335
  before do
223
- env[Appsignal::Rack::APPSIGNAL_TRANSACTION] = http_request_transaction
336
+ env[Appsignal::Rack::APPSIGNAL_TRANSACTION] = transaction
337
+ set_current_transaction(transaction)
224
338
  end
225
339
 
226
340
  it "uses the existing transaction" do
227
- make_request(env)
341
+ make_request
342
+
343
+ expect { make_request }.to_not(change { created_transactions.count })
344
+ end
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)
228
349
 
229
- expect { make_request(env) }.to_not(change { created_transactions.count })
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
+
375
+ context "with error" do
376
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
377
+
378
+ it "doesn't record the error on the transaction" do
379
+ make_request_with_error(ExampleException, "error message")
380
+
381
+ expect(last_transaction).to_not have_error
382
+ end
230
383
  end
231
384
 
232
385
  it "doesn't complete the existing transaction" do
233
- make_request(env)
386
+ make_request
234
387
 
235
388
  expect(env[Appsignal::Rack::APPSIGNAL_TRANSACTION]).to_not be_completed
236
389
  end
@@ -239,9 +392,53 @@ describe Appsignal::Rack::AbstractMiddleware do
239
392
  it "does not overwrite the action name" do
240
393
  env[Appsignal::Rack::APPSIGNAL_TRANSACTION].set_action("My custom action")
241
394
  env["appsignal.action"] = "POST /my-action"
242
- make_request(env)
395
+ make_request
396
+
397
+ expect(last_transaction).to have_action("My custom action")
398
+ end
399
+ end
400
+
401
+ context "with :report_errors set to false" do
402
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
403
+ let(:options) { { :report_errors => false } }
404
+
405
+ it "does not record the error on the transaction" do
406
+ make_request_with_error(ExampleException, "error message")
407
+
408
+ expect(last_transaction).to_not have_error
409
+ end
410
+ end
411
+
412
+ context "with :report_errors set to true" do
413
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
414
+ let(:options) { { :report_errors => true } }
415
+
416
+ it "records the error on the transaction" do
417
+ make_request_with_error(ExampleException, "error message")
418
+
419
+ expect(last_transaction).to have_error("ExampleException", "error message")
420
+ end
421
+ end
422
+
423
+ context "with :report_errors set to a lambda that returns false" do
424
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
425
+ let(:options) { { :report_errors => lambda { |_env| false } } }
426
+
427
+ it "does not record the exception on the transaction" do
428
+ make_request_with_error(ExampleException, "error message")
429
+
430
+ expect(last_transaction).to_not have_error
431
+ end
432
+ end
433
+
434
+ context "with :report_errors set to a lambda that returns true" do
435
+ let(:app) { lambda { |_env| raise ExampleException, "error message" } }
436
+ let(:options) { { :report_errors => lambda { |_env| true } } }
437
+
438
+ it "records the error on the transaction" do
439
+ make_request_with_error(ExampleException, "error message")
243
440
 
244
- expect(last_transaction.to_h).to include("action" => "My custom action")
441
+ expect(last_transaction).to have_error("ExampleException", "error message")
245
442
  end
246
443
  end
247
444
  end