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
@@ -22,17 +22,19 @@ describe Appsignal::Rack::EventHandler do
22
22
  event_handler_instance.on_start(request, response)
23
23
  end
24
24
 
25
+ def on_error(error)
26
+ event_handler_instance.on_error(request, response, error)
27
+ end
28
+
25
29
  describe "#on_start" do
26
30
  it "creates a new transaction" do
27
31
  expect { on_start }.to change { created_transactions.length }.by(1)
28
32
 
29
33
  transaction = last_transaction
30
- expect(transaction.to_h).to include(
31
- "id" => kind_of(String),
32
- "namespace" => Appsignal::Transaction::HTTP_REQUEST
33
- )
34
+ expect(transaction).to have_id
35
+ expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
34
36
 
35
- expect(Appsignal::Transaction.current).to eq(last_transaction)
37
+ expect(Appsignal::Transaction.current).to eq(transaction)
36
38
  end
37
39
 
38
40
  context "when the handler is nested in another EventHandler" do
@@ -119,21 +121,11 @@ describe Appsignal::Rack::EventHandler do
119
121
  end
120
122
 
121
123
  describe "#on_error" do
122
- def on_error(error)
123
- event_handler_instance.on_error(request, response, error)
124
- end
125
-
126
124
  it "reports the error" do
127
125
  on_start
128
126
  on_error(ExampleStandardError.new("the error"))
129
127
 
130
- expect(last_transaction.to_h).to include(
131
- "error" => {
132
- "name" => "ExampleStandardError",
133
- "message" => "the error",
134
- "backtrace" => kind_of(String)
135
- }
136
- )
128
+ expect(last_transaction).to have_error("ExampleStandardError", "the error")
137
129
  end
138
130
 
139
131
  context "when the handler is nested in another EventHandler" do
@@ -141,7 +133,7 @@ describe Appsignal::Rack::EventHandler do
141
133
  on_start
142
134
  described_class.new.on_error(request, response, ExampleStandardError.new("the error"))
143
135
 
144
- expect(last_transaction.to_h).to include("error" => nil)
136
+ expect(last_transaction).to_not have_error
145
137
  end
146
138
  end
147
139
 
@@ -174,11 +166,9 @@ describe Appsignal::Rack::EventHandler do
174
166
 
175
167
  on_finish
176
168
 
177
- expect(last_transaction.to_h).to include(
178
- "action" => nil,
179
- "sample_data" => {},
180
- "events" => []
181
- )
169
+ expect(last_transaction).to_not have_action
170
+ expect(last_transaction).to_not include_events
171
+ expect(last_transaction).to include("sample_data" => {})
182
172
  expect(last_transaction).to_not be_completed
183
173
  end
184
174
 
@@ -186,18 +176,12 @@ describe Appsignal::Rack::EventHandler do
186
176
  on_start
187
177
  on_finish
188
178
 
189
- expect(last_transaction.to_h).to include(
190
- # The action is not set on purpose, as we can't set a normalized route
191
- # It requires the app to set an action name
192
- "action" => nil,
193
- "sample_data" => hash_including(
194
- "environment" => {
195
- "REQUEST_METHOD" => "GET",
196
- "PATH_INFO" => "/path"
197
- }
198
- )
179
+ expect(last_transaction).to_not have_action
180
+ expect(last_transaction).to include_environment(
181
+ "REQUEST_METHOD" => "GET",
182
+ "PATH_INFO" => "/path"
199
183
  )
200
- expect(last_transaction.ext.queue_start).to eq(queue_start_time)
184
+ expect(last_transaction).to have_queue_start(queue_start_time)
201
185
  expect(last_transaction).to be_completed
202
186
  end
203
187
 
@@ -206,18 +190,14 @@ describe Appsignal::Rack::EventHandler do
206
190
  on_start
207
191
  on_finish(request, nil)
208
192
 
209
- expect(last_transaction.to_h).to include(
210
- # The action is not set on purpose, as we can't set a normalized route
211
- # It requires the app to set an action name
212
- "action" => nil,
213
- "sample_data" => hash_including(
214
- "environment" => {
215
- "REQUEST_METHOD" => "GET",
216
- "PATH_INFO" => "/path"
217
- }
218
- )
193
+ # The action is not set on purpose, as we can't set a normalized route
194
+ # It requires the app to set an action name
195
+ expect(last_transaction).to_not have_action
196
+ expect(last_transaction).to include_environment(
197
+ "REQUEST_METHOD" => "GET",
198
+ "PATH_INFO" => "/path"
219
199
  )
220
- expect(last_transaction.ext.queue_start).to eq(queue_start_time)
200
+ expect(last_transaction).to have_queue_start(queue_start_time)
221
201
  expect(last_transaction).to be_completed
222
202
  end
223
203
 
@@ -225,7 +205,7 @@ describe Appsignal::Rack::EventHandler do
225
205
  on_start
226
206
  on_finish(request, nil)
227
207
 
228
- expect(last_transaction.to_h.dig("sample_data", "tags")).to_not have_key("response_status")
208
+ expect(last_transaction).to_not include_tags("response_status" => anything)
229
209
  end
230
210
 
231
211
  it "does not report a response_status counter metric" do
@@ -235,6 +215,25 @@ describe Appsignal::Rack::EventHandler do
235
215
  on_start
236
216
  on_finish(request, nil)
237
217
  end
218
+
219
+ context "with an error previously recorded by on_error" do
220
+ it "sets response status 500 as a tag" do
221
+ on_start
222
+ on_error(ExampleStandardError.new("the error"))
223
+ on_finish(request, nil)
224
+
225
+ expect(last_transaction).to include_tags("response_status" => 500)
226
+ end
227
+
228
+ it "increments the response status counter for response status 500" do
229
+ expect(Appsignal).to receive(:increment_counter)
230
+ .with(:response_status, 1, :status => 500, :namespace => :web)
231
+
232
+ on_start
233
+ on_error(ExampleStandardError.new("the error"))
234
+ on_finish(request, nil)
235
+ end
236
+ end
238
237
  end
239
238
 
240
239
  context "with error inside on_finish handler" do
@@ -260,12 +259,10 @@ describe Appsignal::Rack::EventHandler do
260
259
  on_start
261
260
  described_class.new.on_finish(request, response)
262
261
 
263
- expect(last_transaction.to_h).to include(
264
- "action" => nil,
265
- "metadata" => {},
266
- "sample_data" => {},
267
- "events" => []
268
- )
262
+ expect(last_transaction).to_not have_action
263
+ expect(last_transaction).to_not include_metadata
264
+ expect(last_transaction).to_not include_events
265
+ expect(last_transaction.to_h).to include("sample_data" => {})
269
266
  expect(last_transaction).to_not be_completed
270
267
  end
271
268
  end
@@ -275,44 +272,50 @@ describe Appsignal::Rack::EventHandler do
275
272
  last_transaction.set_action("My action")
276
273
  on_finish
277
274
 
278
- expect(last_transaction.to_h).to include(
279
- "action" => "My action"
280
- )
275
+ expect(last_transaction).to have_action("My action")
281
276
  end
282
277
 
283
278
  it "finishes the process_request.rack event" do
284
279
  on_start
285
280
  on_finish
286
281
 
287
- expect(last_transaction.to_h).to include(
288
- "events" => [
289
- hash_including(
290
- "name" => "process_request.rack",
291
- "title" => "",
292
- "body" => "",
293
- "body_format" => Appsignal::EventFormatter::DEFAULT
294
- )
295
- ]
296
- )
282
+ expect(last_transaction).to include_event("name" => "process_request.rack")
297
283
  end
298
284
 
299
- it "sets the response status as a tag" do
300
- on_start
301
- on_finish
285
+ context "with response" do
286
+ it "sets the response status as a tag" do
287
+ on_start
288
+ on_finish
302
289
 
303
- expect(last_transaction.to_h).to include(
304
- "sample_data" => hash_including(
305
- "tags" => { "response_status" => 200 }
306
- )
307
- )
308
- end
290
+ expect(last_transaction).to include_tags("response_status" => 200)
291
+ end
309
292
 
310
- it "increments the response status counter for response status" do
311
- expect(Appsignal).to receive(:increment_counter)
312
- .with(:response_status, 1, :status => 200, :namespace => :web)
293
+ it "increments the response status counter for response status" do
294
+ expect(Appsignal).to receive(:increment_counter)
295
+ .with(:response_status, 1, :status => 200, :namespace => :web)
313
296
 
314
- on_start
315
- on_finish
297
+ on_start
298
+ on_finish
299
+ end
300
+
301
+ context "with an error previously recorded by on_error" do
302
+ it "sets response status from the response as a tag" do
303
+ on_start
304
+ on_error(ExampleStandardError.new("the error"))
305
+ on_finish
306
+
307
+ expect(last_transaction).to include_tags("response_status" => 200)
308
+ end
309
+
310
+ it "increments the response status counter based on the response" do
311
+ expect(Appsignal).to receive(:increment_counter)
312
+ .with(:response_status, 1, :status => 200, :namespace => :web)
313
+
314
+ on_start
315
+ on_error(ExampleStandardError.new("the error"))
316
+ on_finish
317
+ end
318
+ end
316
319
  end
317
320
 
318
321
  it "logs an error in case of an error" do
@@ -14,17 +14,7 @@ describe Appsignal::Rack::GenericInstrumentation do
14
14
  it "reports a process_action.generic event" do
15
15
  make_request(env)
16
16
 
17
- expect(last_transaction.to_h).to include(
18
- "events" => [
19
- hash_including(
20
- "body" => "",
21
- "body_format" => Appsignal::EventFormatter::DEFAULT,
22
- "count" => 1,
23
- "name" => "process_action.generic",
24
- "title" => ""
25
- )
26
- ]
27
- )
17
+ expect(last_transaction).to include_event("name" => "process_action.generic")
28
18
  end
29
19
  end
30
20
 
@@ -32,7 +22,7 @@ describe Appsignal::Rack::GenericInstrumentation do
32
22
  it "reports 'unknown' as the action name" do
33
23
  make_request(env)
34
24
 
35
- expect(last_transaction.to_h).to include("action" => "unknown")
25
+ expect(last_transaction).to have_action("unknown")
36
26
  end
37
27
  end
38
28
  end
@@ -0,0 +1,234 @@
1
+ if DependencyHelper.grape_present?
2
+ require "appsignal/integrations/grape"
3
+
4
+ context "Appsignal::Grape::Middleware constant" do
5
+ let(:err_stream) { std_stream }
6
+ let(:stderr) { err_stream.read }
7
+
8
+ it "returns the Probes constant calling the Minutely constant" do
9
+ silence { expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware) }
10
+ end
11
+
12
+ it "prints a deprecation warning to STDERR" do
13
+ capture_std_streams(std_stream, err_stream) do
14
+ expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware)
15
+ end
16
+
17
+ expect(stderr).to include(
18
+ "appsignal WARNING: The constant Appsignal::Grape::Middleware has been deprecated."
19
+ )
20
+ end
21
+
22
+ it "logs a warning" do
23
+ logs =
24
+ capture_logs do
25
+ silence do
26
+ expect(Appsignal::Grape::Middleware).to be(Appsignal::Rack::GrapeMiddleware)
27
+ end
28
+ end
29
+
30
+ expect(logs).to contains_log(
31
+ :warn,
32
+ "The constant Appsignal::Grape::Middleware has been deprecated."
33
+ )
34
+ end
35
+ end
36
+
37
+ describe Appsignal::Rack::GrapeMiddleware do
38
+ let(:app) do
39
+ Class.new(::Grape::API) do
40
+ format :json
41
+ post :ping do
42
+ { :message => "Hello world!" }
43
+ end
44
+ end
45
+ end
46
+ let(:api_endpoint) { app.endpoints.first }
47
+ let(:env) do
48
+ http_request_env_with_data \
49
+ "api.endpoint" => api_endpoint,
50
+ "REQUEST_METHOD" => "POST",
51
+ :path => "/ping"
52
+ end
53
+ let(:middleware) { Appsignal::Rack::GrapeMiddleware.new(api_endpoint) }
54
+ let(:transaction) { http_request_transaction }
55
+ before(:context) { start_agent }
56
+ around do |example|
57
+ GrapeExample = Module.new
58
+ GrapeExample.send(:const_set, :Api, app)
59
+ keep_transactions { example.run }
60
+ Object.send(:remove_const, :GrapeExample)
61
+ end
62
+
63
+ def make_request(env)
64
+ middleware.call(env)
65
+ end
66
+
67
+ def make_request_with_exception(env, exception_class, exception_message)
68
+ expect do
69
+ middleware.call(env)
70
+ end.to raise_error(exception_class, exception_message)
71
+ end
72
+
73
+ context "with error" do
74
+ let(:app) do
75
+ Class.new(::Grape::API) do
76
+ format :json
77
+ post :ping do
78
+ raise ExampleException, "error message"
79
+ end
80
+ end
81
+ end
82
+
83
+ it "sets the error" do
84
+ make_request_with_exception(env, ExampleException, "error message")
85
+
86
+ expect(last_transaction).to have_error("ExampleException", "error message")
87
+ end
88
+
89
+ context "with env['grape.skip_appsignal_error'] = true" do
90
+ let(:app) do
91
+ Class.new(::Grape::API) do
92
+ format :json
93
+ post :ping do
94
+ env["grape.skip_appsignal_error"] = true
95
+ raise ExampleException, "error message"
96
+ end
97
+ end
98
+ end
99
+
100
+ it "does not add the error" do
101
+ make_request_with_exception(env, ExampleException, "error message")
102
+
103
+ expect(last_transaction).to_not have_error
104
+ end
105
+ end
106
+ end
107
+
108
+ context "with route" do
109
+ let(:app) do
110
+ Class.new(::Grape::API) do
111
+ route([:get, :post], "hello") do
112
+ "Hello!"
113
+ end
114
+ end
115
+ end
116
+ let(:env) do
117
+ http_request_env_with_data \
118
+ "api.endpoint" => api_endpoint,
119
+ "REQUEST_METHOD" => "GET",
120
+ :path => ""
121
+ end
122
+
123
+ it "sets non-unique route path" do
124
+ make_request(env)
125
+
126
+ expect(last_transaction).to have_action("GET::GrapeExample::Api#/hello")
127
+ expect(last_transaction).to include_metadata("path" => "/hello", "method" => "GET")
128
+ end
129
+ end
130
+
131
+ context "with route_param" do
132
+ let(:app) do
133
+ Class.new(::Grape::API) do
134
+ format :json
135
+ resource :users do
136
+ route_param :id do
137
+ get do
138
+ { :name => "Tom" }
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ let(:env) do
145
+ http_request_env_with_data \
146
+ "api.endpoint" => api_endpoint,
147
+ "REQUEST_METHOD" => "GET",
148
+ :path => ""
149
+ end
150
+
151
+ it "sets non-unique route_param path" do
152
+ make_request(env)
153
+
154
+ expect(last_transaction).to have_action("GET::GrapeExample::Api#/users/:id/")
155
+ expect(last_transaction).to include_metadata("path" => "/users/:id/", "method" => "GET")
156
+ end
157
+ end
158
+
159
+ context "with namespaced path" do
160
+ context "with symbols" do
161
+ let(:app) do
162
+ Class.new(::Grape::API) do
163
+ format :json
164
+ namespace :v1 do
165
+ namespace :beta do
166
+ post :ping do
167
+ { :message => "Hello namespaced world!" }
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ it "sets namespaced path" do
175
+ make_request(env)
176
+
177
+ expect(last_transaction).to have_action("POST::GrapeExample::Api#/v1/beta/ping")
178
+ expect(last_transaction).to include_metadata("path" => "/v1/beta/ping",
179
+ "method" => "POST")
180
+ end
181
+ end
182
+
183
+ context "with strings" do
184
+ context "without / prefix" do
185
+ let(:app) do
186
+ Class.new(::Grape::API) do
187
+ format :json
188
+ namespace "v1" do
189
+ namespace "beta" do
190
+ post "ping" do
191
+ { :message => "Hello namespaced world!" }
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ it "sets namespaced path" do
199
+ make_request(env)
200
+
201
+ expect(last_transaction).to have_action("POST::GrapeExample::Api#/v1/beta/ping")
202
+ expect(last_transaction).to include_metadata(
203
+ "path" => "/v1/beta/ping",
204
+ "method" => "POST"
205
+ )
206
+ end
207
+ end
208
+
209
+ context "with / prefix" do
210
+ let(:app) do
211
+ Class.new(::Grape::API) do
212
+ format :json
213
+ namespace "/v1" do
214
+ namespace "/beta" do
215
+ post "/ping" do
216
+ { :message => "Hello namespaced world!" }
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ it "sets namespaced path" do
224
+ make_request(env)
225
+
226
+ expect(last_transaction).to have_action("POST::GrapeExample::Api#/v1/beta/ping")
227
+ expect(last_transaction).to include_metadata("path" => "/v1/beta/ping",
228
+ "method" => "POST")
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end
234
+ end
@@ -23,28 +23,14 @@ if DependencyHelper.hanami2_present?
23
23
  it "sets request parameters on the transaction" do
24
24
  make_request(env)
25
25
 
26
- expect(last_transaction.to_h).to include(
27
- "sample_data" => hash_including(
28
- "params" => { "param1" => "value1", "param2" => "value2" }
29
- )
30
- )
26
+ expect(last_transaction).to include_params("param1" => "value1", "param2" => "value2")
31
27
  end
32
28
  end
33
29
 
34
30
  it "reports a process_action.hanami event" do
35
31
  make_request(env)
36
32
 
37
- expect(last_transaction.to_h).to include(
38
- "events" => [
39
- hash_including(
40
- "body" => "",
41
- "body_format" => Appsignal::EventFormatter::DEFAULT,
42
- "count" => 1,
43
- "name" => "process_action.hanami",
44
- "title" => ""
45
- )
46
- ]
47
- )
33
+ expect(last_transaction).to include_event("name" => "process_action.hanami")
48
34
  end
49
35
  end
50
36
  end