appsignal 2.11.8-java → 3.0.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/.rubocop_todo.yml +1 -1
  4. data/.semaphore/semaphore.yml +88 -111
  5. data/CHANGELOG.md +24 -0
  6. data/appsignal.gemspec +1 -1
  7. data/build_matrix.yml +11 -15
  8. data/lib/appsignal.rb +2 -29
  9. data/lib/appsignal/auth_check.rb +2 -8
  10. data/lib/appsignal/cli.rb +1 -23
  11. data/lib/appsignal/config.rb +1 -25
  12. data/lib/appsignal/event_formatter.rb +0 -25
  13. data/lib/appsignal/helpers/instrumentation.rb +69 -5
  14. data/lib/appsignal/hooks.rb +6 -13
  15. data/lib/appsignal/hooks/action_cable.rb +3 -34
  16. data/lib/appsignal/hooks/active_support_notifications.rb +7 -86
  17. data/lib/appsignal/hooks/celluloid.rb +5 -9
  18. data/lib/appsignal/hooks/net_http.rb +2 -12
  19. data/lib/appsignal/hooks/puma.rb +3 -5
  20. data/lib/appsignal/hooks/que.rb +1 -1
  21. data/lib/appsignal/hooks/rake.rb +2 -24
  22. data/lib/appsignal/hooks/redis.rb +2 -13
  23. data/lib/appsignal/hooks/resque.rb +2 -43
  24. data/lib/appsignal/hooks/sidekiq.rb +6 -143
  25. data/lib/appsignal/hooks/unicorn.rb +3 -24
  26. data/lib/appsignal/hooks/webmachine.rb +1 -7
  27. data/lib/appsignal/integrations/action_cable.rb +34 -0
  28. data/lib/appsignal/integrations/active_support_notifications.rb +77 -0
  29. data/lib/appsignal/integrations/net_http.rb +16 -0
  30. data/lib/appsignal/integrations/object.rb +39 -4
  31. data/lib/appsignal/integrations/padrino.rb +5 -7
  32. data/lib/appsignal/integrations/que.rb +26 -33
  33. data/lib/appsignal/integrations/railtie.rb +1 -4
  34. data/lib/appsignal/integrations/rake.rb +26 -2
  35. data/lib/appsignal/integrations/redis.rb +17 -0
  36. data/lib/appsignal/integrations/resque.rb +39 -10
  37. data/lib/appsignal/integrations/sidekiq.rb +171 -0
  38. data/lib/appsignal/integrations/unicorn.rb +28 -0
  39. data/lib/appsignal/integrations/webmachine.rb +22 -24
  40. data/lib/appsignal/minutely.rb +0 -12
  41. data/lib/appsignal/version.rb +1 -1
  42. data/spec/lib/appsignal/auth_check_spec.rb +1 -24
  43. data/spec/lib/appsignal/cli_spec.rb +1 -1
  44. data/spec/lib/appsignal/config_spec.rb +2 -66
  45. data/spec/lib/appsignal/event_formatter_spec.rb +0 -37
  46. data/spec/lib/appsignal/hooks/celluloid_spec.rb +6 -1
  47. data/spec/lib/appsignal/hooks/rake_spec.rb +1 -2
  48. data/spec/lib/appsignal/hooks/redis_spec.rb +50 -15
  49. data/spec/lib/appsignal/hooks/sidekiq_spec.rb +12 -464
  50. data/spec/lib/appsignal/hooks/unicorn_spec.rb +14 -3
  51. data/spec/lib/appsignal/hooks/webmachine_spec.rb +2 -13
  52. data/spec/lib/appsignal/hooks_spec.rb +6 -22
  53. data/spec/lib/appsignal/integrations/object_spec.rb +91 -8
  54. data/spec/lib/appsignal/integrations/padrino_spec.rb +2 -3
  55. data/spec/lib/appsignal/integrations/railtie_spec.rb +0 -45
  56. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +524 -0
  57. data/spec/lib/appsignal/integrations/webmachine_spec.rb +26 -8
  58. data/spec/lib/appsignal/minutely_spec.rb +0 -19
  59. data/spec/lib/appsignal/transaction_spec.rb +1 -14
  60. data/spec/lib/appsignal/transmitter_spec.rb +1 -1
  61. data/spec/lib/appsignal_spec.rb +162 -116
  62. data/spec/spec_helper.rb +1 -15
  63. metadata +11 -21
  64. data/lib/appsignal/cli/notify_of_deploy.rb +0 -131
  65. data/lib/appsignal/integrations/object_ruby_19.rb +0 -37
  66. data/lib/appsignal/integrations/object_ruby_modern.rb +0 -64
  67. data/lib/appsignal/integrations/resque_active_job.rb +0 -19
  68. data/lib/appsignal/js_exception_transaction.rb +0 -56
  69. data/lib/appsignal/rack/js_exception_catcher.rb +0 -80
  70. data/spec/lib/appsignal/cli/notify_of_deploy_spec.rb +0 -180
  71. data/spec/lib/appsignal/integrations/object_19_spec.rb +0 -266
  72. data/spec/lib/appsignal/integrations/resque_active_job_spec.rb +0 -28
  73. data/spec/lib/appsignal/integrations/resque_spec.rb +0 -28
  74. data/spec/lib/appsignal/js_exception_transaction_spec.rb +0 -128
  75. data/spec/lib/appsignal/rack/js_exception_catcher_spec.rb +0 -170
@@ -3,6 +3,11 @@ describe Appsignal::Hooks::CelluloidHook do
3
3
  before :context do
4
4
  module Celluloid
5
5
  def self.shutdown
6
+ @shut_down = true
7
+ end
8
+
9
+ def self.shut_down?
10
+ @shut_down == true
6
11
  end
7
12
  end
8
13
  Appsignal::Hooks::CelluloidHook.new.install
@@ -18,7 +23,7 @@ describe Appsignal::Hooks::CelluloidHook do
18
23
  end
19
24
 
20
25
  specify { expect(Appsignal).to receive(:stop) }
21
- specify { expect(Celluloid).to receive(:shutdown_without_appsignal) }
26
+ specify { expect(Celluloid.shut_down?).to be true }
22
27
 
23
28
  after do
24
29
  Celluloid.shutdown
@@ -20,8 +20,7 @@ describe Appsignal::Hooks::RakeHook do
20
20
  end
21
21
 
22
22
  it "calls the original task" do
23
- expect(task).to receive(:execute_without_appsignal).with(arguments)
24
- perform
23
+ expect(perform).to eq([])
25
24
  end
26
25
  end
27
26
 
@@ -1,33 +1,68 @@
1
1
  describe Appsignal::Hooks::RedisHook do
2
2
  before do
3
3
  Appsignal.config = project_fixture_config
4
- Appsignal::Hooks.load_hooks
5
4
  end
6
5
 
7
6
  if DependencyHelper.redis_present?
8
7
  context "with redis" do
9
8
  context "with instrumentation enabled" do
10
- before do
11
- Appsignal.config.config_hash[:instrument_redis] = true
12
- allow_any_instance_of(Redis::Client).to receive(:process_without_appsignal).and_return(1)
13
- end
14
-
15
9
  describe "#dependencies_present?" do
16
10
  subject { described_class.new.dependencies_present? }
17
11
 
18
12
  it { is_expected.to be_truthy }
19
13
  end
20
14
 
21
- it "should instrument a redis call" do
22
- Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
23
- expect(Appsignal::Transaction.current).to receive(:start_event)
24
- .at_least(:once)
25
- expect(Appsignal::Transaction.current).to receive(:finish_event)
26
- .at_least(:once)
27
- .with("query.redis", "redis://127.0.0.1:6379/0", "get ?", 0)
15
+ describe "integration" do
16
+ before do
17
+ Appsignal.config.config_hash[:instrument_redis] = true
18
+ end
19
+
20
+ context "install" do
21
+ before do
22
+ Appsignal::Hooks.load_hooks
23
+ end
24
+
25
+ it "does something" do
26
+ # Test if the last included module (prepended module) was our
27
+ # integration. That's not certain with the assertions below
28
+ # because we have to overwrite the `process` method for the test.
29
+ expect(Redis::Client.included_modules.first)
30
+ .to eql(Appsignal::Integrations::RedisIntegration)
31
+ end
32
+ end
33
+
34
+ context "instrumentation" do
35
+ before do
36
+ # Stub Redis::Client class so that it doesn't perform an actual
37
+ # Redis query. This class will be included (prepended) with the
38
+ # AppSignal Redis integration.
39
+ stub_const("Redis::Client", Class.new do
40
+ def id
41
+ :stub_id
42
+ end
43
+
44
+ def process(_commands)
45
+ :stub_process
46
+ end
47
+ end)
48
+ # Load the integration again for the stubbed Redis::Client class.
49
+ # Call it directly because {Appsignal::Hooks.load_hooks} keeps
50
+ # track if it was installed already or not.
51
+ Appsignal::Hooks::RedisHook.new.install
52
+ end
53
+
54
+ it "instrument a redis call" do
55
+ Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
56
+ expect(Appsignal::Transaction.current).to receive(:start_event)
57
+ .at_least(:once)
58
+ expect(Appsignal::Transaction.current).to receive(:finish_event)
59
+ .at_least(:once)
60
+ .with("query.redis", :stub_id, "get ?", 0)
28
61
 
29
- client = Redis::Client.new
30
- expect(client.process([[:get, "key"]])).to eq 1
62
+ client = Redis::Client.new
63
+ expect(client.process([[:get, "key"]])).to eql(:stub_process)
64
+ end
65
+ end
31
66
  end
32
67
  end
33
68
 
@@ -51,6 +51,10 @@ describe Appsignal::Hooks::SidekiqHook do
51
51
  yield middlewares if block_given?
52
52
  middlewares
53
53
  end
54
+
55
+ def self.error_handlers
56
+ @error_handlers ||= []
57
+ end
54
58
  end
55
59
 
56
60
  def add_middleware(middleware)
@@ -64,6 +68,12 @@ describe Appsignal::Hooks::SidekiqHook do
64
68
  stub_const "Sidekiq", SidekiqMock
65
69
  end
66
70
 
71
+ it "adds error handler" do
72
+ Sidekiq.middleware_mock = SidekiqMiddlewareMockWithPrepend
73
+ described_class.new.install
74
+ expect(Sidekiq.error_handlers).to include(Appsignal::Integrations::SidekiqErrorHandler)
75
+ end
76
+
67
77
  context "when Sidekiq middleware responds to prepend method" do # Sidekiq 3.3.0 and newer
68
78
  before { Sidekiq.middleware_mock = SidekiqMiddlewareMockWithPrepend }
69
79
 
@@ -75,7 +85,7 @@ describe Appsignal::Hooks::SidekiqHook do
75
85
  add_middleware(user_middleware2)
76
86
 
77
87
  expect(Sidekiq.server_middleware).to eql([
78
- Appsignal::Hooks::SidekiqPlugin, # Prepend makes it the first entry
88
+ Appsignal::Integrations::SidekiqMiddleware, # Prepend makes it the first entry
79
89
  user_middleware1,
80
90
  user_middleware2
81
91
  ])
@@ -95,472 +105,10 @@ describe Appsignal::Hooks::SidekiqHook do
95
105
  # Add middlewares in whatever order they were added
96
106
  expect(Sidekiq.server_middleware).to eql([
97
107
  user_middleware1,
98
- Appsignal::Hooks::SidekiqPlugin,
108
+ Appsignal::Integrations::SidekiqMiddleware,
99
109
  user_middleware2
100
110
  ])
101
111
  end
102
112
  end
103
113
  end
104
114
  end
105
-
106
- describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
107
- class DelayedTestClass; end
108
-
109
- let(:namespace) { Appsignal::Transaction::BACKGROUND_JOB }
110
- let(:worker) { anything }
111
- let(:queue) { anything }
112
- let(:given_args) do
113
- [
114
- "foo",
115
- {
116
- :foo => "Foo",
117
- :bar => "Bar",
118
- "baz" => { 1 => :foo }
119
- }
120
- ]
121
- end
122
- let(:expected_args) do
123
- [
124
- "foo",
125
- {
126
- "foo" => "Foo",
127
- "bar" => "Bar",
128
- "baz" => { "1" => "foo" }
129
- }
130
- ]
131
- end
132
- let(:job_class) { "TestClass" }
133
- let(:jid) { "b4a577edbccf1d805744efa9" }
134
- let(:item) do
135
- {
136
- "jid" => jid,
137
- "class" => job_class,
138
- "retry_count" => 0,
139
- "queue" => "default",
140
- "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
141
- "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
142
- "args" => given_args,
143
- "extra" => "data"
144
- }
145
- end
146
- let(:plugin) { Appsignal::Hooks::SidekiqPlugin.new }
147
- let(:log) { StringIO.new }
148
- before do
149
- start_agent
150
- Appsignal.logger = test_logger(log)
151
- end
152
- around { |example| keep_transactions { example.run } }
153
- after :with_yaml_parse_error => false do
154
- expect(log_contents(log)).to_not contains_log(:warn, "Unable to load YAML")
155
- end
156
-
157
- describe "internal Sidekiq job values" do
158
- it "does not save internal Sidekiq values as metadata on transaction" do
159
- perform_job
160
-
161
- transaction_hash = transaction.to_h
162
- expect(transaction_hash["metadata"].keys)
163
- .to_not include(*Appsignal::Hooks::SidekiqPlugin::EXCLUDED_JOB_KEYS)
164
- end
165
- end
166
-
167
- context "with parameter filtering" do
168
- before do
169
- Appsignal.config = project_fixture_config("production")
170
- Appsignal.config[:filter_parameters] = ["foo"]
171
- end
172
-
173
- it "filters selected arguments" do
174
- perform_job
175
-
176
- transaction_hash = transaction.to_h
177
- expect(transaction_hash["sample_data"]).to include(
178
- "params" => [
179
- "foo",
180
- {
181
- "foo" => "[FILTERED]",
182
- "bar" => "Bar",
183
- "baz" => { "1" => "foo" }
184
- }
185
- ]
186
- )
187
- end
188
- end
189
-
190
- context "with encrypted arguments" do
191
- before do
192
- item["encrypt"] = true
193
- item["args"] << "super secret value" # Last argument will be replaced
194
- end
195
-
196
- it "replaces the last argument (the secret bag) with an [encrypted data] string" do
197
- perform_job
198
-
199
- transaction_hash = transaction.to_h
200
- expect(transaction_hash["sample_data"]).to include(
201
- "params" => expected_args << "[encrypted data]"
202
- )
203
- end
204
- end
205
-
206
- context "when using the Sidekiq delayed extension" do
207
- let(:item) do
208
- {
209
- "jid" => jid,
210
- "class" => "Sidekiq::Extensions::DelayedClass",
211
- "queue" => "default",
212
- "args" => [
213
- "---\n- !ruby/class 'DelayedTestClass'\n- :foo_method\n- - :bar: baz\n"
214
- ],
215
- "retry" => true,
216
- "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
217
- "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
218
- "extra" => "data"
219
- }
220
- end
221
-
222
- it "uses the delayed class and method name for the action" do
223
- perform_job
224
-
225
- transaction_hash = transaction.to_h
226
- expect(transaction_hash["action"]).to eq("DelayedTestClass.foo_method")
227
- expect(transaction_hash["sample_data"]).to include(
228
- "params" => ["bar" => "baz"]
229
- )
230
- end
231
-
232
- context "when job arguments is a malformed YAML object", :with_yaml_parse_error => true do
233
- before { item["args"] = [] }
234
-
235
- it "logs a warning and uses the default argument" do
236
- perform_job
237
-
238
- transaction_hash = transaction.to_h
239
- expect(transaction_hash["action"]).to eq("Sidekiq::Extensions::DelayedClass#perform")
240
- expect(transaction_hash["sample_data"]).to include("params" => [])
241
- expect(log_contents(log)).to contains_log(:warn, "Unable to load YAML")
242
- end
243
- end
244
- end
245
-
246
- context "when using the Sidekiq ActiveRecord instance delayed extension" do
247
- let(:item) do
248
- {
249
- "jid" => jid,
250
- "class" => "Sidekiq::Extensions::DelayedModel",
251
- "queue" => "default",
252
- "args" => [
253
- "---\n- !ruby/object:DelayedTestClass {}\n- :foo_method\n- - :bar: :baz\n"
254
- ],
255
- "retry" => true,
256
- "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
257
- "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
258
- "extra" => "data"
259
- }
260
- end
261
-
262
- it "uses the delayed class and method name for the action" do
263
- perform_job
264
-
265
- transaction_hash = transaction.to_h
266
- expect(transaction_hash["action"]).to eq("DelayedTestClass#foo_method")
267
- expect(transaction_hash["sample_data"]).to include(
268
- "params" => ["bar" => "baz"]
269
- )
270
- end
271
-
272
- context "when job arguments is a malformed YAML object", :with_yaml_parse_error => true do
273
- before { item["args"] = [] }
274
-
275
- it "logs a warning and uses the default argument" do
276
- perform_job
277
-
278
- transaction_hash = transaction.to_h
279
- expect(transaction_hash["action"]).to eq("Sidekiq::Extensions::DelayedModel#perform")
280
- expect(transaction_hash["sample_data"]).to include("params" => [])
281
- expect(log_contents(log)).to contains_log(:warn, "Unable to load YAML")
282
- end
283
- end
284
- end
285
-
286
- context "with an error" do
287
- let(:error) { ExampleException }
288
-
289
- it "creates a transaction and adds the error" do
290
- expect(Appsignal).to receive(:increment_counter)
291
- .with("sidekiq_queue_job_count", 1, :queue => "default", :status => :failed)
292
- expect(Appsignal).to receive(:increment_counter)
293
- .with("sidekiq_queue_job_count", 1, :queue => "default", :status => :processed)
294
-
295
- expect do
296
- perform_job { raise error, "uh oh" }
297
- end.to raise_error(error)
298
-
299
- transaction_hash = transaction.to_h
300
- expect(transaction_hash).to include(
301
- "id" => jid,
302
- "action" => "TestClass#perform",
303
- "error" => {
304
- "name" => "ExampleException",
305
- "message" => "uh oh",
306
- # TODO: backtrace should be an Array of Strings
307
- # https://github.com/appsignal/appsignal-agent/issues/294
308
- "backtrace" => kind_of(String)
309
- },
310
- "metadata" => {
311
- "extra" => "data",
312
- "queue" => "default",
313
- "retry_count" => "0"
314
- },
315
- "namespace" => namespace,
316
- "sample_data" => {
317
- "environment" => {},
318
- "params" => expected_args,
319
- "tags" => {},
320
- "breadcrumbs" => []
321
- }
322
- )
323
- expect_transaction_to_have_sidekiq_event(transaction_hash)
324
- end
325
- end
326
-
327
- context "without an error" do
328
- it "creates a transaction with events" do
329
- expect(Appsignal).to receive(:increment_counter)
330
- .with("sidekiq_queue_job_count", 1, :queue => "default", :status => :processed)
331
-
332
- perform_job
333
-
334
- transaction_hash = transaction.to_h
335
- expect(transaction_hash).to include(
336
- "id" => jid,
337
- "action" => "TestClass#perform",
338
- "error" => nil,
339
- "metadata" => {
340
- "extra" => "data",
341
- "queue" => "default",
342
- "retry_count" => "0"
343
- },
344
- "namespace" => namespace,
345
- "sample_data" => {
346
- "environment" => {},
347
- "params" => expected_args,
348
- "tags" => {},
349
- "breadcrumbs" => []
350
- }
351
- )
352
- # TODO: Not available in transaction.to_h yet.
353
- # https://github.com/appsignal/appsignal-agent/issues/293
354
- expect(transaction.request.env).to eq(
355
- :queue_start => Time.parse("2001-01-01 10:00:00UTC").to_f
356
- )
357
- expect_transaction_to_have_sidekiq_event(transaction_hash)
358
- end
359
- end
360
-
361
- def perform_job
362
- Timecop.freeze(Time.parse("2001-01-01 10:01:00UTC")) do
363
- plugin.call(worker, item, queue) do
364
- yield if block_given?
365
- end
366
- end
367
- end
368
-
369
- def transaction
370
- last_transaction
371
- end
372
-
373
- def expect_transaction_to_have_sidekiq_event(transaction_hash)
374
- events = transaction_hash["events"]
375
- expect(events.count).to eq(1)
376
- expect(events.first).to include(
377
- "name" => "perform_job.sidekiq",
378
- "title" => "",
379
- "count" => 1,
380
- "body" => "",
381
- "body_format" => Appsignal::EventFormatter::DEFAULT
382
- )
383
- end
384
- end
385
-
386
- if DependencyHelper.active_job_present?
387
- require "active_job"
388
- require "action_mailer"
389
- require "sidekiq/testing"
390
-
391
- describe "Sidekiq ActiveJob integration" do
392
- let(:namespace) { Appsignal::Transaction::BACKGROUND_JOB }
393
- let(:time) { Time.parse("2001-01-01 10:00:00UTC") }
394
- let(:log) { StringIO.new }
395
- let(:given_args) do
396
- [
397
- "foo",
398
- {
399
- :foo => "Foo",
400
- "bar" => "Bar",
401
- "baz" => { "1" => "foo" }
402
- }
403
- ]
404
- end
405
- let(:expected_args) do
406
- [
407
- "foo",
408
- {
409
- "_aj_symbol_keys" => ["foo"],
410
- "foo" => "Foo",
411
- "bar" => "Bar",
412
- "baz" => {
413
- "_aj_symbol_keys" => [],
414
- "1" => "foo"
415
- }
416
- }
417
- ]
418
- end
419
- let(:expected_tags) do
420
- {}.tap do |hash|
421
- hash["active_job_id"] = kind_of(String)
422
- if DependencyHelper.rails_version >= Gem::Version.new("5.0.0")
423
- hash["provider_job_id"] = kind_of(String)
424
- end
425
- end
426
- end
427
- before do
428
- start_agent
429
- Appsignal.logger = test_logger(log)
430
- ActiveJob::Base.queue_adapter = :sidekiq
431
-
432
- class ActiveJobSidekiqTestJob < ActiveJob::Base
433
- self.queue_adapter = :sidekiq
434
-
435
- def perform(*_args)
436
- end
437
- end
438
-
439
- class ActiveJobSidekiqErrorTestJob < ActiveJob::Base
440
- self.queue_adapter = :sidekiq
441
-
442
- def perform(*_args)
443
- raise "uh oh"
444
- end
445
- end
446
- # Manually add the AppSignal middleware for the Testing environment.
447
- # It doesn't use configured middlewares by default looks like.
448
- # We test somewhere else if the middleware is installed properly.
449
- Sidekiq::Testing.server_middleware do |chain|
450
- chain.add Appsignal::Hooks::SidekiqPlugin
451
- end
452
- end
453
- around do |example|
454
- keep_transactions do
455
- Sidekiq::Testing.fake! do
456
- example.run
457
- end
458
- end
459
- end
460
- after do
461
- Object.send(:remove_const, :ActiveJobSidekiqTestJob)
462
- Object.send(:remove_const, :ActiveJobSidekiqErrorTestJob)
463
- end
464
-
465
- it "reports the transaction from the ActiveJob integration" do
466
- perform_job(ActiveJobSidekiqTestJob, given_args)
467
-
468
- transaction = last_transaction
469
- transaction_hash = transaction.to_h
470
- expect(transaction_hash).to include(
471
- "action" => "ActiveJobSidekiqTestJob#perform",
472
- "error" => nil,
473
- "namespace" => namespace,
474
- "metadata" => hash_including(
475
- "queue" => "default"
476
- ),
477
- "sample_data" => hash_including(
478
- "environment" => {},
479
- "params" => [expected_args],
480
- "tags" => expected_tags.merge("queue" => "default")
481
- )
482
- )
483
- expect(transaction.request.env).to eq(:queue_start => time.to_f)
484
- events = transaction_hash["events"]
485
- .sort_by { |e| e["start"] }
486
- .map { |event| event["name"] }
487
- expect(events)
488
- .to eq(["perform_job.sidekiq", "perform_start.active_job", "perform.active_job"])
489
- end
490
-
491
- context "with error" do
492
- it "reports the error on the transaction from the ActiveRecord integration" do
493
- expect do
494
- perform_job(ActiveJobSidekiqErrorTestJob, given_args)
495
- end.to raise_error(RuntimeError, "uh oh")
496
-
497
- transaction = last_transaction
498
- transaction_hash = transaction.to_h
499
- expect(transaction_hash).to include(
500
- "action" => "ActiveJobSidekiqErrorTestJob#perform",
501
- "error" => {
502
- "name" => "RuntimeError",
503
- "message" => "uh oh",
504
- "backtrace" => kind_of(String)
505
- },
506
- "namespace" => namespace,
507
- "metadata" => hash_including(
508
- "queue" => "default"
509
- ),
510
- "sample_data" => hash_including(
511
- "environment" => {},
512
- "params" => [expected_args],
513
- "tags" => expected_tags.merge("queue" => "default")
514
- )
515
- )
516
- expect(transaction.request.env).to eq(:queue_start => time.to_f)
517
- events = transaction_hash["events"]
518
- .sort_by { |e| e["start"] }
519
- .map { |event| event["name"] }
520
- expect(events)
521
- .to eq(["perform_job.sidekiq", "perform_start.active_job", "perform.active_job"])
522
- end
523
- end
524
-
525
- context "with ActionMailer" do
526
- include ActionMailerHelpers
527
-
528
- before do
529
- class ActionMailerSidekiqTestJob < ActionMailer::Base
530
- def welcome(*args)
531
- end
532
- end
533
- end
534
-
535
- it "reports ActionMailer data on the transaction" do
536
- perform_mailer(ActionMailerSidekiqTestJob, :welcome, given_args)
537
-
538
- transaction = last_transaction
539
- transaction_hash = transaction.to_h
540
- expect(transaction_hash).to include(
541
- "action" => "ActionMailerSidekiqTestJob#welcome",
542
- "sample_data" => hash_including(
543
- "params" => ["ActionMailerSidekiqTestJob", "welcome", "deliver_now"] + expected_args
544
- )
545
- )
546
- end
547
- end
548
-
549
- def perform_sidekiq
550
- Timecop.freeze(time) do
551
- yield
552
- # Combined with Sidekiq::Testing.fake! and drain_all we get a
553
- # enqueue_at in the job data.
554
- Sidekiq::Worker.drain_all
555
- end
556
- end
557
-
558
- def perform_job(job_class, args)
559
- perform_sidekiq { job_class.perform_later(args) }
560
- end
561
-
562
- def perform_mailer(mailer, method, args = nil)
563
- perform_sidekiq { perform_action_mailer(mailer, method, args) }
564
- end
565
- end
566
- end