appsignal 3.9.2-java → 3.9.3-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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +3135 -0
  3. data/.rubocop.yml +28 -20
  4. data/.rubocop_todo.yml +7 -33
  5. data/CHANGELOG.md +38 -0
  6. data/Rakefile +79 -64
  7. data/appsignal.gemspec +1 -1
  8. data/build_matrix.yml +109 -179
  9. data/ext/base.rb +1 -1
  10. data/gemfiles/hanami-2.1.gemfile +7 -0
  11. data/lib/appsignal/cli/diagnose.rb +1 -1
  12. data/lib/appsignal/config.rb +1 -1
  13. data/lib/appsignal/demo.rb +0 -1
  14. data/lib/appsignal/environment.rb +5 -1
  15. data/lib/appsignal/extension/jruby.rb +1 -1
  16. data/lib/appsignal/helpers/instrumentation.rb +1 -1
  17. data/lib/appsignal/integrations/grape.rb +19 -47
  18. data/lib/appsignal/integrations/hanami.rb +8 -7
  19. data/lib/appsignal/integrations/padrino.rb +46 -43
  20. data/lib/appsignal/integrations/railtie.rb +0 -3
  21. data/lib/appsignal/integrations/sinatra.rb +0 -1
  22. data/lib/appsignal/probes/gvl.rb +24 -2
  23. data/lib/appsignal/probes/sidekiq.rb +1 -1
  24. data/lib/appsignal/probes.rb +1 -1
  25. data/lib/appsignal/rack/abstract_middleware.rb +62 -28
  26. data/lib/appsignal/rack/event_handler.rb +12 -3
  27. data/lib/appsignal/rack/grape_middleware.rb +40 -0
  28. data/lib/appsignal/rack/hanami_middleware.rb +1 -11
  29. data/lib/appsignal/rack/rails_instrumentation.rb +14 -55
  30. data/lib/appsignal/utils/integration_memory_logger.rb +78 -0
  31. data/lib/appsignal/utils.rb +1 -0
  32. data/lib/appsignal/version.rb +1 -1
  33. data/lib/appsignal.rb +34 -33
  34. data/spec/.rubocop.yml +1 -1
  35. data/spec/lib/appsignal/cli/diagnose_spec.rb +1 -1
  36. data/spec/lib/appsignal/cli/install_spec.rb +3 -3
  37. data/spec/lib/appsignal/config_spec.rb +7 -5
  38. data/spec/lib/appsignal/demo_spec.rb +38 -41
  39. data/spec/lib/appsignal/hooks/action_cable_spec.rb +86 -167
  40. data/spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb +8 -20
  41. data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +38 -84
  42. data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +16 -37
  43. data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +4 -4
  44. data/spec/lib/appsignal/hooks/activejob_spec.rb +111 -200
  45. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +54 -91
  46. data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +14 -32
  47. data/spec/lib/appsignal/hooks/excon_spec.rb +8 -12
  48. data/spec/lib/appsignal/hooks/net_http_spec.rb +7 -42
  49. data/spec/lib/appsignal/hooks/rake_spec.rb +9 -19
  50. data/spec/lib/appsignal/hooks/redis_client_spec.rb +18 -30
  51. data/spec/lib/appsignal/hooks/redis_spec.rb +10 -16
  52. data/spec/lib/appsignal/hooks/resque_spec.rb +42 -62
  53. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +33 -74
  54. data/spec/lib/appsignal/integrations/hanami_spec.rb +79 -21
  55. data/spec/lib/appsignal/integrations/http_spec.rb +12 -20
  56. data/spec/lib/appsignal/integrations/net_http_spec.rb +33 -0
  57. data/spec/lib/appsignal/integrations/object_spec.rb +29 -36
  58. data/spec/lib/appsignal/integrations/padrino_spec.rb +47 -70
  59. data/spec/lib/appsignal/integrations/que_spec.rb +43 -70
  60. data/spec/lib/appsignal/integrations/railtie_spec.rb +26 -67
  61. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +86 -160
  62. data/spec/lib/appsignal/integrations/sinatra_spec.rb +0 -1
  63. data/spec/lib/appsignal/integrations/webmachine_spec.rb +28 -39
  64. data/spec/lib/appsignal/probes/gvl_spec.rb +80 -3
  65. data/spec/lib/appsignal/probes_spec.rb +7 -4
  66. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +215 -106
  67. data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -78
  68. data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +2 -12
  69. data/spec/lib/appsignal/rack/grape_middleware_spec.rb +234 -0
  70. data/spec/lib/appsignal/rack/hanami_middleware_spec.rb +2 -16
  71. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +67 -131
  72. data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +36 -44
  73. data/spec/lib/appsignal/rack/streaming_listener_spec.rb +68 -86
  74. data/spec/lib/appsignal/transaction_spec.rb +76 -90
  75. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +163 -0
  76. data/spec/lib/appsignal_spec.rb +363 -342
  77. data/spec/support/helpers/dependency_helper.rb +6 -1
  78. data/spec/support/helpers/std_streams_helper.rb +1 -1
  79. data/spec/support/helpers/transaction_helpers.rb +8 -0
  80. data/spec/support/matchers/transaction.rb +185 -0
  81. data/spec/support/mocks/dummy_app.rb +20 -0
  82. data/spec/support/shared_examples/instrument.rb +17 -12
  83. data/spec/support/testing.rb +18 -9
  84. metadata +15 -10
  85. data/.semaphore/semaphore.yml +0 -2347
  86. data/script/lint_git +0 -22
  87. data/spec/lib/appsignal/integrations/grape_spec.rb +0 -239
  88. data/spec/support/matchers/be_completed.rb +0 -5
  89. /data/gemfiles/{hanami.gemfile → hanami-2.0.gemfile} +0 -0
@@ -136,8 +136,8 @@ if DependencyHelper.rails_present?
136
136
  it "does nothing" do
137
137
  with_rails_error_reporter do
138
138
  expect do
139
- Rails.error.record { raise ExampleStandardError }
140
- end.to raise_error(ExampleStandardError)
139
+ Rails.error.record { raise ExampleStandardError, "error message" }
140
+ end.to raise_error(ExampleStandardError, "error message")
141
141
  end
142
142
 
143
143
  expect(created_transactions).to be_empty
@@ -156,24 +156,15 @@ if DependencyHelper.rails_present?
156
156
 
157
157
  with_rails_error_reporter do
158
158
  with_current_transaction current_transaction do
159
- Rails.error.handle { raise ExampleStandardError }
159
+ Rails.error.handle { raise ExampleStandardError, "error message" }
160
160
 
161
161
  transaction = last_transaction
162
- transaction_hash = transaction.to_h
163
- expect(transaction_hash).to include(
164
- "action" => "CustomAction",
165
- "namespace" => "custom",
166
- "error" => {
167
- "name" => "ExampleStandardError",
168
- "message" => "ExampleStandardError",
169
- "backtrace" => kind_of(String)
170
- },
171
- "sample_data" => hash_including(
172
- "tags" => hash_including(
173
- "duplicated_tag" => "duplicated value",
174
- "severity" => "warning"
175
- )
176
- )
162
+ expect(transaction).to have_namespace("custom")
163
+ expect(transaction).to have_action("CustomAction")
164
+ expect(transaction).to have_error("ExampleStandardError", "error message")
165
+ expect(transaction).to include_tags(
166
+ "duplicated_tag" => "duplicated value",
167
+ "severity" => "warning"
177
168
  )
178
169
  end
179
170
  end
@@ -188,16 +179,10 @@ if DependencyHelper.rails_present?
188
179
  given_context = { :tag1 => "value1", :tag2 => "value2" }
189
180
  Rails.error.handle(:context => given_context) { raise ExampleStandardError }
190
181
 
191
- transaction = last_transaction
192
- transaction_hash = transaction.to_h
193
- expect(transaction_hash).to include(
194
- "sample_data" => hash_including(
195
- "tags" => hash_including(
196
- "tag1" => "value1",
197
- "tag2" => "value2",
198
- "severity" => "warning"
199
- )
200
- )
182
+ expect(last_transaction).to include_tags(
183
+ "tag1" => "value1",
184
+ "tag2" => "value2",
185
+ "severity" => "warning"
201
186
  )
202
187
  end
203
188
  end
@@ -219,14 +204,9 @@ if DependencyHelper.rails_present?
219
204
  Rails.error.handle(:context => given_context) { raise ExampleStandardError }
220
205
 
221
206
  transaction = last_transaction
222
- transaction_hash = transaction.to_h
223
- expect(transaction_hash).to include(
224
- "sample_data" => hash_including(
225
- "custom_data" => {
226
- "array" => [1, 2],
227
- "hash" => { "one" => 1, "two" => 2 }
228
- }
229
- )
207
+ expect(transaction).to include_custom_data(
208
+ "array" => [1, 2],
209
+ "hash" => { "one" => 1, "two" => 2 }
230
210
  )
231
211
  end
232
212
  end
@@ -245,11 +225,8 @@ if DependencyHelper.rails_present?
245
225
  Rails.error.handle(:context => given_context) { raise ExampleStandardError }
246
226
 
247
227
  transaction = last_transaction
248
- transaction_hash = transaction.to_h
249
- expect(transaction_hash).to include(
250
- "namespace" => "context",
251
- "action" => "ContextAction"
252
- )
228
+ expect(transaction).to have_namespace("context")
229
+ expect(transaction).to have_action("ContextAction")
253
230
  end
254
231
  end
255
232
  end
@@ -301,17 +278,9 @@ if DependencyHelper.rails_present?
301
278
  end
302
279
 
303
280
  transaction = last_transaction
304
- transaction_hash = transaction.to_h
305
- expect(transaction_hash).to include(
306
- "action" => "ExampleRailsControllerMock#index",
307
- "metadata" => hash_including(
308
- "path" => "path",
309
- "method" => "GET"
310
- ),
311
- "sample_data" => hash_including(
312
- "params" => { "user_id" => 123, "password" => "[FILTERED]" }
313
- )
314
- )
281
+ expect(transaction).to have_action("ExampleRailsControllerMock#index")
282
+ expect(transaction).to include_metadata("path" => "path", "method" => "GET")
283
+ expect(transaction).to include_params("user_id" => 123, "password" => "[FILTERED]")
315
284
  end
316
285
 
317
286
  it "sets no action if no execution context is present" do
@@ -320,11 +289,7 @@ if DependencyHelper.rails_present?
320
289
  Rails.error.handle { raise ExampleStandardError }
321
290
  end
322
291
 
323
- transaction = last_transaction
324
- transaction_hash = transaction.to_h
325
- expect(transaction_hash).to include(
326
- "action" => nil
327
- )
292
+ expect(last_transaction).to_not have_action
328
293
  end
329
294
  end
330
295
 
@@ -340,16 +305,10 @@ if DependencyHelper.rails_present?
340
305
  Rails.error.handle(:context => given_context) { raise ExampleStandardError }
341
306
  end
342
307
 
343
- transaction = last_transaction
344
- transaction_hash = transaction.to_h
345
- expect(transaction_hash).to include(
346
- "sample_data" => hash_including(
347
- "tags" => hash_including(
348
- "tag1" => "value1",
349
- "tag2" => "value2",
350
- "severity" => "warning"
351
- )
352
- )
308
+ expect(last_transaction).to include_tags(
309
+ "tag1" => "value1",
310
+ "tag2" => "value2",
311
+ "severity" => "warning"
353
312
  )
354
313
  end
355
314
  end
@@ -20,17 +20,11 @@ describe Appsignal::Integrations::SidekiqDeathHandler do
20
20
  end
21
21
 
22
22
  def expect_error_on_transaction
23
- expect(last_transaction.to_h).to include(
24
- "error" => hash_including(
25
- "name" => "ExampleStandardError",
26
- "message" => "uh oh",
27
- "backtrace" => kind_of(String)
28
- )
29
- )
23
+ expect(last_transaction).to have_error("ExampleStandardError", "uh oh")
30
24
  end
31
25
 
32
26
  def expect_no_error_on_transaction
33
- expect(last_transaction.to_h).to include("error" => nil)
27
+ expect(last_transaction).to_not have_error
34
28
  end
35
29
 
36
30
  context "when sidekiq_report_errors = none" do
@@ -90,21 +84,13 @@ describe Appsignal::Integrations::SidekiqErrorHandler do
90
84
  described_class.new.call(exception, job_context)
91
85
  end.to(change { created_transactions.count }.by(1))
92
86
 
93
- transaction_hash = last_transaction.to_h
94
- expect(transaction_hash).to include(
95
- "action" => "SidekiqInternal",
96
- "error" => hash_including(
97
- "name" => "ExampleStandardError",
98
- "message" => "uh oh",
99
- "backtrace" => kind_of(String)
100
- )
101
- )
102
- expect(transaction_hash["sample_data"]).to include(
103
- "params" => {
104
- "jobstr" => "{ bad json }"
105
- }
87
+ transaction = last_transaction
88
+ expect(transaction).to have_action("SidekiqInternal")
89
+ expect(transaction).to have_error("ExampleStandardError", "uh oh")
90
+ expect(transaction).to include_params(
91
+ "jobstr" => "{ bad json }"
106
92
  )
107
- expect(transaction_hash["metadata"]).to include(
93
+ expect(transaction).to include_metadata(
108
94
  "sidekiq_error" => "Sidekiq internal error!"
109
95
  )
110
96
  end
@@ -149,17 +135,11 @@ describe Appsignal::Integrations::SidekiqErrorHandler do
149
135
  end
150
136
 
151
137
  def expect_error_on_transaction
152
- expect(last_transaction.to_h).to include(
153
- "error" => hash_including(
154
- "name" => "ExampleStandardError",
155
- "message" => "uh oh",
156
- "backtrace" => kind_of(String)
157
- )
158
- )
138
+ expect(last_transaction).to have_error("ExampleStandardError", "uh oh")
159
139
  end
160
140
 
161
141
  def expect_no_error_on_transaction
162
- expect(last_transaction.to_h).to include("error" => nil)
142
+ expect(last_transaction).to_not have_error
163
143
  end
164
144
 
165
145
  context "when sidekiq_report_errors = none" do
@@ -270,9 +250,8 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
270
250
  it "filters selected arguments" do
271
251
  perform_sidekiq_job
272
252
 
273
- transaction_hash = transaction.to_h
274
- expect(transaction_hash["sample_data"]).to include(
275
- "params" => [
253
+ expect(transaction).to include_params(
254
+ [
276
255
  "foo",
277
256
  {
278
257
  "foo" => "[FILTERED]",
@@ -293,10 +272,7 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
293
272
  it "replaces the last argument (the secret bag) with an [encrypted data] string" do
294
273
  perform_sidekiq_job
295
274
 
296
- transaction_hash = transaction.to_h
297
- expect(transaction_hash["sample_data"]).to include(
298
- "params" => expected_args << "[encrypted data]"
299
- )
275
+ expect(transaction).to include_params(expected_args << "[encrypted data]")
300
276
  end
301
277
  end
302
278
 
@@ -319,11 +295,8 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
319
295
  it "uses the delayed class and method name for the action" do
320
296
  perform_sidekiq_job
321
297
 
322
- transaction_hash = transaction.to_h
323
- expect(transaction_hash["action"]).to eq("DelayedTestClass.foo_method")
324
- expect(transaction_hash["sample_data"]).to include(
325
- "params" => ["bar" => "baz"]
326
- )
298
+ expect(transaction).to have_action("DelayedTestClass.foo_method")
299
+ expect(transaction).to include_params(["bar" => "baz"])
327
300
  end
328
301
 
329
302
  context "when job arguments is a malformed YAML object", :with_yaml_parse_error => true do
@@ -332,9 +305,8 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
332
305
  it "logs a warning and uses the default argument" do
333
306
  perform_sidekiq_job
334
307
 
335
- transaction_hash = transaction.to_h
336
- expect(transaction_hash["action"]).to eq("Sidekiq::Extensions::DelayedClass#perform")
337
- expect(transaction_hash["sample_data"]).to include("params" => [])
308
+ expect(transaction).to have_action("Sidekiq::Extensions::DelayedClass#perform")
309
+ expect(transaction).to include_params([])
338
310
  expect(log_contents(log)).to contains_log(:warn, "Unable to load YAML")
339
311
  end
340
312
  end
@@ -359,11 +331,8 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
359
331
  it "uses the delayed class and method name for the action" do
360
332
  perform_sidekiq_job
361
333
 
362
- transaction_hash = transaction.to_h
363
- expect(transaction_hash["action"]).to eq("DelayedTestClass#foo_method")
364
- expect(transaction_hash["sample_data"]).to include(
365
- "params" => ["bar" => "baz"]
366
- )
334
+ expect(transaction).to have_action("DelayedTestClass#foo_method")
335
+ expect(transaction).to include_params(["bar" => "baz"])
367
336
  end
368
337
 
369
338
  context "when job arguments is a malformed YAML object", :with_yaml_parse_error => true do
@@ -372,9 +341,8 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
372
341
  it "logs a warning and uses the default argument" do
373
342
  perform_sidekiq_job
374
343
 
375
- transaction_hash = transaction.to_h
376
- expect(transaction_hash["action"]).to eq("Sidekiq::Extensions::DelayedModel#perform")
377
- expect(transaction_hash["sample_data"]).to include("params" => [])
344
+ expect(transaction).to have_action("Sidekiq::Extensions::DelayedModel#perform")
345
+ expect(transaction).to include_params([])
378
346
  expect(log_contents(log)).to contains_log(:warn, "Unable to load YAML")
379
347
  end
380
348
  end
@@ -394,31 +362,20 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
394
362
  perform_sidekiq_job { raise error, "uh oh" }
395
363
  end.to raise_error(error)
396
364
 
397
- transaction_hash = transaction.to_h
398
- expect(transaction_hash).to include(
399
- "id" => jid,
400
- "action" => "TestClass#perform",
401
- "error" => {
402
- "name" => "ExampleException",
403
- "message" => "uh oh",
404
- # TODO: backtrace should be an Array of Strings
405
- # https://github.com/appsignal/appsignal-agent/issues/294
406
- "backtrace" => kind_of(String)
407
- },
408
- "metadata" => {
409
- "extra" => "data",
410
- "queue" => "default",
411
- "retry_count" => "0"
412
- },
413
- "namespace" => namespace,
414
- "sample_data" => {
415
- "environment" => {},
416
- "params" => expected_args,
417
- "tags" => {},
418
- "breadcrumbs" => []
419
- }
365
+ expect(transaction).to have_id(jid)
366
+ expect(transaction).to have_namespace(namespace)
367
+ expect(transaction).to have_action("TestClass#perform")
368
+ expect(transaction).to have_error("ExampleException", "uh oh")
369
+ expect(transaction).to include_metadata(
370
+ "extra" => "data",
371
+ "queue" => "default",
372
+ "retry_count" => "0"
420
373
  )
421
- expect_transaction_to_have_sidekiq_event(transaction_hash)
374
+ expect(transaction).to_not include_environment
375
+ expect(transaction).to include_params(expected_args)
376
+ expect(transaction).to_not include_tags
377
+ expect(transaction).to_not include_breadcrumbs
378
+ expect_transaction_to_have_sidekiq_event(transaction)
422
379
  end
423
380
  end
424
381
 
@@ -438,17 +395,17 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
438
395
  end
439
396
 
440
397
  expect(created_transactions.count).to eq(2)
441
- expected_transaction = {
442
- "namespace" => "background_job",
443
- "action" => "TestClass#perform",
444
- "sample_data" => hash_including(
445
- "tags" => hash_including("test_tag" => "value")
446
- )
447
- }
448
- sidekiq_transaction = created_transactions.first.to_h
449
- error_reporter_transaction = created_transactions.last.to_h
450
- expect(sidekiq_transaction).to include(expected_transaction)
451
- expect(error_reporter_transaction).to include(expected_transaction)
398
+ tags = { "test_tag" => "value" }
399
+ sidekiq_transaction = created_transactions.first
400
+ error_reporter_transaction = created_transactions.last
401
+
402
+ expect(sidekiq_transaction).to have_namespace("background_job")
403
+ expect(sidekiq_transaction).to have_action("TestClass#perform")
404
+ expect(sidekiq_transaction).to include_tags(tags)
405
+
406
+ expect(error_reporter_transaction).to have_namespace("background_job")
407
+ expect(error_reporter_transaction).to have_action("TestClass#perform")
408
+ expect(error_reporter_transaction).to include_tags(tags)
452
409
  end
453
410
  end
454
411
  end
@@ -461,30 +418,21 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
461
418
  .with("sidekiq_queue_job_count", 1, { :queue => "default", :status => :processed })
462
419
  perform_sidekiq_job
463
420
 
464
- transaction_hash = transaction.to_h
465
- expect(transaction_hash).to include(
466
- "id" => jid,
467
- "action" => "TestClass#perform",
468
- "error" => nil,
469
- "metadata" => {
470
- "extra" => "data",
471
- "queue" => "default",
472
- "retry_count" => "0"
473
- },
474
- "namespace" => namespace,
475
- "sample_data" => {
476
- "environment" => {},
477
- "params" => expected_args,
478
- "tags" => {},
479
- "breadcrumbs" => []
480
- }
481
- )
482
- # TODO: Not available in transaction.to_h yet.
483
- # https://github.com/appsignal/appsignal-agent/issues/293
484
- expect(transaction.request.env).to eq(
485
- :queue_start => Time.parse("2001-01-01 10:00:00UTC").to_f
421
+ expect(transaction).to have_id(jid)
422
+ expect(transaction).to have_namespace(namespace)
423
+ expect(transaction).to have_action("TestClass#perform")
424
+ expect(transaction).to_not have_error
425
+ expect(transaction).to_not include_tags
426
+ expect(transaction).to_not include_environment
427
+ expect(transaction).to_not include_breadcrumbs
428
+ expect(transaction).to_not include_params(expected_args)
429
+ expect(transaction).to include_metadata(
430
+ "extra" => "data",
431
+ "queue" => "default",
432
+ "retry_count" => "0"
486
433
  )
487
- expect_transaction_to_have_sidekiq_event(transaction_hash)
434
+ expect(transaction).to have_queue_start(Time.parse("2001-01-01 10:00:00UTC").to_i * 1000)
435
+ expect_transaction_to_have_sidekiq_event(transaction)
488
436
  end
489
437
  end
490
438
 
@@ -505,10 +453,9 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
505
453
  last_transaction
506
454
  end
507
455
 
508
- def expect_transaction_to_have_sidekiq_event(transaction_hash)
509
- events = transaction_hash["events"]
510
- expect(events.count).to eq(1)
511
- expect(events.first).to include(
456
+ def expect_transaction_to_have_sidekiq_event(transaction)
457
+ expect(transaction.to_h["events"].count).to eq(1)
458
+ expect(transaction).to include_event(
512
459
  "name" => "perform_job.sidekiq",
513
460
  "title" => "",
514
461
  "count" => 1,
@@ -621,25 +568,18 @@ if DependencyHelper.active_job_present?
621
568
  perform_sidekiq_job(ActiveJobSidekiqTestJob, given_args)
622
569
 
623
570
  transaction = last_transaction
624
- transaction_hash = transaction.to_h
625
- expect(transaction_hash).to include(
626
- "action" => "ActiveJobSidekiqTestJob#perform",
627
- "error" => nil,
628
- "namespace" => namespace,
629
- "metadata" => hash_including(
630
- "queue" => "default"
631
- ),
632
- "sample_data" => hash_including(
633
- "environment" => {},
634
- "params" => [expected_args],
635
- "tags" => expected_tags.merge("queue" => "default")
636
- )
637
- )
638
- expect(transaction.request.env).to eq(:queue_start => time.to_f)
639
- events = transaction_hash["events"]
571
+ expect(transaction).to have_namespace(namespace)
572
+ expect(transaction).to have_action("ActiveJobSidekiqTestJob#perform")
573
+ expect(transaction).to_not have_error
574
+ expect(transaction).to include_metadata("queue" => "default")
575
+ expect(transaction).to_not include_environment
576
+ expect(transaction).to include_params([expected_args])
577
+ expect(transaction).to include_tags(expected_tags.merge("queue" => "default"))
578
+ expect(transaction).to have_queue_start(time.to_i * 1000)
579
+
580
+ events = transaction.to_h["events"]
640
581
  .sort_by { |e| e["start"] }
641
582
  .map { |event| event["name"] }
642
-
643
583
  expect(events).to eq(expected_perform_events)
644
584
  end
645
585
 
@@ -650,29 +590,18 @@ if DependencyHelper.active_job_present?
650
590
  end.to raise_error(RuntimeError, "uh oh")
651
591
 
652
592
  transaction = last_transaction
653
- transaction_hash = transaction.to_h
654
- expect(transaction_hash).to include(
655
- "action" => "ActiveJobSidekiqErrorTestJob#perform",
656
- "error" => {
657
- "name" => "RuntimeError",
658
- "message" => "uh oh",
659
- "backtrace" => kind_of(String)
660
- },
661
- "namespace" => namespace,
662
- "metadata" => hash_including(
663
- "queue" => "default"
664
- ),
665
- "sample_data" => hash_including(
666
- "environment" => {},
667
- "params" => [expected_args],
668
- "tags" => expected_tags.merge("queue" => "default")
669
- )
670
- )
671
- expect(transaction.request.env).to eq(:queue_start => time.to_f)
672
- events = transaction_hash["events"]
593
+ expect(transaction).to have_namespace(namespace)
594
+ expect(transaction).to have_action("ActiveJobSidekiqErrorTestJob#perform")
595
+ expect(transaction).to have_error("RuntimeError", "uh oh")
596
+ expect(transaction).to include_metadata("queue" => "default")
597
+ expect(transaction).to_not include_environment
598
+ expect(transaction).to include_params([expected_args])
599
+ expect(transaction).to include_tags(expected_tags.merge("queue" => "default"))
600
+ expect(transaction).to have_queue_start(time.to_i * 1000)
601
+
602
+ events = transaction.to_h["events"]
673
603
  .sort_by { |e| e["start"] }
674
604
  .map { |event| event["name"] }
675
-
676
605
  expect(events).to eq(expected_perform_events)
677
606
  end
678
607
  end
@@ -691,13 +620,10 @@ if DependencyHelper.active_job_present?
691
620
  perform_mailer(ActionMailerSidekiqTestJob, :welcome, given_args)
692
621
 
693
622
  transaction = last_transaction
694
- transaction_hash = transaction.to_h
695
- expect(transaction_hash).to include(
696
- "action" => "ActionMailerSidekiqTestJob#welcome",
697
- "sample_data" => hash_including(
698
- "params" => ["ActionMailerSidekiqTestJob", "welcome",
699
- "deliver_now"] + expected_wrapped_args
700
- )
623
+ expect(transaction).to have_action("ActionMailerSidekiqTestJob#welcome")
624
+ expect(transaction).to include_params(
625
+ ["ActionMailerSidekiqTestJob", "welcome",
626
+ "deliver_now"] + expected_wrapped_args
701
627
  )
702
628
  end
703
629
  end
@@ -24,7 +24,6 @@ if DependencyHelper.sinatra_present?
24
24
  it "does not start AppSignal again" do
25
25
  expect(Appsignal::Config).to_not receive(:new)
26
26
  expect(Appsignal).to_not receive(:start)
27
- expect(Appsignal).to_not receive(:start_logger)
28
27
  install_sinatra_integration
29
28
  end
30
29
 
@@ -17,70 +17,59 @@ if DependencyHelper.webmachine_present?
17
17
  let(:request) do
18
18
  Webmachine::Request.new("GET", "http://google.com:80/foo", {}, nil)
19
19
  end
20
- let(:resource) { double(:trace? => false, :handle_exception => true, :"code=" => nil) }
21
- let(:response) { Response.new }
22
- let(:transaction) { double(:set_action_if_nil => true) }
20
+ let(:resource) { double(:trace? => false, :handle_exception => true, :"code=" => nil) }
21
+ let(:response) { Response.new }
23
22
  let(:fsm) { Webmachine::Decision::FSM.new(resource, request, response) }
24
23
  before(:context) { start_agent }
24
+ around { |example| keep_transactions { example.run } }
25
25
 
26
26
  # Make sure the request responds to the method we need to get query params.
27
27
  describe "request" do
28
- it "should respond to `query`" do
28
+ it "responds to #query" do
29
29
  expect(request).to respond_to(:query)
30
30
  end
31
31
  end
32
32
 
33
33
  describe "#run" do
34
- before do
35
- allow(SecureRandom).to receive(:uuid).and_return("uuid")
36
- allow(Appsignal::Transaction).to receive(:create).and_return(transaction)
37
- end
34
+ before { allow(fsm).to receive(:call).and_call_original }
38
35
 
39
- it "should create a transaction" do
40
- expect(Appsignal::Transaction).to receive(:create).with(
41
- "uuid",
42
- Appsignal::Transaction::HTTP_REQUEST,
43
- request,
44
- :params_method => :query
45
- ).and_return(transaction)
36
+ it "creates a transaction" do
37
+ expect { fsm.run }.to(change { created_transactions.count }.by(1))
46
38
  end
47
39
 
48
- it "should set the action" do
49
- expect(transaction).to receive(:set_action_if_nil).with("RSpec::Mocks::Double#GET")
40
+ it "sets the action" do
41
+ fsm.run
42
+ expect(last_transaction).to have_action("RSpec::Mocks::Double#GET")
50
43
  end
51
44
 
52
- it "should call the original method" do
53
- expect(fsm).to receive(:run)
45
+ it "records an instrumentation event" do
46
+ fsm.run
47
+ expect(last_transaction).to include_event("name" => "process_action.webmachine")
54
48
  end
55
49
 
56
- it "should instrument the original method" do
57
- expect(Appsignal).to receive(:instrument).with("process_action.webmachine")
50
+ it "closes the transaction" do
51
+ fsm.run
52
+ expect(last_transaction).to be_completed
53
+ expect(current_transaction?).to be_falsy
58
54
  end
59
55
 
60
- it "should close the transaction" do
61
- expect(Appsignal::Transaction).to receive(:complete_current!)
62
- end
63
-
64
- after { fsm.run }
65
-
66
- describe "concerning the response" do
67
- it "sets a response code" do
68
- expect(fsm.response.code).to be_nil
69
- fsm.run
70
- expect(fsm.response.code).not_to be_nil
71
- end
56
+ it "sets a response code" do
57
+ expect(fsm.response.code).to be_nil
58
+ fsm.run
59
+ expect(fsm.response.code).not_to be_nil
72
60
  end
73
61
  end
74
62
 
75
63
  describe "#handle_exceptions" do
76
- let(:error) { ExampleException }
64
+ let(:error) { ExampleException.new("error message") }
65
+ let(:transaction) { http_request_transaction }
77
66
 
78
- it "should catch the error and send it to AppSignal" do
79
- expect(Appsignal).to receive(:set_error).with(error)
80
- end
67
+ it "tracks the error" do
68
+ with_current_transaction(transaction) do
69
+ fsm.send(:handle_exceptions) { raise error }
70
+ end
81
71
 
82
- after do
83
- fsm.send(:handle_exceptions) { raise error }
72
+ expect(last_transaction).to have_error("ExampleException", "error message")
84
73
  end
85
74
  end
86
75
  end