appsignal 3.10.0-java → 3.11.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +88 -0
  4. data/Gemfile +1 -0
  5. data/benchmark.rake +99 -42
  6. data/lib/appsignal/cli/demo.rb +0 -1
  7. data/lib/appsignal/config.rb +54 -98
  8. data/lib/appsignal/demo.rb +15 -20
  9. data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
  10. data/lib/appsignal/event_formatter.rb +3 -2
  11. data/lib/appsignal/helpers/instrumentation.rb +331 -19
  12. data/lib/appsignal/hooks/action_cable.rb +21 -16
  13. data/lib/appsignal/hooks/active_job.rb +14 -8
  14. data/lib/appsignal/hooks/delayed_job.rb +1 -1
  15. data/lib/appsignal/hooks/shoryuken.rb +3 -63
  16. data/lib/appsignal/integrations/action_cable.rb +5 -7
  17. data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
  18. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
  19. data/lib/appsignal/integrations/data_mapper.rb +1 -0
  20. data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
  21. data/lib/appsignal/integrations/dry_monitor.rb +1 -0
  22. data/lib/appsignal/integrations/excon.rb +1 -0
  23. data/lib/appsignal/integrations/http.rb +1 -0
  24. data/lib/appsignal/integrations/net_http.rb +1 -0
  25. data/lib/appsignal/integrations/object.rb +6 -0
  26. data/lib/appsignal/integrations/que.rb +13 -20
  27. data/lib/appsignal/integrations/railtie.rb +1 -1
  28. data/lib/appsignal/integrations/rake.rb +1 -5
  29. data/lib/appsignal/integrations/redis.rb +1 -0
  30. data/lib/appsignal/integrations/redis_client.rb +1 -0
  31. data/lib/appsignal/integrations/resque.rb +2 -5
  32. data/lib/appsignal/integrations/shoryuken.rb +75 -0
  33. data/lib/appsignal/integrations/sidekiq.rb +7 -15
  34. data/lib/appsignal/integrations/unicorn.rb +1 -0
  35. data/lib/appsignal/integrations/webmachine.rb +2 -5
  36. data/lib/appsignal/logger.rb +7 -3
  37. data/lib/appsignal/probes/helpers.rb +1 -0
  38. data/lib/appsignal/probes/mri.rb +1 -0
  39. data/lib/appsignal/probes/sidekiq.rb +1 -0
  40. data/lib/appsignal/probes.rb +3 -0
  41. data/lib/appsignal/rack/abstract_middleware.rb +18 -12
  42. data/lib/appsignal/rack/event_handler.rb +39 -8
  43. data/lib/appsignal/rack/generic_instrumentation.rb +1 -0
  44. data/lib/appsignal/rack/grape_middleware.rb +2 -1
  45. data/lib/appsignal/rack/streaming_listener.rb +1 -0
  46. data/lib/appsignal/rack.rb +29 -0
  47. data/lib/appsignal/span.rb +1 -0
  48. data/lib/appsignal/transaction.rb +308 -101
  49. data/lib/appsignal/utils/data.rb +0 -1
  50. data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
  51. data/lib/appsignal/utils/integration_logger.rb +0 -13
  52. data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
  53. data/lib/appsignal/utils/json.rb +0 -1
  54. data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
  55. data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
  56. data/lib/appsignal/utils.rb +6 -0
  57. data/lib/appsignal/version.rb +1 -1
  58. data/lib/appsignal.rb +6 -5
  59. data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
  60. data/spec/lib/appsignal/config_spec.rb +138 -43
  61. data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
  62. data/spec/lib/appsignal/hooks/activejob_spec.rb +9 -0
  63. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
  64. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
  65. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
  66. data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
  67. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
  68. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +4 -4
  69. data/spec/lib/appsignal/integrations/webmachine_spec.rb +13 -1
  70. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +48 -3
  71. data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -10
  72. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
  73. data/spec/lib/appsignal/rack_spec.rb +63 -0
  74. data/spec/lib/appsignal/transaction_spec.rb +1634 -1071
  75. data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
  76. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
  77. data/spec/lib/appsignal_spec.rb +323 -10
  78. data/spec/support/helpers/transaction_helpers.rb +44 -20
  79. data/spec/support/matchers/transaction.rb +15 -1
  80. data/spec/support/testing.rb +1 -1
  81. metadata +6 -2
@@ -126,6 +126,7 @@ if DependencyHelper.active_job_present?
126
126
  expect(transaction).to include_params([])
127
127
  expect(transaction).to include_tags(
128
128
  "active_job_id" => kind_of(String),
129
+ "request_id" => kind_of(String),
129
130
  "queue" => queue,
130
131
  "executions" => 1
131
132
  )
@@ -196,6 +197,7 @@ if DependencyHelper.active_job_present?
196
197
  expect(transaction).to include_params([])
197
198
  expect(transaction).to include_tags(
198
199
  "active_job_id" => kind_of(String),
200
+ "request_id" => kind_of(String),
199
201
  "queue" => queue,
200
202
  "executions" => 1
201
203
  )
@@ -335,6 +337,7 @@ if DependencyHelper.active_job_present?
335
337
  expect(transaction).to include_params([])
336
338
  expect(transaction).to include_tags(
337
339
  "active_job_id" => kind_of(String),
340
+ "request_id" => kind_of(String),
338
341
  "queue" => queue,
339
342
  "executions" => 1
340
343
  )
@@ -470,6 +473,7 @@ if DependencyHelper.active_job_present?
470
473
  )
471
474
  expect(transaction).to include_tags(
472
475
  "active_job_id" => kind_of(String),
476
+ "request_id" => kind_of(String),
473
477
  "queue" => "mailers",
474
478
  "executions" => 1
475
479
  )
@@ -488,6 +492,7 @@ if DependencyHelper.active_job_present?
488
492
  )
489
493
  expect(transaction).to include_tags(
490
494
  "active_job_id" => kind_of(String),
495
+ "request_id" => kind_of(String),
491
496
  "queue" => "mailers",
492
497
  "executions" => 1
493
498
  )
@@ -510,6 +515,7 @@ if DependencyHelper.active_job_present?
510
515
  )
511
516
  expect(transaction).to include_tags(
512
517
  "active_job_id" => kind_of(String),
518
+ "request_id" => kind_of(String),
513
519
  "queue" => "mailers",
514
520
  "executions" => 1
515
521
  )
@@ -549,6 +555,7 @@ if DependencyHelper.active_job_present?
549
555
  )
550
556
  expect(transaction).to include_tags(
551
557
  "active_job_id" => kind_of(String),
558
+ "request_id" => kind_of(String),
552
559
  "queue" => "mailers",
553
560
  "executions" => 1
554
561
  )
@@ -573,6 +580,7 @@ if DependencyHelper.active_job_present?
573
580
  )
574
581
  expect(transaction).to include_tags(
575
582
  "active_job_id" => kind_of(String),
583
+ "request_id" => kind_of(String),
576
584
  "queue" => "mailers",
577
585
  "executions" => 1
578
586
  )
@@ -599,6 +607,7 @@ if DependencyHelper.active_job_present?
599
607
  )
600
608
  expect(transaction).to include_tags(
601
609
  "active_job_id" => kind_of(String),
610
+ "request_id" => kind_of(String),
602
611
  "queue" => "mailers",
603
612
  "executions" => 1
604
613
  )
@@ -15,9 +15,7 @@ describe Appsignal::Hooks::DelayedJobHook do
15
15
  end
16
16
  end
17
17
  after(:context) { Object.send(:remove_const, :Delayed) }
18
- before do
19
- start_agent
20
- end
18
+ before { start_agent }
21
19
 
22
20
  describe "#dependencies_present?" do
23
21
  subject { described_class.new.dependencies_present? }
@@ -26,446 +24,7 @@ describe Appsignal::Hooks::DelayedJobHook do
26
24
  end
27
25
 
28
26
  it "adds the plugin" do
29
- expect(::Delayed::Worker.plugins).to include Appsignal::Hooks::DelayedJobPlugin
30
- end
31
-
32
- # We haven't found a way to test the hooks, we'll have to do that manually
33
-
34
- describe ".invoke_with_instrumentation" do
35
- let(:plugin) { Appsignal::Hooks::DelayedJobPlugin }
36
- let(:time) { Time.parse("01-01-2001 10:01:00UTC") }
37
- let(:created_at) { time - 3600 }
38
- let(:run_at) { time - 3600 }
39
- let(:payload_object) { double(:args => args) }
40
- let(:job_data) do
41
- {
42
- :id => 123,
43
- :name => "TestClass#perform",
44
- :priority => 1,
45
- :attempts => 1,
46
- :queue => "default",
47
- :created_at => created_at,
48
- :run_at => run_at,
49
- :payload_object => payload_object
50
- }
51
- end
52
- let(:args) { ["argument"] }
53
- let(:job) { double(job_data) }
54
- let(:invoked_block) { proc {} }
55
-
56
- def perform
57
- Timecop.freeze(time) do
58
- keep_transactions do
59
- plugin.invoke_with_instrumentation(job, invoked_block)
60
- end
61
- end
62
- end
63
-
64
- context "with a normal call" do
65
- it "wraps it in a transaction" do
66
- perform
67
- transaction = last_transaction
68
- expect(transaction).to have_action("TestClass#perform")
69
- expect(transaction).to have_namespace("background_job")
70
- expect(transaction).to_not have_error
71
- expect(transaction).to include_event(:name => "perform_job.delayed_job")
72
- expect(transaction).to include_sample_metadata(
73
- "priority" => 1,
74
- "attempts" => 1,
75
- "queue" => "default",
76
- "id" => "123"
77
- )
78
- expect(transaction).to include_params(["argument"])
79
- end
80
-
81
- context "with more complex params" do
82
- let(:args) do
83
- {
84
- :foo => "Foo",
85
- :bar => "Bar"
86
- }
87
- end
88
-
89
- it "adds the more complex arguments" do
90
- perform
91
-
92
- expect(last_transaction).to include_params("foo" => "Foo", "bar" => "Bar")
93
- end
94
-
95
- context "with parameter filtering" do
96
- before do
97
- Appsignal.config = project_fixture_config("production")
98
- Appsignal.config[:filter_parameters] = ["foo"]
99
- end
100
-
101
- it "filters selected arguments" do
102
- perform
103
-
104
- expect(last_transaction).to include_params("foo" => "[FILTERED]", "bar" => "Bar")
105
- end
106
- end
107
- end
108
-
109
- context "with run_at in the future" do
110
- let(:run_at) { Time.parse("2017-01-01 10:01:00UTC") }
111
-
112
- it "reports queue_start with run_at time" do
113
- perform
114
-
115
- expect(last_transaction).to have_queue_start(run_at.to_i * 1000)
116
- end
117
- end
118
-
119
- context "with class method job" do
120
- let(:job_data) do
121
- { :name => "CustomClassMethod.perform", :payload_object => payload_object }
122
- end
123
-
124
- it "wraps it in a transaction using the class method job name" do
125
- perform
126
- expect(last_transaction).to have_action("CustomClassMethod.perform")
127
- end
128
- end
129
-
130
- context "with custom name call" do
131
- before { perform }
132
-
133
- context "with appsignal_name defined" do
134
- context "with payload_object being an object" do
135
- context "with value" do
136
- let(:payload_object) { double(:appsignal_name => "CustomClass#perform") }
137
-
138
- it "wraps it in a transaction using the custom name" do
139
- expect(last_transaction).to have_action("CustomClass#perform")
140
- end
141
- end
142
-
143
- context "with non-String value" do
144
- let(:payload_object) { double(:appsignal_name => Object.new) }
145
-
146
- it "wraps it in a transaction using the original job name" do
147
- expect(last_transaction).to have_action("TestClass#perform")
148
- end
149
- end
150
-
151
- context "with class method name as job" do
152
- let(:payload_object) { double(:appsignal_name => "CustomClassMethod.perform") }
153
-
154
- it "wraps it in a transaction using the custom name" do
155
- perform
156
- expect(last_transaction).to have_action("CustomClassMethod.perform")
157
- end
158
- end
159
- end
160
-
161
- context "with payload_object being a Hash" do
162
- context "with value" do
163
- let(:payload_object) { double(:appsignal_name => "CustomClassHash#perform") }
164
-
165
- it "wraps it in a transaction using the custom name" do
166
- expect(last_transaction).to have_action("CustomClassHash#perform")
167
- end
168
- end
169
-
170
- context "with non-String value" do
171
- let(:payload_object) { double(:appsignal_name => Object.new) }
172
-
173
- it "wraps it in a transaction using the original job name" do
174
- expect(last_transaction).to have_action("TestClass#perform")
175
- end
176
- end
177
-
178
- context "with class method name as job" do
179
- let(:payload_object) { { :appsignal_name => "CustomClassMethod.perform" } }
180
-
181
- it "wraps it in a transaction using the custom name" do
182
- perform
183
- expect(last_transaction).to have_action("CustomClassMethod.perform")
184
- end
185
- end
186
- end
187
-
188
- context "with payload_object acting like a Hash and returning a non-String value" do
189
- class ClassActingAsHash
190
- def self.[](_key)
191
- Object.new
192
- end
193
-
194
- def self.appsignal_name
195
- "ClassActingAsHash#perform"
196
- end
197
- end
198
- let(:payload_object) { ClassActingAsHash }
199
-
200
- # We check for hash values before object values
201
- # this means ClassActingAsHash returns `Object.new` instead
202
- # of `self.appsignal_name`. Since this isn't a valid `String`
203
- # we return the default job name as action name.
204
- it "wraps it in a transaction using the original job name" do
205
- expect(last_transaction).to have_action("TestClass#perform")
206
- end
207
- end
208
- end
209
- end
210
-
211
- context "with only job class name" do
212
- let(:job_data) do
213
- { :name => "Banana", :payload_object => payload_object }
214
- end
215
-
216
- it "appends #perform to the class name" do
217
- perform
218
- expect(last_transaction).to have_action("Banana#perform")
219
- end
220
- end
221
-
222
- if active_job_present?
223
- require "active_job"
224
-
225
- context "when wrapped by ActiveJob" do
226
- let(:payload_object) do
227
- ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper.new(
228
- "arguments" => args,
229
- "job_class" => "TestClass",
230
- "job_id" => 123,
231
- "locale" => :en,
232
- "queue_name" => "default"
233
- )
234
- end
235
- let(:job) do
236
- double(
237
- :id => 123,
238
- :name => "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper",
239
- :priority => 1,
240
- :attempts => 1,
241
- :queue => "default",
242
- :created_at => created_at,
243
- :run_at => run_at,
244
- :payload_object => payload_object
245
- )
246
- end
247
- let(:args) { ["activejob_argument"] }
248
-
249
- it "wraps it in a transaction with the correct params" do
250
- perform
251
-
252
- transaction = last_transaction
253
- expect(transaction).to have_namespace("background_job")
254
- expect(transaction).to have_action("TestClass#perform")
255
- expect(transaction).to_not have_error
256
- expect(transaction).to include_event("name" => "perform_job.delayed_job")
257
- expect(transaction).to include_sample_metadata(
258
- "priority" => 1,
259
- "attempts" => 1,
260
- "queue" => "default",
261
- "id" => "123"
262
- )
263
- expect(transaction).to include_params(["activejob_argument"])
264
- end
265
-
266
- context "with more complex params" do
267
- let(:args) do
268
- {
269
- :foo => "Foo",
270
- :bar => "Bar"
271
- }
272
- end
273
-
274
- it "adds the more complex arguments" do
275
- perform
276
- transaction = last_transaction
277
- expect(transaction).to have_action("TestClass#perform")
278
- expect(transaction).to include_params(
279
- "foo" => "Foo",
280
- "bar" => "Bar"
281
- )
282
- end
283
-
284
- context "with parameter filtering" do
285
- before do
286
- Appsignal.config = project_fixture_config("production")
287
- Appsignal.config[:filter_parameters] = ["foo"]
288
- end
289
-
290
- it "filters selected arguments" do
291
- perform
292
- transaction = last_transaction
293
- expect(transaction).to have_action("TestClass#perform")
294
- expect(transaction).to include_params(
295
- "foo" => "[FILTERED]",
296
- "bar" => "Bar"
297
- )
298
- end
299
- end
300
- end
301
-
302
- context "with run_at in the future" do
303
- let(:run_at) { Time.parse("2017-01-01 10:01:00UTC") }
304
-
305
- it "reports queue_start with run_at time" do
306
- perform
307
-
308
- expect(last_transaction).to have_queue_start(run_at.to_i * 1000)
309
- end
310
- end
311
- end
312
- end
313
- end
314
-
315
- context "with an erroring call" do
316
- let(:error) { ExampleException.new("uh oh") }
317
- before do
318
- expect(invoked_block).to receive(:call).and_raise(error)
319
- end
320
-
321
- it "adds the error to the transaction" do
322
- expect do
323
- perform
324
- end.to raise_error(error)
325
-
326
- transaction = last_transaction
327
- expect(transaction).to have_namespace("background_job")
328
- expect(transaction).to have_action("TestClass#perform")
329
- expect(transaction).to have_error("ExampleException", "uh oh")
330
- end
331
- end
332
- end
333
-
334
- describe ".extract_value" do
335
- let(:plugin) { Appsignal::Hooks::DelayedJobPlugin }
336
-
337
- context "for a hash" do
338
- let(:hash) { { :key => "value", :bool_false => false } }
339
-
340
- context "when the key exists" do
341
- subject { plugin.extract_value(hash, :key) }
342
-
343
- it { is_expected.to eq "value" }
344
-
345
- context "when the value is false" do
346
- subject { plugin.extract_value(hash, :bool_false) }
347
-
348
- it { is_expected.to be false }
349
- end
350
- end
351
-
352
- context "when the key does not exist" do
353
- subject { plugin.extract_value(hash, :nonexistent_key) }
354
-
355
- it { is_expected.to be_nil }
356
-
357
- context "with a default value" do
358
- subject { plugin.extract_value(hash, :nonexistent_key, 1) }
359
-
360
- it { is_expected.to eq 1 }
361
- end
362
- end
363
- end
364
-
365
- context "for a struct" do
366
- before :context do
367
- TestStruct = Struct.new(:key)
368
- end
369
- let(:struct) { TestStruct.new("value") }
370
-
371
- context "when the key exists" do
372
- subject { plugin.extract_value(struct, :key) }
373
-
374
- it { is_expected.to eq "value" }
375
- end
376
-
377
- context "when the key does not exist" do
378
- subject { plugin.extract_value(struct, :nonexistent_key) }
379
-
380
- it { is_expected.to be_nil }
381
-
382
- context "with a default value" do
383
- subject { plugin.extract_value(struct, :nonexistent_key, 1) }
384
-
385
- it { is_expected.to eq 1 }
386
- end
387
- end
388
- end
389
-
390
- context "for a struct with a method" do
391
- before :context do
392
- class TestStructClass < Struct.new(:id) # rubocop:disable Style/StructInheritance
393
- def appsignal_name
394
- "TestStruct#perform"
395
- end
396
-
397
- def bool_false
398
- false
399
- end
400
- end
401
- end
402
- let(:struct) { TestStructClass.new("id") }
403
-
404
- context "when the Struct responds to a method" do
405
- subject { plugin.extract_value(struct, :appsignal_name) }
406
-
407
- it "returns the method value" do
408
- is_expected.to eq "TestStruct#perform"
409
- end
410
-
411
- context "when the value is false" do
412
- subject { plugin.extract_value(struct, :bool_false) }
413
-
414
- it "returns the method value" do
415
- is_expected.to be false
416
- end
417
- end
418
- end
419
-
420
- context "when the key does not exist" do
421
- subject { plugin.extract_value(struct, :nonexistent_key) }
422
-
423
- context "without a method with the same name" do
424
- it "returns nil" do
425
- is_expected.to be_nil
426
- end
427
- end
428
-
429
- context "with a default value" do
430
- let(:default_value) { :my_default_value }
431
- subject { plugin.extract_value(struct, :nonexistent_key, default_value) }
432
-
433
- it "returns the default value" do
434
- is_expected.to eq default_value
435
- end
436
- end
437
- end
438
- end
439
-
440
- context "for an object" do
441
- let(:object) { double(:existing_method => "value") }
442
-
443
- context "when the method exists" do
444
- subject { plugin.extract_value(object, :existing_method) }
445
-
446
- it { is_expected.to eq "value" }
447
- end
448
-
449
- context "when the method does not exist" do
450
- subject { plugin.extract_value(object, :nonexistent_method) }
451
-
452
- it { is_expected.to be_nil }
453
-
454
- context "and there is a default value" do
455
- subject { plugin.extract_value(object, :nonexistent_method, 1) }
456
-
457
- it { is_expected.to eq 1 }
458
- end
459
- end
460
- end
461
-
462
- context "when we need to call to_s on the value" do
463
- let(:object) { double(:existing_method => 1) }
464
-
465
- subject { plugin.extract_value(object, :existing_method, nil, true) }
466
-
467
- it { is_expected.to eq "1" }
468
- end
27
+ expect(::Delayed::Worker.plugins).to include(Appsignal::Integrations::DelayedJobPlugin)
469
28
  end
470
29
  end
471
30
 
@@ -1,174 +1,3 @@
1
- describe Appsignal::Hooks::ShoryukenMiddleware do
2
- class DemoShoryukenWorker
3
- end
4
-
5
- let(:time) { "2010-01-01 10:01:00UTC" }
6
- let(:worker_instance) { DemoShoryukenWorker.new }
7
- let(:queue) { "some-funky-queue-name" }
8
- let(:sqs_msg) { double(:message_id => "msg1", :attributes => {}) }
9
- let(:body) { {} }
10
- before(:context) { start_agent }
11
- around { |example| keep_transactions { example.run } }
12
-
13
- def perform_shoryuken_job(&block)
14
- block ||= lambda {}
15
- Timecop.freeze(Time.parse(time)) do
16
- Appsignal::Hooks::ShoryukenMiddleware.new.call(
17
- worker_instance,
18
- queue,
19
- sqs_msg,
20
- body,
21
- &block
22
- )
23
- end
24
- end
25
-
26
- context "with a performance call" do
27
- let(:sent_timestamp) { Time.parse("1976-11-18 0:00:00UTC").to_i * 1000 }
28
- let(:sqs_msg) do
29
- double(:message_id => "msg1", :attributes => { "SentTimestamp" => sent_timestamp })
30
- end
31
-
32
- context "with complex argument" do
33
- let(:body) { { :foo => "Foo", :bar => "Bar" } }
34
-
35
- it "wraps the job in a transaction with the correct params" do
36
- allow_any_instance_of(Appsignal::Transaction).to receive(:set_queue_start).and_call_original
37
- expect { perform_shoryuken_job }.to change { created_transactions.length }.by(1)
38
-
39
- transaction = last_transaction
40
- expect(transaction).to have_id
41
- expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
42
- expect(transaction).to have_action("DemoShoryukenWorker#perform")
43
- expect(transaction).to_not have_error
44
- expect(transaction).to include_event(
45
- "body" => "",
46
- "body_format" => Appsignal::EventFormatter::DEFAULT,
47
- "count" => 1,
48
- "name" => "perform_job.shoryuken",
49
- "title" => ""
50
- )
51
- expect(transaction).to include_params("foo" => "Foo", "bar" => "Bar")
52
- expect(transaction).to include_sample_metadata(
53
- "message_id" => "msg1",
54
- "queue" => queue,
55
- "SentTimestamp" => sent_timestamp
56
- )
57
- expect(transaction).to have_queue_start(sent_timestamp)
58
- expect(transaction).to be_completed
59
- end
60
-
61
- context "with parameter filtering" do
62
- before do
63
- Appsignal.config = project_fixture_config("production")
64
- Appsignal.config[:filter_parameters] = ["foo"]
65
- end
66
- after do
67
- Appsignal.config[:filter_parameters] = []
68
- end
69
-
70
- it "filters selected arguments" do
71
- perform_shoryuken_job
72
-
73
- expect(last_transaction).to include_params("foo" => "[FILTERED]", "bar" => "Bar")
74
- end
75
- end
76
- end
77
-
78
- context "with a string as an argument" do
79
- let(:body) { "foo bar" }
80
-
81
- it "handles string arguments" do
82
- perform_shoryuken_job
83
-
84
- expect(last_transaction).to include_params("params" => body)
85
- end
86
- end
87
-
88
- context "with primitive type as argument" do
89
- let(:body) { 1 }
90
-
91
- it "handles primitive types as arguments" do
92
- perform_shoryuken_job
93
-
94
- expect(last_transaction).to include_params("params" => body)
95
- end
96
- end
97
- end
98
-
99
- context "with exception" do
100
- it "sets the exception on the transaction" do
101
- expect do
102
- expect do
103
- perform_shoryuken_job { raise ExampleException, "error message" }
104
- end.to raise_error(ExampleException)
105
- end.to change { created_transactions.length }.by(1)
106
-
107
- transaction = last_transaction
108
- expect(transaction).to have_id
109
- expect(transaction).to have_action("DemoShoryukenWorker#perform")
110
- expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
111
- expect(transaction).to have_error("ExampleException", "error message")
112
- expect(transaction).to be_completed
113
- end
114
- end
115
-
116
- context "with batched jobs" do
117
- let(:sqs_msg) do
118
- [
119
- double(
120
- :message_id => "msg2",
121
- :attributes => {
122
- "SentTimestamp" => (Time.parse("1976-11-18 01:00:00UTC").to_i * 1000).to_s
123
- }
124
- ),
125
- double(
126
- :message_id => "msg1",
127
- :attributes => { "SentTimestamp" => sent_timestamp.to_s }
128
- )
129
- ]
130
- end
131
- let(:body) do
132
- [
133
- "foo bar",
134
- { :id => "123", :foo => "Foo", :bar => "Bar" }
135
- ]
136
- end
137
- let(:sent_timestamp) { Time.parse("1976-11-18 01:00:00UTC").to_i * 1000 }
138
-
139
- it "creates a transaction for the batch" do
140
- allow_any_instance_of(Appsignal::Transaction).to receive(:set_queue_start).and_call_original
141
- expect do
142
- perform_shoryuken_job {} # rubocop:disable Lint/EmptyBlock
143
- end.to change { created_transactions.length }.by(1)
144
-
145
- transaction = last_transaction
146
- expect(transaction).to have_id
147
- expect(transaction).to have_action("DemoShoryukenWorker#perform")
148
- expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
149
- expect(transaction).to_not have_error
150
- expect(transaction).to include_event(
151
- "body" => "",
152
- "body_format" => Appsignal::EventFormatter::DEFAULT,
153
- "count" => 1,
154
- "name" => "perform_job.shoryuken",
155
- "title" => ""
156
- )
157
- expect(transaction).to include_params(
158
- "msg2" => "foo bar",
159
- "msg1" => { "id" => "123", "foo" => "Foo", "bar" => "Bar" }
160
- )
161
- expect(transaction).to include_sample_metadata(
162
- "batch" => true,
163
- "queue" => "some-funky-queue-name",
164
- "SentTimestamp" => sent_timestamp.to_s # Earliest/oldest timestamp from messages
165
- )
166
- # Queue time based on earliest/oldest timestamp from messages
167
- expect(transaction).to have_queue_start(sent_timestamp)
168
- end
169
- end
170
- end
171
-
172
1
  describe Appsignal::Hooks::ShoryukenHook do
173
2
  context "with shoryuken" do
174
3
  before(:context) do