appsignal 2.11.8-java → 3.0.1-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 (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