appsignal 3.9.2 → 3.9.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,6 +1,8 @@
1
1
  require "appsignal/integrations/object"
2
2
 
3
3
  describe Object do
4
+ around { |example| keep_transactions { example.run } }
5
+
4
6
  describe "#instrument_method" do
5
7
  context "with instance method" do
6
8
  let(:klass) do
@@ -24,10 +26,8 @@ describe Object do
24
26
  context "when active" do
25
27
  let(:transaction) { http_request_transaction }
26
28
  before do
27
- Appsignal.config = project_fixture_config
28
- expect(Appsignal::Transaction).to receive(:current)
29
- .at_least(:once).and_return(transaction)
30
- expect(Appsignal.active?).to be_truthy
29
+ start_agent
30
+ set_current_transaction(transaction)
31
31
  end
32
32
  after { Appsignal.config = nil }
33
33
 
@@ -80,10 +80,9 @@ describe Object do
80
80
 
81
81
  context "with anonymous class" do
82
82
  it "instruments the method and calls it" do
83
- expect(transaction).to receive(:start_event)
84
- expect(transaction).to receive(:finish_event).with \
85
- "foo.AnonymousClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
86
83
  expect(call_with_arguments).to eq(["abc", { :foo => "bar" }, 2])
84
+
85
+ expect(transaction).to include_event("name" => "foo.AnonymousClass.other")
87
86
  end
88
87
  end
89
88
 
@@ -100,10 +99,9 @@ describe Object do
100
99
  let(:klass) { NamedClass }
101
100
 
102
101
  it "instruments the method and calls it" do
103
- expect(transaction).to receive(:start_event)
104
- expect(transaction).to receive(:finish_event).with \
105
- "foo.NamedClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
106
102
  expect(instance.foo).to eq(1)
103
+
104
+ expect(transaction).to include_event("name" => "foo.NamedClass.other")
107
105
  end
108
106
  end
109
107
 
@@ -124,11 +122,11 @@ describe Object do
124
122
  let(:klass) { MyModule::NestedModule::NamedClass }
125
123
 
126
124
  it "instruments the method and calls it" do
127
- expect(transaction).to receive(:start_event)
128
- expect(transaction).to receive(:finish_event).with \
129
- "bar.NamedClass.NestedModule.MyModule.other", nil, nil,
130
- Appsignal::EventFormatter::DEFAULT
131
125
  expect(instance.bar).to eq(2)
126
+
127
+ expect(transaction).to include_event(
128
+ "name" => "bar.NamedClass.NestedModule.MyModule.other"
129
+ )
132
130
  end
133
131
  end
134
132
 
@@ -143,10 +141,11 @@ describe Object do
143
141
  end
144
142
 
145
143
  it "instruments with custom name" do
146
- expect(transaction).to receive(:start_event)
147
- expect(transaction).to receive(:finish_event).with \
148
- "my_method.group", nil, nil, Appsignal::EventFormatter::DEFAULT
149
144
  expect(instance.foo).to eq(1)
145
+
146
+ expect(transaction).to include_event(
147
+ "name" => "my_method.group"
148
+ )
150
149
  end
151
150
  end
152
151
 
@@ -160,7 +159,7 @@ describe Object do
160
159
  end
161
160
  end
162
161
 
163
- it "should yield the block" do
162
+ it "yields the block" do
164
163
  expect(instance.foo { 42 }).to eq(42)
165
164
  end
166
165
  end
@@ -171,7 +170,6 @@ describe Object do
171
170
 
172
171
  it "does not instrument, but still calls the method" do
173
172
  expect(Appsignal.active?).to be_falsy
174
- expect(transaction).to_not receive(:start_event)
175
173
  expect(call_with_arguments).to eq(["abc", { :foo => "bar" }, 2])
176
174
  end
177
175
  end
@@ -198,8 +196,7 @@ describe Object do
198
196
  let(:transaction) { http_request_transaction }
199
197
  before do
200
198
  Appsignal.config = project_fixture_config
201
- expect(Appsignal::Transaction).to receive(:current).at_least(:once)
202
- .and_return(transaction)
199
+ set_current_transaction(transaction)
203
200
  end
204
201
  after { Appsignal.config = nil }
205
202
 
@@ -253,10 +250,10 @@ describe Object do
253
250
  context "with anonymous class" do
254
251
  it "instruments the method and calls it" do
255
252
  expect(Appsignal.active?).to be_truthy
256
- expect(transaction).to receive(:start_event)
257
- expect(transaction).to receive(:finish_event).with \
258
- "bar.class_method.AnonymousClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
259
253
  expect(call_with_arguments).to eq(["abc", { :foo => "bar" }, 2])
254
+
255
+ transaction._sample
256
+ expect(transaction).to include_event("name" => "bar.class_method.AnonymousClass.other")
260
257
  end
261
258
  end
262
259
 
@@ -274,10 +271,9 @@ describe Object do
274
271
 
275
272
  it "instruments the method and calls it" do
276
273
  expect(Appsignal.active?).to be_truthy
277
- expect(transaction).to receive(:start_event)
278
- expect(transaction).to receive(:finish_event).with \
279
- "bar.class_method.NamedClass.other", nil, nil, Appsignal::EventFormatter::DEFAULT
280
274
  expect(klass.bar).to eq(2)
275
+
276
+ expect(transaction).to include_event("name" => "bar.class_method.NamedClass.other")
281
277
  end
282
278
 
283
279
  context "with nested named class" do
@@ -298,11 +294,10 @@ describe Object do
298
294
 
299
295
  it "instruments the method and calls it" do
300
296
  expect(Appsignal.active?).to be_truthy
301
- expect(transaction).to receive(:start_event)
302
- expect(transaction).to receive(:finish_event).with \
303
- "bar.class_method.NamedClass.NestedModule.MyModule.other", nil, nil,
304
- Appsignal::EventFormatter::DEFAULT
305
297
  expect(klass.bar).to eq(2)
298
+ expect(transaction).to include_event(
299
+ "name" => "bar.class_method.NamedClass.NestedModule.MyModule.other"
300
+ )
306
301
  end
307
302
  end
308
303
  end
@@ -319,10 +314,9 @@ describe Object do
319
314
 
320
315
  it "instruments with custom name" do
321
316
  expect(Appsignal.active?).to be_truthy
322
- expect(transaction).to receive(:start_event)
323
- expect(transaction).to receive(:finish_event).with \
324
- "my_method.group", nil, nil, Appsignal::EventFormatter::DEFAULT
325
317
  expect(klass.bar).to eq(2)
318
+
319
+ expect(transaction).to include_event("name" => "my_method.group")
326
320
  end
327
321
  end
328
322
 
@@ -336,7 +330,7 @@ describe Object do
336
330
  end
337
331
  end
338
332
 
339
- it "should yield the block" do
333
+ it "yields the block" do
340
334
  expect(klass.bar { 42 }).to eq(42)
341
335
  end
342
336
  end
@@ -347,7 +341,6 @@ describe Object do
347
341
 
348
342
  it "does not instrument, but still call the method" do
349
343
  expect(Appsignal.active?).to be_falsy
350
- expect(transaction).to_not receive(:start_event)
351
344
  expect(call_with_arguments).to eq(["abc", { :foo => "bar" }, 2])
352
345
  end
353
346
  end
@@ -2,21 +2,11 @@ if DependencyHelper.padrino_present?
2
2
  describe "Padrino integration" do
3
3
  require "appsignal/integrations/padrino"
4
4
 
5
- before do
6
- allow(Appsignal).to receive(:active?).and_return(true)
7
- allow(Appsignal).to receive(:start).and_return(true)
8
- allow(Appsignal).to receive(:start_logger).and_return(true)
9
- end
10
-
11
5
  describe Appsignal::Integrations::PadrinoPlugin do
12
6
  it "starts AppSignal on init" do
13
7
  expect(Appsignal).to receive(:start)
14
8
  end
15
9
 
16
- it "starts the logger on init" do
17
- expect(Appsignal).to receive(:start_logger)
18
- end
19
-
20
10
  context "when not active" do
21
11
  before { allow(Appsignal).to receive(:active?).and_return(false) }
22
12
 
@@ -59,20 +49,9 @@ if DependencyHelper.padrino_present?
59
49
  let(:env) { {} }
60
50
  # TODO: use an instance double
61
51
  let(:settings) { double(:name => "TestApp") }
52
+ around { |example| keep_transactions { example.run } }
62
53
 
63
54
  describe "routes" do
64
- let(:transaction) do
65
- instance_double "Appsignal::Transaction",
66
- :set_http_or_background_action => nil,
67
- :set_http_or_background_queue_start => nil,
68
- :set_metadata => nil,
69
- :set_action => nil,
70
- :set_action_if_nil => nil,
71
- :set_error => nil,
72
- :start_event => nil,
73
- :finish_event => nil,
74
- :complete => nil
75
- end
76
55
  let(:request_kind) { kind_of(Sinatra::Request) }
77
56
  let(:env) do
78
57
  {
@@ -90,10 +69,6 @@ if DependencyHelper.padrino_present?
90
69
  end
91
70
  end
92
71
  let(:response) { app.call(env) }
93
- before do
94
- allow(Appsignal::Transaction).to receive(:create).and_return(transaction)
95
- allow(Appsignal::Transaction).to receive(:current).and_return(transaction)
96
- end
97
72
 
98
73
  RSpec::Matchers.define :match_response do |expected_status, expected_content|
99
74
  match do |response|
@@ -109,46 +84,41 @@ if DependencyHelper.padrino_present?
109
84
  end
110
85
 
111
86
  def expect_a_transaction_to_be_created
112
- expect(Appsignal::Transaction).to receive(:create).with(
113
- kind_of(String),
114
- Appsignal::Transaction::HTTP_REQUEST,
115
- request_kind
116
- ).and_return(transaction)
117
-
118
- expect(Appsignal).to receive(:instrument)
119
- .at_least(:once)
120
- .with("process_action.padrino")
121
- .and_call_original
122
- expect(transaction).to receive(:set_metadata).with("path", path)
123
- expect(transaction).to receive(:set_metadata).with("method", "GET")
124
- expect(transaction).to receive(:complete)
125
- end
126
-
127
- def expect_no_transaction_to_be_created
128
- expect(Appsignal::Transaction).to_not receive(:create)
129
- expect(Appsignal).to_not receive(:instrument)
87
+ transaction = last_transaction
88
+ expect(transaction).to have_id
89
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
90
+ expect(transaction).to include_metadata(
91
+ "path" => path,
92
+ "method" => "GET"
93
+ )
94
+ expect(transaction).to include_event("name" => "process_action.padrino")
95
+ expect(transaction).to be_completed
130
96
  end
131
97
 
132
98
  context "when AppSignal is not active" do
133
99
  before { allow(Appsignal).to receive(:active?).and_return(false) }
134
100
  let(:path) { "/foo" }
135
101
  before { app.controllers { get(:foo) { "content" } } }
136
- after { expect(response).to match_response(200, "content") }
137
102
 
138
103
  it "does not instrument the request" do
139
- expect_no_transaction_to_be_created
104
+ expect do
105
+ expect(response).to match_response(200, "content")
106
+ end.to_not(change { created_transactions.count })
140
107
  end
141
108
  end
142
109
 
143
110
  context "when AppSignal is active" do
111
+ before { start_agent }
112
+
144
113
  context "with not existing route" do
145
114
  let(:path) { "/404" }
146
115
 
147
116
  it "instruments the request" do
117
+ expect(response).to match_response(404, /^GET /404/)
118
+
148
119
  expect_a_transaction_to_be_created
149
120
  # Uses path for action name
150
- expect(transaction).to receive(:set_action_if_nil).with("PadrinoTestApp#unknown")
151
- expect(response).to match_response(404, /^GET /404/)
121
+ expect(last_transaction).to have_action("PadrinoTestApp#unknown")
152
122
  end
153
123
  end
154
124
 
@@ -158,10 +128,11 @@ if DependencyHelper.padrino_present?
158
128
  env["sinatra.static_file"] = true
159
129
  app.controllers { get(:static) { "Static!" } }
160
130
  end
161
- after { expect(response).to match_response(200, "Static!") }
162
131
 
163
132
  it "does not instrument the request" do
164
- expect_no_transaction_to_be_created
133
+ expect do
134
+ expect(response).to match_response(200, "Static!")
135
+ end.to_not(change { created_transactions.count })
165
136
  end
166
137
  end
167
138
 
@@ -172,12 +143,14 @@ if DependencyHelper.padrino_present?
172
143
  allow_any_instance_of(Sinatra::Request).to receive(:action).and_return(nil)
173
144
  app.controllers { get(:my_original_path, :with => :id) { "content" } }
174
145
  end
175
- after { expect(response).to match_response(200, "content") }
176
146
 
177
147
  it "falls back on Sinatra::Request#route_obj.original_path" do
148
+ expect do
149
+ expect(response).to match_response(200, "content")
150
+ end.to(change { created_transactions.count }.by(1))
151
+
178
152
  expect_a_transaction_to_be_created
179
- expect(transaction)
180
- .to receive(:set_action_if_nil).with("PadrinoTestApp:/my_original_path/:id")
153
+ expect(last_transaction).to have_action("PadrinoTestApp:/my_original_path/:id")
181
154
  end
182
155
  end
183
156
 
@@ -188,11 +161,11 @@ if DependencyHelper.padrino_present?
188
161
  allow_any_instance_of(Sinatra::Request).to receive(:route_obj).and_return(nil)
189
162
  app.controllers { get(:my_original_path) { "content" } }
190
163
  end
191
- after { expect(response).to match_response(200, "content") }
192
164
 
193
165
  it "falls back on app name" do
166
+ expect(response).to match_response(200, "content")
194
167
  expect_a_transaction_to_be_created
195
- expect(transaction).to receive(:set_action_if_nil).with("PadrinoTestApp#unknown")
168
+ expect(last_transaction).to have_action("PadrinoTestApp#unknown")
196
169
  end
197
170
  end
198
171
 
@@ -200,25 +173,25 @@ if DependencyHelper.padrino_present?
200
173
  context "with an exception in the controller" do
201
174
  let(:path) { "/exception" }
202
175
  before do
203
- app.controllers { get(:exception) { raise ExampleException } }
176
+ app.controllers { get(:exception) { raise ExampleException, "error message" } }
177
+ expect { response }.to raise_error(ExampleException, "error message")
204
178
  expect_a_transaction_to_be_created
205
179
  end
206
- after do
207
- expect { response }.to raise_error(ExampleException)
208
- end
209
180
 
210
181
  it "sets the action name based on the app name and action name" do
211
- expect(transaction).to receive(:set_action_if_nil).with("PadrinoTestApp:#exception")
182
+ expect(last_transaction).to have_action("PadrinoTestApp:#exception")
212
183
  end
213
184
 
214
185
  it "sets the error on the transaction" do
215
- expect(transaction).to receive(:set_error).with(ExampleException)
186
+ expect(last_transaction).to have_error("ExampleException", "error message")
216
187
  end
217
188
  end
218
189
 
219
190
  context "without an exception in the controller" do
220
191
  let(:path) { "/" }
221
- after { expect(response).to match_response(200, "content") }
192
+ def make_request
193
+ expect(response).to match_response(200, "content")
194
+ end
222
195
 
223
196
  context "with action name as symbol" do
224
197
  context "with :index helper" do
@@ -228,8 +201,9 @@ if DependencyHelper.padrino_present?
228
201
  end
229
202
 
230
203
  it "sets the action with the app name and action name" do
204
+ make_request
231
205
  expect_a_transaction_to_be_created
232
- expect(transaction).to receive(:set_action_if_nil).with("PadrinoTestApp:#index")
206
+ expect(last_transaction).to have_action("PadrinoTestApp:#index")
233
207
  end
234
208
  end
235
209
 
@@ -240,8 +214,9 @@ if DependencyHelper.padrino_present?
240
214
  end
241
215
 
242
216
  it "sets the action with the app name and action name" do
217
+ make_request
243
218
  expect_a_transaction_to_be_created
244
- expect(transaction).to receive(:set_action_if_nil).with("PadrinoTestApp:#foo")
219
+ expect(last_transaction).to have_action("PadrinoTestApp:#foo")
245
220
  end
246
221
  end
247
222
  end
@@ -254,8 +229,9 @@ if DependencyHelper.padrino_present?
254
229
  end
255
230
 
256
231
  it "sets the action with the app name and action path" do
232
+ make_request
257
233
  expect_a_transaction_to_be_created
258
- expect(transaction).to receive(:set_action_if_nil).with("PadrinoTestApp:#/")
234
+ expect(last_transaction).to have_action("PadrinoTestApp:#/")
259
235
  end
260
236
  end
261
237
 
@@ -266,8 +242,9 @@ if DependencyHelper.padrino_present?
266
242
  end
267
243
 
268
244
  it "sets the action with the app name and action path" do
245
+ make_request
269
246
  expect_a_transaction_to_be_created
270
- expect(transaction).to receive(:set_action_if_nil).with("PadrinoTestApp:#/foo")
247
+ expect(last_transaction).to have_action("PadrinoTestApp:#/foo")
271
248
  end
272
249
  end
273
250
  end
@@ -282,9 +259,9 @@ if DependencyHelper.padrino_present?
282
259
  end
283
260
 
284
261
  it "sets the action with the app name, controller name and action name" do
262
+ make_request
285
263
  expect_a_transaction_to_be_created
286
- expect(transaction).to receive(:set_action_if_nil)
287
- .with("PadrinoTestApp:my_controller#index")
264
+ expect(last_transaction).to have_action("PadrinoTestApp:my_controller#index")
288
265
  end
289
266
  end
290
267
 
@@ -295,9 +272,9 @@ if DependencyHelper.padrino_present?
295
272
  end
296
273
 
297
274
  it "sets the action with the app name, controller name and action path" do
275
+ make_request
298
276
  expect_a_transaction_to_be_created
299
- expect(transaction).to receive(:set_action_if_nil)
300
- .with("PadrinoTestApp:/my_controller#index")
277
+ expect(last_transaction).to have_action("PadrinoTestApp:/my_controller#index")
301
278
  end
302
279
  end
303
280
  end
@@ -53,38 +53,27 @@ if DependencyHelper.que_present?
53
53
  perform_que_job(instance)
54
54
  end.to change { created_transactions.length }.by(1)
55
55
 
56
- expect(last_transaction).to be_completed
57
- transaction_hash = last_transaction.to_h
58
- expect(transaction_hash).to include(
59
- "action" => "MyQueJob#run",
60
- "id" => instance_of(String),
61
- "namespace" => Appsignal::Transaction::BACKGROUND_JOB
62
- )
63
- expect(transaction_hash["error"]).to be_nil
64
- expect(transaction_hash["events"].first).to include(
65
- "allocation_count" => kind_of(Integer),
56
+ transaction = last_transaction
57
+ expect(transaction).to have_id
58
+ expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
59
+ expect(transaction).to have_action("MyQueJob#run")
60
+ expect(transaction).to_not have_error
61
+ expect(transaction).to include_event(
66
62
  "body" => "",
67
63
  "body_format" => Appsignal::EventFormatter::DEFAULT,
68
- "child_allocation_count" => kind_of(Integer),
69
- "child_duration" => kind_of(Float),
70
- "child_gc_duration" => kind_of(Float),
71
64
  "count" => 1,
72
- "gc_duration" => kind_of(Float),
73
- "start" => kind_of(Float),
74
- "duration" => kind_of(Float),
75
65
  "name" => "perform_job.que",
76
66
  "title" => ""
77
67
  )
78
- expect(transaction_hash["sample_data"]).to include(
79
- "params" => %w[1 birds],
80
- "metadata" => {
81
- "attempts" => 0,
82
- "id" => 123,
83
- "priority" => 100,
84
- "queue" => "dfl",
85
- "run_at" => fixed_time.to_s
86
- }
68
+ expect(transaction).to include_params(%w[1 birds])
69
+ expect(transaction).to include_sample_metadata(
70
+ "attempts" => 0,
71
+ "id" => 123,
72
+ "priority" => 100,
73
+ "queue" => "dfl",
74
+ "run_at" => fixed_time.to_s
87
75
  )
76
+ expect(transaction).to be_completed
88
77
  end
89
78
  end
90
79
 
@@ -100,28 +89,20 @@ if DependencyHelper.que_present?
100
89
  end.to raise_error(ExampleException)
101
90
  end.to change { created_transactions.length }.by(1)
102
91
 
103
- expect(last_transaction).to be_completed
104
- transaction_hash = last_transaction.to_h
105
- expect(transaction_hash).to include(
106
- "action" => "MyQueJob#run",
107
- "id" => instance_of(String),
108
- "namespace" => Appsignal::Transaction::BACKGROUND_JOB
109
- )
110
- expect(transaction_hash["error"]).to include(
111
- "backtrace" => kind_of(String),
112
- "name" => error.class.name,
113
- "message" => error.message
114
- )
115
- expect(transaction_hash["sample_data"]).to include(
116
- "params" => %w[1 birds],
117
- "metadata" => {
118
- "attempts" => 0,
119
- "id" => 123,
120
- "priority" => 100,
121
- "queue" => "dfl",
122
- "run_at" => fixed_time.to_s
123
- }
92
+ transaction = last_transaction
93
+ expect(transaction).to have_id
94
+ expect(transaction).to have_action("MyQueJob#run")
95
+ expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
96
+ expect(transaction).to have_error(error.class.name, error.message)
97
+ expect(transaction).to include_params(%w[1 birds])
98
+ expect(transaction).to include_sample_metadata(
99
+ "attempts" => 0,
100
+ "id" => 123,
101
+ "priority" => 100,
102
+ "queue" => "dfl",
103
+ "run_at" => fixed_time.to_s
124
104
  )
105
+ expect(transaction).to be_completed
125
106
  end
126
107
  end
127
108
 
@@ -133,28 +114,20 @@ if DependencyHelper.que_present?
133
114
 
134
115
  expect { perform_que_job(instance) }.to change { created_transactions.length }.by(1)
135
116
 
136
- expect(last_transaction).to be_completed
137
- transaction_hash = last_transaction.to_h
138
- expect(transaction_hash).to include(
139
- "action" => "MyQueJob#run",
140
- "id" => instance_of(String),
141
- "namespace" => Appsignal::Transaction::BACKGROUND_JOB
142
- )
143
- expect(transaction_hash["error"]).to include(
144
- "backtrace" => kind_of(String),
145
- "name" => error.class.name,
146
- "message" => error.message
147
- )
148
- expect(transaction_hash["sample_data"]).to include(
149
- "params" => %w[1 birds],
150
- "metadata" => {
151
- "attempts" => 0,
152
- "id" => 123,
153
- "priority" => 100,
154
- "queue" => "dfl",
155
- "run_at" => fixed_time.to_s
156
- }
117
+ transaction = last_transaction
118
+ expect(transaction).to have_id
119
+ expect(transaction).to have_action("MyQueJob#run")
120
+ expect(transaction).to have_namespace(Appsignal::Transaction::BACKGROUND_JOB)
121
+ expect(transaction).to have_error(error.class.name, error.message)
122
+ expect(transaction).to include_params(%w[1 birds])
123
+ expect(transaction).to include_sample_metadata(
124
+ "attempts" => 0,
125
+ "id" => 123,
126
+ "priority" => 100,
127
+ "queue" => "dfl",
128
+ "run_at" => fixed_time.to_s
157
129
  )
130
+ expect(transaction).to be_completed
158
131
  end
159
132
  end
160
133
 
@@ -170,9 +143,9 @@ if DependencyHelper.que_present?
170
143
  it "uses the custom action" do
171
144
  perform_que_job(instance)
172
145
 
173
- expect(last_transaction).to be_completed
174
- transaction_hash = last_transaction.to_h
175
- expect(transaction_hash).to include("action" => "MyCustomJob#perform")
146
+ transaction = last_transaction
147
+ expect(transaction).to have_action("MyCustomJob#perform")
148
+ expect(transaction).to be_completed
176
149
  end
177
150
  end
178
151
  end