appsignal 3.10.0-java → 3.11.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +88 -0
  4. data/Gemfile +1 -0
  5. data/benchmark.rake +99 -42
  6. data/lib/appsignal/cli/demo.rb +0 -1
  7. data/lib/appsignal/config.rb +54 -98
  8. data/lib/appsignal/demo.rb +15 -20
  9. data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
  10. data/lib/appsignal/event_formatter.rb +3 -2
  11. data/lib/appsignal/helpers/instrumentation.rb +331 -19
  12. data/lib/appsignal/hooks/action_cable.rb +21 -16
  13. data/lib/appsignal/hooks/active_job.rb +14 -8
  14. data/lib/appsignal/hooks/delayed_job.rb +1 -1
  15. data/lib/appsignal/hooks/shoryuken.rb +3 -63
  16. data/lib/appsignal/integrations/action_cable.rb +5 -7
  17. data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
  18. data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
  19. data/lib/appsignal/integrations/data_mapper.rb +1 -0
  20. data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
  21. data/lib/appsignal/integrations/dry_monitor.rb +1 -0
  22. data/lib/appsignal/integrations/excon.rb +1 -0
  23. data/lib/appsignal/integrations/http.rb +1 -0
  24. data/lib/appsignal/integrations/net_http.rb +1 -0
  25. data/lib/appsignal/integrations/object.rb +6 -0
  26. data/lib/appsignal/integrations/que.rb +13 -20
  27. data/lib/appsignal/integrations/railtie.rb +1 -1
  28. data/lib/appsignal/integrations/rake.rb +1 -5
  29. data/lib/appsignal/integrations/redis.rb +1 -0
  30. data/lib/appsignal/integrations/redis_client.rb +1 -0
  31. data/lib/appsignal/integrations/resque.rb +2 -5
  32. data/lib/appsignal/integrations/shoryuken.rb +75 -0
  33. data/lib/appsignal/integrations/sidekiq.rb +7 -15
  34. data/lib/appsignal/integrations/unicorn.rb +1 -0
  35. data/lib/appsignal/integrations/webmachine.rb +2 -5
  36. data/lib/appsignal/logger.rb +7 -3
  37. data/lib/appsignal/probes/helpers.rb +1 -0
  38. data/lib/appsignal/probes/mri.rb +1 -0
  39. data/lib/appsignal/probes/sidekiq.rb +1 -0
  40. data/lib/appsignal/probes.rb +3 -0
  41. data/lib/appsignal/rack/abstract_middleware.rb +18 -12
  42. data/lib/appsignal/rack/event_handler.rb +39 -8
  43. data/lib/appsignal/rack/generic_instrumentation.rb +1 -0
  44. data/lib/appsignal/rack/grape_middleware.rb +2 -1
  45. data/lib/appsignal/rack/streaming_listener.rb +1 -0
  46. data/lib/appsignal/rack.rb +29 -0
  47. data/lib/appsignal/span.rb +1 -0
  48. data/lib/appsignal/transaction.rb +308 -101
  49. data/lib/appsignal/utils/data.rb +0 -1
  50. data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
  51. data/lib/appsignal/utils/integration_logger.rb +0 -13
  52. data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
  53. data/lib/appsignal/utils/json.rb +0 -1
  54. data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
  55. data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
  56. data/lib/appsignal/utils.rb +6 -0
  57. data/lib/appsignal/version.rb +1 -1
  58. data/lib/appsignal.rb +6 -5
  59. data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
  60. data/spec/lib/appsignal/config_spec.rb +138 -43
  61. data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
  62. data/spec/lib/appsignal/hooks/activejob_spec.rb +9 -0
  63. data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
  64. data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
  65. data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
  66. data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
  67. data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
  68. data/spec/lib/appsignal/integrations/sidekiq_spec.rb +4 -4
  69. data/spec/lib/appsignal/integrations/webmachine_spec.rb +13 -1
  70. data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +48 -3
  71. data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -10
  72. data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
  73. data/spec/lib/appsignal/rack_spec.rb +63 -0
  74. data/spec/lib/appsignal/transaction_spec.rb +1634 -1071
  75. data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
  76. data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
  77. data/spec/lib/appsignal_spec.rb +323 -10
  78. data/spec/support/helpers/transaction_helpers.rb +44 -20
  79. data/spec/support/matchers/transaction.rb +15 -1
  80. data/spec/support/testing.rb +1 -1
  81. metadata +6 -2
@@ -1,132 +1,211 @@
1
1
  describe Appsignal::Transaction do
2
- before :context do
3
- start_agent
4
- end
5
-
6
- let(:transaction_id) { "1" }
7
- let(:time) { Time.at(fixed_time) }
8
- let(:namespace) { Appsignal::Transaction::HTTP_REQUEST }
9
- let(:env) { {} }
10
- let(:merged_env) { http_request_env_with_data(env) }
11
- let(:options) { {} }
12
- let(:request) { Rack::Request.new(merged_env) }
13
- let(:transaction) { Appsignal::Transaction.new(transaction_id, namespace, request, options) }
14
- let(:log) { StringIO.new }
2
+ let(:time) { Time.at(fixed_time) }
15
3
 
16
4
  before { Timecop.freeze(time) }
17
5
  after { Timecop.return }
18
6
  around do |example|
19
- use_logger_with log do
7
+ start_agent
8
+ keep_transactions do
20
9
  example.run
21
10
  end
22
11
  end
23
12
 
24
- describe "class methods" do
25
- def current_transaction
26
- Appsignal::Transaction.current
27
- end
13
+ describe ".create" do
14
+ context "when no transaction is running" do
15
+ it "returns the created transaction" do
16
+ mock_transaction_id = "mock-uuid"
17
+ allow(SecureRandom).to receive(:uuid).and_return(mock_transaction_id)
18
+
19
+ transaction = create_transaction
20
+ expect(transaction).to be_a Appsignal::Transaction
28
21
 
29
- describe ".create" do
30
- def create_transaction(id = transaction_id)
31
- Appsignal::Transaction.create(id, namespace, request, options)
22
+ expect(transaction).to have_id(mock_transaction_id)
23
+ expect(transaction.transaction_id).to eq(mock_transaction_id)
24
+
25
+ expect(transaction).to have_namespace(default_namespace)
26
+ expect(transaction.namespace).to eq(default_namespace)
32
27
  end
33
28
 
34
- context "when no transaction is running" do
35
- let!(:transaction) { create_transaction }
29
+ it "assigns the transaction to current" do
30
+ transaction = create_transaction
31
+ expect(transaction).to eq current_transaction
32
+ end
36
33
 
34
+ context "with legacy arguments" do
37
35
  it "returns the created transaction" do
38
- expect(transaction).to be_a Appsignal::Transaction
39
- expect(transaction.transaction_id).to eq transaction_id
40
- expect(transaction.namespace).to eq namespace
41
- expect(transaction.request).to eq request
36
+ transaction_id = "mock-id"
37
+ namespace = "my_namespace"
38
+ transaction = legacy_create_transaction(
39
+ :id => transaction_id,
40
+ :namespace => namespace
41
+ )
42
+ expect(transaction).to be_a(Appsignal::Transaction)
42
43
 
43
44
  expect(transaction).to have_id(transaction_id)
45
+ expect(transaction.transaction_id).to eq(transaction_id)
46
+
44
47
  expect(transaction).to have_namespace(namespace)
48
+ expect(transaction.namespace).to eq(namespace)
45
49
  end
46
50
 
47
- it "assigns the transaction to current" do
48
- expect(transaction).to eq current_transaction
51
+ it "logs deprecation warnings" do
52
+ logs =
53
+ capture_logs do
54
+ legacy_create_transaction(
55
+ :id => "mock-id",
56
+ :namespace => "my_namespace",
57
+ :request => Appsignal::Transaction::InternalGenericRequest.new({}),
58
+ :options => { :force => true }
59
+ )
60
+ end
61
+
62
+ expect(logs).to contains_log(
63
+ :warn,
64
+ "Appsignal::Transaction.create: " \
65
+ "A new Transaction is created using the transaction ID argument."
66
+ )
67
+ expect(logs).to contains_log(
68
+ :warn,
69
+ "Appsignal::Transaction.create: " \
70
+ "A Transaction is created using the namespace argument."
71
+ )
72
+ expect(logs).to contains_log(
73
+ :warn,
74
+ "Appsignal::Transaction.create: " \
75
+ "A Transaction is created using the request argument."
76
+ )
77
+ expect(logs).to contains_log(
78
+ :warn,
79
+ "Appsignal::Transaction.create: " \
80
+ "A Transaction is created using the `:force => true` option argument. "
81
+ )
49
82
  end
50
- end
51
83
 
52
- context "when a transaction is already running" do
53
- before { create_transaction }
84
+ it "prints deprecation warnings" do
85
+ err_stream = std_stream
86
+ capture_std_streams(std_stream, err_stream) do
87
+ legacy_create_transaction(
88
+ :id => "mock-id",
89
+ :namespace => "my_namespace",
90
+ :request => Appsignal::Transaction::InternalGenericRequest.new({}),
91
+ :options => { :force => true }
92
+ )
93
+ end
54
94
 
55
- it "does not create a new transaction, but returns the current transaction" do
56
- expect do
57
- new_transaction = create_transaction("2")
58
- expect(new_transaction).to eq(current_transaction)
59
- expect(new_transaction.transaction_id).to eq(transaction_id)
60
- end.to_not(change { current_transaction })
95
+ stderr = err_stream.read
96
+ expect(stderr).to include(
97
+ "appsignal WARNING: Appsignal::Transaction.create: " \
98
+ "A new Transaction is created using the transaction ID argument."
99
+ )
100
+ expect(stderr).to include(
101
+ "appsignal WARNING: Appsignal::Transaction.create: " \
102
+ "A Transaction is created using the namespace argument."
103
+ )
104
+ expect(stderr).to include(
105
+ "appsignal WARNING: Appsignal::Transaction.create: " \
106
+ "A Transaction is created using the request argument."
107
+ )
108
+ expect(stderr).to include(
109
+ "appsignal WARNING: Appsignal::Transaction.create: " \
110
+ "A Transaction is created using the `:force => true` option argument. "
111
+ )
61
112
  end
113
+ end
114
+ end
62
115
 
63
- it "logs a debug message" do
64
- create_transaction("2")
65
- expect(log_contents(log)).to contains_log :warn,
66
- "Trying to start new transaction with id '2', but a " \
67
- "transaction with id '#{transaction_id}' is already " \
68
- "running. Using transaction '#{transaction_id}'."
69
- end
116
+ context "when a transaction is already running" do
117
+ before do
118
+ allow(SecureRandom).to receive(:uuid)
119
+ .and_return(
120
+ "transaction_id_1",
121
+ "transaction_id_2"
122
+ )
123
+ create_transaction
124
+ end
70
125
 
71
- context "with option :force => true" do
72
- it "returns the newly created (and current) transaction" do
73
- original_transaction = current_transaction
74
- expect(original_transaction).to_not be_nil
75
- expect(current_transaction.transaction_id).to eq transaction_id
126
+ it "does not create a new transaction, but returns the current transaction" do
127
+ expect do
128
+ new_transaction = create_transaction
76
129
 
77
- options[:force] = true
78
- expect(create_transaction("2")).to_not eq original_transaction
79
- expect(current_transaction.transaction_id).to eq "2"
80
- end
130
+ expect(new_transaction).to eq(current_transaction)
131
+ end.to_not(change { current_transaction })
132
+ end
133
+
134
+ it "logs a debug message" do
135
+ logs = capture_logs { create_transaction }
136
+
137
+ expect(logs).to contains_log :warn,
138
+ "Trying to start new transaction with id 'transaction_id_2', but a " \
139
+ "transaction with id 'transaction_id_1' is already " \
140
+ "running. Using transaction 'transaction_id_1'."
141
+ end
142
+
143
+ context "with option :force => true" do
144
+ it "returns the newly created (and current) transaction" do
145
+ original_transaction = create_transaction
146
+
147
+ expect(original_transaction).to be_a(Appsignal::Transaction)
148
+ expect(current_transaction).to have_id("transaction_id_1")
149
+
150
+ new_transaction = legacy_create_transaction(
151
+ :id => "transaction_id_2",
152
+ :options => { :force => true }
153
+ )
154
+
155
+ expect(new_transaction).to be_a(Appsignal::Transaction)
156
+ expect(new_transaction).to_not eq(original_transaction)
157
+ expect(new_transaction).to have_id("transaction_id_2")
158
+ expect(current_transaction).to eq(new_transaction)
81
159
  end
82
160
  end
83
161
  end
162
+ end
84
163
 
85
- describe ".current" do
86
- context "when there is a current transaction" do
87
- let!(:transaction) do
88
- Appsignal::Transaction.create(transaction_id, namespace, request, options)
89
- end
164
+ describe ".current" do
165
+ context "when there is a current transaction" do
166
+ let!(:transaction) { create_transaction }
90
167
 
91
- it "reads :appsignal_transaction from the current Thread" do
92
- expect(current_transaction).to eq Thread.current[:appsignal_transaction]
93
- expect(current_transaction).to eq transaction
94
- end
168
+ it "reads :appsignal_transaction from the current Thread" do
169
+ expect(current_transaction).to eq(Thread.current[:appsignal_transaction])
170
+ expect(current_transaction).to eq(transaction)
171
+ end
95
172
 
96
- it "is not a NilTransaction" do
97
- expect(current_transaction.nil_transaction?).to eq false
98
- expect(current_transaction).to be_a Appsignal::Transaction
99
- end
173
+ it "is not a NilTransaction" do
174
+ expect(current_transaction.nil_transaction?).to be(false)
175
+ expect(current_transaction).to be_a(Appsignal::Transaction)
176
+ end
100
177
 
101
- it "returns true for current?" do
102
- expect(Appsignal::Transaction.current?).to be(true)
103
- end
178
+ it "returns true for current?" do
179
+ expect(Appsignal::Transaction.current?).to be(true)
104
180
  end
181
+ end
105
182
 
106
- context "when there is no current transaction" do
107
- it "has no :appsignal_transaction registered on the current Thread" do
108
- expect(Thread.current[:appsignal_transaction]).to be_nil
109
- end
183
+ context "when there is no current transaction" do
184
+ it "has no :appsignal_transaction registered on the current Thread" do
185
+ expect(Thread.current[:appsignal_transaction]).to be_nil
186
+ end
110
187
 
111
- it "returns a NilTransaction stub" do
112
- expect(current_transaction.nil_transaction?).to eq true
113
- expect(current_transaction).to be_a Appsignal::Transaction::NilTransaction
114
- end
188
+ it "returns a NilTransaction stub" do
189
+ expect(current_transaction.nil_transaction?).to be(true)
190
+ expect(current_transaction).to be_a(Appsignal::Transaction::NilTransaction)
191
+ end
115
192
 
116
- it "returns false for current?" do
117
- expect(Appsignal::Transaction.current?).to be(false)
118
- end
193
+ it "returns false for current?" do
194
+ expect(Appsignal::Transaction.current?).to be(false)
119
195
  end
120
196
  end
197
+ end
121
198
 
122
- describe ".complete_current!" do
123
- let!(:transaction) { Appsignal::Transaction.create(transaction_id, namespace, options) }
199
+ describe ".complete_current!" do
200
+ context "with active transaction" do
201
+ let!(:transaction) { create_transaction }
124
202
 
125
203
  it "completes the current transaction" do
126
- expect(transaction).to eq current_transaction
127
- expect(transaction).to receive(:complete).and_call_original
204
+ expect(transaction).to eq(current_transaction)
128
205
 
129
206
  Appsignal::Transaction.complete_current!
207
+
208
+ expect(transaction).to be_completed
130
209
  end
131
210
 
132
211
  it "unsets the current transaction on the current Thread" do
@@ -141,8 +220,11 @@ describe Appsignal::Transaction do
141
220
  end
142
221
 
143
222
  it "logs an error message" do
144
- Appsignal::Transaction.complete_current!
145
- expect(log_contents(log)).to contains_log :error,
223
+ logs =
224
+ capture_logs do
225
+ Appsignal::Transaction.complete_current!
226
+ end
227
+ expect(logs).to contains_log :error,
146
228
  "Failed to complete transaction ##{transaction.transaction_id}. ExampleStandardError"
147
229
  end
148
230
 
@@ -153,9 +235,19 @@ describe Appsignal::Transaction do
153
235
  end
154
236
  end
155
237
  end
238
+
239
+ context "without active transaction" do
240
+ it "does nothing" do
241
+ expect do
242
+ Appsignal::Transaction.complete_current!
243
+ end.to_not(change { Thread.current[:appsignal_transaction] })
244
+ end
245
+ end
156
246
  end
157
247
 
158
248
  describe "#complete" do
249
+ let(:transaction) { create_transaction }
250
+
159
251
  context "when transaction is being sampled" do
160
252
  it "samples data" do
161
253
  transaction.set_tags(:foo => "bar")
@@ -183,11 +275,12 @@ describe Appsignal::Transaction do
183
275
  end
184
276
 
185
277
  it "logs a debug message" do
278
+ allow(SecureRandom).to receive(:uuid).and_return("mock_transaction_id")
186
279
  transaction.discard!
187
- transaction.complete
280
+ logs = capture_logs { transaction.complete }
188
281
 
189
- expect(log_contents(log)).to contains_log :debug,
190
- "Skipping transaction '#{transaction_id}' because it was manually discarded."
282
+ expect(logs).to contains_log :debug,
283
+ "Skipping transaction 'mock_transaction_id' because it was manually discarded."
191
284
  end
192
285
 
193
286
  context "when a discarded transaction is restored" do
@@ -207,6 +300,8 @@ describe Appsignal::Transaction do
207
300
  end
208
301
 
209
302
  context "pausing" do
303
+ let(:transaction) { new_transaction }
304
+
210
305
  describe "#pause!" do
211
306
  it "changes the pause flag to true" do
212
307
  expect do
@@ -242,993 +337,1439 @@ describe Appsignal::Transaction do
242
337
  end
243
338
  end
244
339
 
245
- context "with transaction instance" do
246
- context "initialization" do
247
- it "loads the AppSignal extension" do
248
- expect(transaction.ext).to_not be_nil
249
- end
340
+ context "initialization" do
341
+ let(:transaction) { new_transaction }
250
342
 
251
- context "when extension is not loaded", :extension_installation_failure do
252
- around do |example|
253
- Appsignal::Testing.without_testing { example.run }
254
- end
343
+ it "loads the AppSignal extension" do
344
+ expect(transaction.ext).to_not be_nil
345
+ end
255
346
 
256
- it "does not error on missing extension method calls" do
257
- expect(transaction.ext).to be_kind_of(Appsignal::Extension::MockTransaction)
258
- transaction.start_event
259
- transaction.finish_event(
260
- "name",
261
- "title",
262
- "body",
263
- Appsignal::EventFormatter::DEFAULT
264
- )
265
- end
347
+ context "when extension is not loaded", :extension_installation_failure do
348
+ around do |example|
349
+ Appsignal::Testing.without_testing { example.run }
266
350
  end
267
351
 
268
- it "sets the transaction id" do
269
- expect(transaction.transaction_id).to eq "1"
352
+ it "does not error on missing extension method calls" do
353
+ expect(transaction.ext).to be_kind_of(Appsignal::Extension::MockTransaction)
354
+ transaction.start_event
355
+ transaction.finish_event(
356
+ "name",
357
+ "title",
358
+ "body",
359
+ Appsignal::EventFormatter::DEFAULT
360
+ )
270
361
  end
362
+ end
271
363
 
272
- it "sets the namespace to http_request" do
273
- expect(transaction.namespace).to eq "http_request"
364
+ context "transaction id" do
365
+ before do
366
+ allow(SecureRandom).to receive(:uuid).and_return("mock_transaction_id")
274
367
  end
275
368
 
276
- it "sets the request" do
277
- expect(transaction.request).to_not be_nil
369
+ it "sets the transaction id" do
370
+ expect(transaction).to have_id("mock_transaction_id")
278
371
  end
372
+ end
279
373
 
280
- it "sets the request not to paused" do
281
- expect(transaction.paused).to be_falsy
282
- end
374
+ it "sets the namespace to http_request" do
375
+ expect(transaction.namespace).to eq "http_request"
376
+ end
283
377
 
284
- it "sets no tags by default" do
285
- expect(transaction.tags).to eq({})
286
- end
378
+ it "sets the request" do
379
+ expect(transaction.request).to be_a(Appsignal::Transaction::InternalGenericRequest)
380
+ end
287
381
 
288
- describe "#options" do
289
- subject { transaction.options }
382
+ it "sets the request not to paused" do
383
+ expect(transaction.paused?).to be_falsy
384
+ end
290
385
 
291
- it "sets the default :params_method" do
292
- expect(subject[:params_method]).to eq :params
293
- end
386
+ it "sets no tags by default" do
387
+ expect(transaction.tags).to be_empty
388
+ end
294
389
 
295
- context "with overridden options" do
296
- let(:options) { { :params_method => :filtered_params } }
390
+ describe "#options" do
391
+ let(:options) { transaction.options }
297
392
 
298
- it "sets the overridden :params_method" do
299
- expect(subject[:params_method]).to eq :filtered_params
300
- end
301
- end
393
+ it "sets the default :params_method" do
394
+ expect(options[:params_method]).to eq :params
302
395
  end
303
- end
304
396
 
305
- describe "#store" do
306
- it "should return an empty store when it's not already present" do
307
- expect(transaction.store("test")).to eql({})
397
+ context "with overridden options" do
398
+ let(:transaction) do
399
+ legacy_new_transaction(:options => { :params_method => :filtered_params })
400
+ end
401
+
402
+ it "sets the overridden :params_method" do
403
+ expect(options[:params_method]).to eq :filtered_params
404
+ end
308
405
  end
406
+ end
407
+ end
309
408
 
310
- it "should store changes to the store" do
311
- transaction_store = transaction.store("test")
312
- transaction_store["transaction"] = "value"
409
+ describe "#store" do
410
+ let(:transaction) { new_transaction }
313
411
 
314
- expect(transaction.store("test")).to eql("transaction" => "value")
315
- end
412
+ it "returns an empty store when it's not already present" do
413
+ expect(transaction.store("test")).to eql({})
316
414
  end
317
415
 
318
- describe "#params" do
319
- subject { transaction.params }
416
+ it "stores changes to the store" do
417
+ transaction_store = transaction.store("test")
418
+ transaction_store["transaction"] = "value"
320
419
 
321
- context "with custom params set on transaction" do
322
- before do
323
- transaction.set_params(:foo => "bar")
324
- end
420
+ expect(transaction.store("test")).to eql("transaction" => "value")
421
+ end
422
+ end
325
423
 
326
- it "returns custom parameters" do
327
- expect(subject).to eq(:foo => "bar")
328
- end
424
+ describe "#params" do
425
+ let(:transaction) { new_transaction }
426
+ let(:params) { transaction.params }
329
427
 
330
- context "when params is a callable object" do
331
- it "calls the params object and sets the return value as parametesr" do
332
- transaction.set_params { { "param1" => "value1" } }
428
+ context "with custom params set on transaction" do
429
+ before { transaction.set_params(:foo => "bar") }
333
430
 
334
- expect(transaction.params).to eq(
335
- "param1" => "value1"
336
- )
337
- end
338
- end
431
+ it "returns custom parameters" do
432
+ expect(params).to eq(:foo => "bar")
339
433
  end
340
434
 
341
- context "without custom params set on transaction" do
342
- it "returns parameters from request" do
343
- expect(subject).to eq(
344
- "action" => "show",
345
- "controller" => "blog_posts",
346
- "id" => "1"
347
- )
435
+ context "when params is a callable object" do
436
+ it "calls the params object and sets the return value as parametesr" do
437
+ transaction.set_params { { "param1" => "value1" } }
438
+
439
+ expect(params).to eq("param1" => "value1")
348
440
  end
349
441
  end
350
442
  end
351
443
 
352
- describe "#params=" do
353
- around { |example| keep_transactions { example.run } }
444
+ context "without custom params set on transaction" do
445
+ let(:transaction) do
446
+ legacy_new_transaction(
447
+ :request => legacy_request(
448
+ :params => {
449
+ "action" => "show",
450
+ "controller" => "blog_posts",
451
+ "id" => "1"
354
452
 
355
- it "sets params on the transaction" do
356
- params = { "foo" => "bar" }
357
- silence { transaction.params = params }
358
-
359
- transaction._sample
360
- expect(transaction.params).to eq(params)
361
- expect(transaction).to include_params(params)
453
+ }
454
+ )
455
+ )
362
456
  end
363
457
 
364
- it "logs a deprecation warning" do
365
- transaction.params = { "foo" => "bar" }
366
-
367
- expect(log_contents(log)).to contains_log(
368
- :warn,
369
- "Transaction#params= is deprecated." \
370
- "Use Transaction#set_params or #set_params_if_nil instead."
458
+ it "returns parameters from request" do
459
+ expect(params).to eq(
460
+ "action" => "show",
461
+ "controller" => "blog_posts",
462
+ "id" => "1"
371
463
  )
372
464
  end
373
465
  end
466
+ end
374
467
 
375
- describe "#set_params" do
376
- around { |example| keep_transactions { example.run } }
468
+ describe "#params=" do
469
+ let(:transaction) { new_transaction }
377
470
 
378
- context "when the params are set" do
379
- it "updates the params on the transaction" do
380
- params = { "key" => "value" }
381
- transaction.set_params(params)
471
+ it "sets params on the transaction" do
472
+ params = { "foo" => "bar" }
473
+ silence { transaction.params = params }
382
474
 
383
- transaction._sample
384
- expect(transaction.params).to eq(params)
385
- expect(transaction).to include_params(params)
475
+ transaction._sample
476
+ expect(transaction.params).to eq(params)
477
+ expect(transaction).to include_params(params)
478
+ end
479
+
480
+ it "logs a deprecation warning" do
481
+ logs =
482
+ capture_logs do
483
+ transaction.params = { "foo" => "bar" }
386
484
  end
387
485
 
388
- it "updates the params on the transaction with a block" do
389
- params = { "key" => "value" }
390
- transaction.set_params { params }
486
+ expect(logs).to contains_log(
487
+ :warn,
488
+ "Transaction#params= is deprecated." \
489
+ "Use Transaction#set_params or #set_params_if_nil instead."
490
+ )
491
+ end
492
+ end
391
493
 
392
- transaction._sample
393
- expect(transaction.params).to eq(params)
394
- expect(transaction).to include_params(params)
395
- end
494
+ describe "#set_params" do
495
+ let(:transaction) { new_transaction }
396
496
 
397
- it "updates with the params argument when both an argument and block are given" do
398
- arg_params = { "argument" => "value" }
399
- block_params = { "block" => "value" }
400
- transaction.set_params(arg_params) { block_params }
497
+ context "when the params are set" do
498
+ it "updates the params on the transaction" do
499
+ params = { "key" => "value" }
500
+ transaction.set_params(params)
401
501
 
402
- transaction._sample
403
- expect(transaction.params).to eq(arg_params)
404
- expect(transaction).to include_params(arg_params)
405
- end
502
+ transaction._sample
503
+ expect(transaction.params).to eq(params)
504
+ expect(transaction).to include_params(params)
406
505
  end
407
506
 
408
- context "when the given params is nil" do
409
- it "does not update the params on the transaction" do
410
- params = { "key" => "value" }
411
- transaction.set_params(params)
412
- transaction.set_params(nil)
507
+ it "updates the params on the transaction with a block" do
508
+ params = { "key" => "value" }
509
+ transaction.set_params { params }
413
510
 
414
- transaction._sample
415
- expect(transaction.params).to eq(params)
416
- expect(transaction).to include_params(params)
417
- end
511
+ transaction._sample
512
+ expect(transaction.params).to eq(params)
513
+ expect(transaction).to include_params(params)
418
514
  end
419
- end
420
515
 
421
- describe "#set_params_if_nil" do
422
- around { |example| keep_transactions { example.run } }
516
+ it "updates with the params argument when both an argument and block are given" do
517
+ arg_params = { "argument" => "value" }
518
+ block_params = { "block" => "value" }
519
+ transaction.set_params(arg_params) { block_params }
423
520
 
424
- context "when the params are not set" do
425
- it "sets the params on the transaction" do
426
- params = { "key" => "value" }
427
- transaction.set_params_if_nil(params)
521
+ transaction._sample
522
+ expect(transaction.params).to eq(arg_params)
523
+ expect(transaction).to include_params(arg_params)
524
+ end
428
525
 
429
- transaction._sample
430
- expect(transaction.params).to eq(params)
431
- expect(transaction).to include_params(params)
432
- end
526
+ it "logs an error if an error occurred storing the params" do
527
+ transaction.set_params { raise "uh oh" }
433
528
 
434
- it "updates the params on the transaction with a block" do
435
- params = { "key" => "value" }
436
- transaction.set_params_if_nil { params }
529
+ logs = capture_logs { transaction._sample }
530
+ expect(logs).to contains_log(
531
+ :error,
532
+ "Exception while fetching params: RuntimeError: uh oh"
533
+ )
534
+ end
535
+ end
437
536
 
438
- transaction._sample
439
- expect(transaction.params).to eq(params)
440
- expect(transaction).to include_params(params)
441
- end
537
+ context "when the given params is nil" do
538
+ it "does not update the params on the transaction" do
539
+ params = { "key" => "value" }
540
+ transaction.set_params(params)
541
+ transaction.set_params(nil)
442
542
 
443
- it "updates with the params argument when both an argument and block are given" do
444
- arg_params = { "argument" => "value" }
445
- block_params = { "block" => "value" }
446
- transaction.set_params_if_nil(arg_params) { block_params }
543
+ transaction._sample
544
+ expect(transaction.params).to eq(params)
545
+ expect(transaction).to include_params(params)
546
+ end
547
+ end
548
+ end
447
549
 
448
- transaction._sample
449
- expect(transaction.params).to eq(arg_params)
450
- expect(transaction).to include_params(arg_params)
451
- end
550
+ describe "#set_params_if_nil" do
551
+ let(:transaction) { new_transaction }
452
552
 
453
- context "when the given params is nil" do
454
- it "does not update the params on the transaction" do
455
- params = { "key" => "value" }
456
- transaction.set_params(params)
457
- transaction.set_params_if_nil(nil)
553
+ context "when the params are not set" do
554
+ it "sets the params on the transaction" do
555
+ params = { "key" => "value" }
556
+ transaction.set_params_if_nil(params)
458
557
 
459
- transaction._sample
460
- expect(transaction.params).to eq(params)
461
- expect(transaction).to include_params(params)
462
- end
463
- end
558
+ transaction._sample
559
+ expect(transaction.params).to eq(params)
560
+ expect(transaction).to include_params(params)
464
561
  end
465
562
 
466
- context "when the params are set" do
467
- it "does not update the params on the transaction" do
468
- preset_params = { "other" => "params" }
469
- params = { "key" => "value" }
470
- transaction.set_params(preset_params)
471
- transaction.set_params_if_nil(params)
563
+ it "updates the params on the transaction with a block" do
564
+ params = { "key" => "value" }
565
+ transaction.set_params_if_nil { params }
472
566
 
473
- transaction._sample
474
- expect(transaction.params).to eq(preset_params)
475
- expect(transaction).to include_params(preset_params)
476
- end
567
+ transaction._sample
568
+ expect(transaction.params).to eq(params)
569
+ expect(transaction).to include_params(params)
570
+ end
571
+
572
+ it "updates with the params argument when both an argument and block are given" do
573
+ arg_params = { "argument" => "value" }
574
+ block_params = { "block" => "value" }
575
+ transaction.set_params_if_nil(arg_params) { block_params }
576
+
577
+ transaction._sample
578
+ expect(transaction.params).to eq(arg_params)
579
+ expect(transaction).to include_params(arg_params)
580
+ end
477
581
 
478
- it "does not update the params with a block on the transaction" do
479
- preset_params = { "other" => "params" }
582
+ context "when the given params is nil" do
583
+ it "does not update the params on the transaction" do
480
584
  params = { "key" => "value" }
481
- transaction.set_params(preset_params)
482
- transaction.set_params_if_nil { params }
585
+ transaction.set_params(params)
586
+ transaction.set_params_if_nil(nil)
483
587
 
484
588
  transaction._sample
485
- expect(transaction.params).to eq(preset_params)
486
- expect(transaction).to include_params(preset_params)
589
+ expect(transaction.params).to eq(params)
590
+ expect(transaction).to include_params(params)
487
591
  end
488
592
  end
489
593
  end
490
594
 
491
- describe "#set_tags" do
492
- let(:long_string) { "a" * 10_001 }
595
+ context "when the params are set" do
596
+ it "does not update the params on the transaction" do
597
+ preset_params = { "other" => "params" }
598
+ params = { "key" => "value" }
599
+ transaction.set_params(preset_params)
600
+ transaction.set_params_if_nil(params)
493
601
 
494
- it "stores tags on the transaction" do
495
- transaction.set_tags(
496
- :valid_key => "valid_value",
497
- "valid_string_key" => "valid_value",
498
- :both_symbols => :valid_value,
499
- :integer_value => 1,
500
- :hash_value => { "invalid" => "hash" },
501
- :array_value => %w[invalid array],
502
- :object => Object.new,
503
- :too_long_value => long_string,
504
- long_string => "too_long_key"
505
- )
506
602
  transaction._sample
507
-
508
- expect(transaction).to include_tags(
509
- "valid_key" => "valid_value",
510
- "valid_string_key" => "valid_value",
511
- "both_symbols" => "valid_value",
512
- "integer_value" => 1,
513
- "too_long_value" => "#{"a" * 10_000}...",
514
- long_string => "too_long_key"
515
- )
603
+ expect(transaction.params).to eq(preset_params)
604
+ expect(transaction).to include_params(preset_params)
516
605
  end
517
606
 
518
- it "merges the tags when called multiple times" do
519
- transaction.set_tags(:key1 => "value1")
520
- transaction.set_tags(:key2 => "value2")
521
- transaction._sample
607
+ it "does not update the params with a block on the transaction" do
608
+ preset_params = { "other" => "params" }
609
+ params = { "key" => "value" }
610
+ transaction.set_params(preset_params)
611
+ transaction.set_params_if_nil { params }
522
612
 
523
- expect(transaction).to include_tags(
524
- "key1" => "value1",
525
- "key2" => "value2"
526
- )
613
+ transaction._sample
614
+ expect(transaction.params).to eq(preset_params)
615
+ expect(transaction).to include_params(preset_params)
527
616
  end
528
617
  end
618
+ end
529
619
 
530
- describe "#set_custom_data" do
531
- let(:log_stream) { std_stream }
532
- let(:logs) { log_contents(log_stream) }
533
- around { |example| use_logger_with(log_stream) { example.run } }
620
+ describe "#set_session_data" do
621
+ let(:transaction) { new_transaction }
534
622
 
535
- it "stores custom Hash data on the transaction" do
536
- transaction.set_custom_data(
537
- :user => {
538
- :id => 123,
539
- :locale => "abc"
540
- },
541
- :organization => {
542
- :slug => "appsignal",
543
- :plan => "enterprise"
544
- }
545
- )
623
+ context "when the session data is set" do
624
+ it "updates the session data on the transaction" do
625
+ data = { "key" => "value" }
626
+ transaction.set_session_data(data)
546
627
 
547
628
  transaction._sample
548
- expect(transaction).to include_custom_data(
549
- "user" => {
550
- "id" => 123,
551
- "locale" => "abc"
552
- },
553
- "organization" => {
554
- "slug" => "appsignal",
555
- "plan" => "enterprise"
556
- }
557
- )
629
+ expect(transaction).to include_session_data(data)
558
630
  end
559
631
 
560
- it "stores custom Array data on the transaction" do
561
- transaction.set_custom_data([
562
- [123, "abc"],
563
- ["appsignal", "enterprise"]
564
- ])
632
+ it "updates the session data on the transaction with a block" do
633
+ data = { "key" => "value" }
634
+ transaction.set_session_data { data }
565
635
 
566
636
  transaction._sample
567
- expect(transaction).to include_custom_data([
568
- [123, "abc"],
569
- ["appsignal", "enterprise"]
570
- ])
637
+ expect(transaction).to include_session_data(data)
571
638
  end
572
639
 
573
- it "does not store non Hash or Array custom data" do
574
- transaction.set_custom_data("abc")
575
- transaction._sample
576
- expect(transaction).to_not include_custom_data
640
+ it "updates with the session data argument when both an argument and block are given" do
641
+ arg_data = { "argument" => "value" }
642
+ block_data = { "block" => "value" }
643
+ transaction.set_session_data(arg_data) { block_data }
577
644
 
578
- transaction.set_custom_data(123)
579
645
  transaction._sample
580
- expect(transaction).to_not include_custom_data
646
+ expect(transaction).to include_session_data(arg_data)
647
+ end
648
+
649
+ it "does not include filtered out session data" do
650
+ Appsignal.config[:filter_session_data] = ["filtered_key"]
651
+ transaction.set_session_data("data" => "value1", "filtered_key" => "filtered_value")
581
652
 
582
- transaction.set_custom_data(Object.new)
583
653
  transaction._sample
584
- expect(transaction).to_not include_custom_data
654
+ expect(transaction).to include_session_data("data" => "value1")
655
+ end
585
656
 
657
+ it "logs an error if an error occurred storing the session data" do
658
+ transaction.set_session_data { raise "uh oh" }
659
+
660
+ logs = capture_logs { transaction._sample }
586
661
  expect(logs).to contains_log(
587
662
  :error,
588
- "set_custom_data: Unsupported data type String received."
589
- )
590
- expect(logs).to contains_log(
591
- :error,
592
- "set_custom_data: Unsupported data type Integer received."
593
- )
594
- expect(logs).to contains_log(
595
- :error,
596
- "set_custom_data: Unsupported data type String received."
663
+ "Exception while fetching session data: RuntimeError: uh oh"
597
664
  )
598
665
  end
666
+ end
599
667
 
600
- it "overwrites the custom data if called multiple times" do
601
- transaction.set_custom_data("user" => { "id" => 123 })
602
- transaction.set_custom_data("user" => { "id" => 456 })
668
+ context "when the given session data is nil" do
669
+ it "does not update the session data on the transaction" do
670
+ data = { "key" => "value" }
671
+ transaction.set_session_data(data)
672
+ transaction.set_session_data(nil)
603
673
 
604
674
  transaction._sample
605
- expect(transaction).to include_custom_data("user" => { "id" => 456 })
675
+ expect(transaction).to include_session_data(data)
606
676
  end
607
677
  end
678
+ end
608
679
 
609
- describe "#add_breadcrumb" do
610
- context "when over the limit" do
611
- before do
612
- 22.times do |i|
613
- transaction.add_breadcrumb(
614
- "network",
615
- "GET http://localhost",
616
- "User made external network request",
617
- { :code => i + 1 },
618
- Time.parse("10-10-2010 10:00:00 UTC")
619
- )
620
- end
621
- transaction.sample_data
622
- end
680
+ describe "#set_session_data_if_nil" do
681
+ let(:transaction) { new_transaction }
623
682
 
624
- it "stores last <LIMIT> breadcrumbs on the transaction" do
625
- expect(transaction.to_h["sample_data"]["breadcrumbs"].length).to eql(20)
626
- expect(transaction.to_h["sample_data"]["breadcrumbs"][0]).to eq(
627
- "action" => "GET http://localhost",
628
- "category" => "network",
629
- "message" => "User made external network request",
630
- "metadata" => { "code" => 3 },
631
- "time" => 1286704800 # rubocop:disable Style/NumericLiterals
632
- )
633
- expect(transaction.to_h["sample_data"]["breadcrumbs"][19]).to eq(
634
- "action" => "GET http://localhost",
635
- "category" => "network",
636
- "message" => "User made external network request",
637
- "metadata" => { "code" => 22 },
638
- "time" => 1286704800 # rubocop:disable Style/NumericLiterals
639
- )
640
- end
683
+ context "when the params are not set" do
684
+ it "sets the params on the transaction" do
685
+ data = { "key" => "value" }
686
+ transaction.set_session_data_if_nil(data)
687
+
688
+ transaction._sample
689
+ expect(transaction).to include_session_data(data)
641
690
  end
642
691
 
643
- context "with defaults" do
644
- it "stores breadcrumb with defaults on transaction" do
645
- timeframe_start = Time.now.utc.to_i
646
- transaction.add_breadcrumb("user_action", "clicked HOME")
647
- transaction.sample_data
648
- timeframe_end = Time.now.utc.to_i
692
+ it "updates the params on the transaction with a block" do
693
+ data = { "key" => "value" }
694
+ transaction.set_session_data_if_nil { data }
649
695
 
650
- expect(transaction).to include_breadcrumb(
651
- "clicked HOME",
652
- "user_action",
653
- "",
654
- {},
655
- be_between(timeframe_start, timeframe_end)
656
- )
657
- end
696
+ transaction._sample
697
+ expect(transaction).to include_session_data(data)
658
698
  end
659
699
 
660
- context "with metadata argument that's not a Hash" do
661
- it "does not add the breadcrumb and logs and error" do
662
- transaction.add_breadcrumb("category", "action", "message", "invalid metadata")
663
- transaction.sample_data
700
+ it "updates with the params argument when both an argument and block are given" do
701
+ arg_data = { "argument" => "value" }
702
+ block_data = { "block" => "value" }
703
+ transaction.set_session_data_if_nil(arg_data) { block_data }
664
704
 
665
- expect(transaction).to_not include_breadcrumbs
666
- expect(log_contents(log)).to contains_log(
667
- :error,
668
- "add_breadcrumb: Cannot add breadcrumb. The given metadata argument is not a Hash."
669
- )
705
+ transaction._sample
706
+ expect(transaction).to include_session_data(arg_data)
707
+ end
708
+
709
+ context "when the given params is nil" do
710
+ it "does not update the params on the transaction" do
711
+ data = { "key" => "value" }
712
+ transaction.set_session_data(data)
713
+ transaction.set_session_data_if_nil(nil)
714
+
715
+ transaction._sample
716
+ expect(transaction).to include_session_data(data)
670
717
  end
671
718
  end
672
719
  end
673
720
 
674
- describe "#set_action" do
675
- context "when the action is set" do
676
- it "updates the action name on the transaction" do
677
- action_name = "PagesController#show"
678
- transaction.set_action(action_name)
721
+ context "when the params are set" do
722
+ it "does not update the params on the transaction" do
723
+ preset_data = { "other" => "data" }
724
+ data = { "key" => "value" }
725
+ transaction.set_session_data(preset_data)
726
+ transaction.set_session_data_if_nil(data)
679
727
 
680
- expect(transaction.action).to eq(action_name)
681
- expect(transaction).to have_action(action_name)
682
- end
728
+ transaction._sample
729
+ expect(transaction).to include_session_data(preset_data)
683
730
  end
684
731
 
685
- context "when the action is nil" do
686
- it "does not update the action name on the transaction" do
687
- action_name = "PagesController#show"
688
- transaction.set_action(action_name)
689
- transaction.set_action(nil)
732
+ it "does not update the params with a block on the transaction" do
733
+ preset_data = { "other" => "data" }
734
+ data = { "key" => "value" }
735
+ transaction.set_session_data(preset_data)
736
+ transaction.set_session_data_if_nil { data }
690
737
 
691
- expect(transaction.action).to eq(action_name)
692
- expect(transaction).to have_action(action_name)
693
- end
738
+ transaction._sample
739
+ expect(transaction).to include_session_data(preset_data)
694
740
  end
695
741
  end
742
+ end
696
743
 
697
- describe "#set_action_if_nil" do
698
- context "when the action is not set" do
699
- it "updates the action name on the transaction" do
700
- expect(transaction.action).to eq(nil)
701
- expect(transaction).to_not have_action
744
+ describe "#set_headers" do
745
+ let(:transaction) { new_transaction }
702
746
 
703
- action_name = "PagesController#show"
704
- transaction.set_action_if_nil(action_name)
747
+ context "when the headers are set" do
748
+ it "updates the headers on the transaction" do
749
+ headers = { "PATH_INFO" => "value" }
750
+ transaction.set_headers(headers)
705
751
 
706
- expect(transaction.action).to eq(action_name)
707
- expect(transaction).to have_action(action_name)
708
- end
752
+ transaction._sample
753
+ expect(transaction).to include_environment(headers)
754
+ end
709
755
 
710
- context "when the given action is nil" do
711
- it "does not update the action name on the transaction" do
712
- action_name = "something"
713
- transaction.set_action("something")
714
- transaction.set_action_if_nil(nil)
756
+ it "updates the headers on the transaction with a block" do
757
+ headers = { "PATH_INFO" => "value" }
758
+ transaction.set_headers { headers }
715
759
 
716
- expect(transaction.action).to eq(action_name)
717
- expect(transaction).to have_action(action_name)
718
- end
719
- end
760
+ transaction._sample
761
+ expect(transaction).to include_environment(headers)
720
762
  end
721
763
 
722
- context "when the action is set" do
723
- it "does not update the action name on the transaction" do
724
- action_name = "something"
725
- transaction.set_action("something")
726
- transaction.set_action_if_nil("something else")
764
+ it "updates with the headers argument when both an argument and block are given" do
765
+ arg_data = { "PATH_INFO" => "/arg-path" }
766
+ block_data = { "PATH_INFO" => "/block-path" }
767
+ transaction.set_headers(arg_data) { block_data }
727
768
 
728
- expect(transaction.action).to eq(action_name)
729
- expect(transaction).to have_action(action_name)
730
- end
769
+ transaction._sample
770
+ expect(transaction).to include_environment(arg_data)
731
771
  end
732
- end
733
772
 
734
- describe "#set_namespace" do
735
- context "when the namespace is not nil" do
736
- it "updates the namespace on the transaction" do
737
- namespace = "custom"
738
- transaction.set_namespace(namespace)
773
+ it "does not include filtered out headers" do
774
+ Appsignal.config[:request_headers] = ["MY_HEADER"]
775
+ transaction.set_headers("MY_HEADER" => "value1", "filtered_key" => "filtered_value")
739
776
 
740
- expect(transaction.namespace).to eq namespace
741
- expect(transaction).to have_namespace(namespace)
742
- end
777
+ transaction._sample
778
+ expect(transaction).to include_environment("MY_HEADER" => "value1")
743
779
  end
744
780
 
745
- context "when the namespace is nil" do
746
- it "does not update the namespace on the transaction" do
747
- namespace = "custom"
748
- transaction.set_namespace(namespace)
749
- transaction.set_namespace(nil)
781
+ it "logs an error if an error occurred storing the headers" do
782
+ transaction.set_headers { raise "uh oh" }
750
783
 
751
- expect(transaction.namespace).to eq(namespace)
752
- expect(transaction).to have_namespace(namespace)
753
- end
784
+ logs = capture_logs { transaction._sample }
785
+ expect(logs).to contains_log(
786
+ :error,
787
+ "Exception while fetching headers: RuntimeError: uh oh"
788
+ )
754
789
  end
755
790
  end
756
791
 
757
- describe "#set_http_or_background_action" do
758
- context "for a hash with controller and action" do
759
- it "sets the action" do
760
- transaction.set_http_or_background_action(
761
- :controller => "HomeController",
762
- :action => "show"
763
- )
764
- expect(transaction).to have_action("HomeController#show")
765
- end
792
+ context "when the given headers is nil" do
793
+ it "does not update the headers on the transaction" do
794
+ headers = { "PATH_INFO" => "value" }
795
+ transaction.set_headers(headers)
796
+ transaction.set_headers(nil)
797
+
798
+ transaction._sample
799
+ expect(transaction).to include_environment(headers)
766
800
  end
801
+ end
802
+ end
767
803
 
768
- context "for a hash with just action" do
769
- it "sets the action" do
770
- transaction.set_http_or_background_action(:action => "show")
771
- expect(transaction).to have_action("show")
772
- end
804
+ describe "#set_headers_if_nil" do
805
+ let(:transaction) { new_transaction }
806
+
807
+ context "when the params are not set" do
808
+ it "sets the params on the transaction" do
809
+ headers = { "PATH_INFO" => "value" }
810
+ transaction.set_headers_if_nil(headers)
811
+
812
+ transaction._sample
813
+ expect(transaction).to include_environment(headers)
773
814
  end
774
815
 
775
- context "for a hash with class and method" do
776
- it "sets the action" do
777
- transaction.set_http_or_background_action(:class => "Worker", :method => "perform")
778
- expect(transaction).to have_action("Worker#perform")
779
- end
816
+ it "updates the params on the transaction with a block" do
817
+ headers = { "PATH_INFO" => "value" }
818
+ transaction.set_headers_if_nil { headers }
819
+
820
+ transaction._sample
821
+ expect(transaction).to include_environment(headers)
822
+ end
823
+
824
+ it "updates with the params argument when both an argument and block are given" do
825
+ arg_data = { "PATH_INFO" => "/arg-path" }
826
+ block_data = { "PATH_INFO" => "/block-path" }
827
+ transaction.set_headers_if_nil(arg_data) { block_data }
828
+
829
+ transaction._sample
830
+ expect(transaction).to include_environment(arg_data)
780
831
  end
781
832
 
782
- context "when action is already set" do
783
- it "does not overwrite the set action" do
784
- transaction.set_action("MyCustomAction#perform")
785
- transaction.set_http_or_background_action(:class => "Worker", :method => "perform")
786
- expect(transaction).to have_action("MyCustomAction#perform")
833
+ context "when the given params is nil" do
834
+ it "does not update the params on the transaction" do
835
+ headers = { "PATH_INFO" => "value" }
836
+ transaction.set_headers(headers)
837
+ transaction.set_headers_if_nil(nil)
838
+
839
+ transaction._sample
840
+ expect(transaction).to include_environment(headers)
787
841
  end
788
842
  end
789
843
  end
790
844
 
791
- describe "#set_queue_start" do
792
- it "sets the queue start in extension" do
793
- expect(transaction.ext).to receive(:set_queue_start).with(10.0).once
845
+ context "when the params are set" do
846
+ it "does not update the params on the transaction" do
847
+ preset_headers = { "PATH_INFO" => "/first-path" }
848
+ headers = { "PATH_INFO" => "/other-path" }
849
+ transaction.set_headers(preset_headers)
850
+ transaction.set_headers_if_nil(headers)
794
851
 
795
- transaction.set_queue_start(10.0)
852
+ transaction._sample
853
+ expect(transaction).to include_environment(preset_headers)
796
854
  end
797
855
 
798
- it "does not set the queue start in extension when value is nil" do
799
- expect(transaction.ext).to_not receive(:set_queue_start)
856
+ it "does not update the params with a block on the transaction" do
857
+ preset_headers = { "PATH_INFO" => "/first-path" }
858
+ headers = { "PATH_INFO" => "/other-path" }
859
+ transaction.set_headers(preset_headers)
860
+ transaction.set_headers_if_nil { headers }
800
861
 
801
- transaction.set_queue_start(nil)
862
+ transaction._sample
863
+ expect(transaction).to include_environment(preset_headers)
802
864
  end
865
+ end
866
+ end
803
867
 
804
- it "does not raise an error when the queue start is too big" do
805
- expect(transaction.ext).to receive(:set_queue_start).and_raise(RangeError)
868
+ describe "#set_tags" do
869
+ let(:transaction) { new_transaction }
870
+ let(:long_string) { "a" * 10_001 }
871
+
872
+ it "stores tags on the transaction" do
873
+ transaction.set_tags(
874
+ :valid_key => "valid_value",
875
+ "valid_string_key" => "valid_value",
876
+ :both_symbols => :valid_value,
877
+ :integer_value => 1,
878
+ :hash_value => { "invalid" => "hash" },
879
+ :array_value => %w[invalid array],
880
+ :object => Object.new,
881
+ :too_long_value => long_string,
882
+ long_string => "too_long_key",
883
+ :true_tag => true,
884
+ :false_tag => false
885
+ )
886
+ transaction._sample
887
+
888
+ expect(transaction).to include_tags(
889
+ "valid_key" => "valid_value",
890
+ "valid_string_key" => "valid_value",
891
+ "both_symbols" => "valid_value",
892
+ "integer_value" => 1,
893
+ "too_long_value" => "#{"a" * 10_000}...",
894
+ long_string => "too_long_key",
895
+ "true_tag" => true,
896
+ "false_tag" => false
897
+ )
898
+ end
806
899
 
807
- expect(Appsignal.internal_logger).to receive(:warn).with("Queue start value 10 is too big")
900
+ it "merges the tags when called multiple times" do
901
+ transaction.set_tags(:key1 => "value1")
902
+ transaction.set_tags(:key2 => "value2")
903
+ transaction._sample
808
904
 
809
- transaction.set_queue_start(10)
810
- end
905
+ expect(transaction).to include_tags(
906
+ "key1" => "value1",
907
+ "key2" => "value2"
908
+ )
811
909
  end
910
+ end
812
911
 
813
- describe "#set_http_or_background_queue_start" do
814
- let(:header_factor) { 1_000 }
815
- let(:env_queue_start) { fixed_time + 20 } # in seconds
912
+ describe "#set_custom_data" do
913
+ let(:transaction) { new_transaction }
914
+
915
+ it "stores custom Hash data on the transaction" do
916
+ transaction.set_custom_data(
917
+ :user => {
918
+ :id => 123,
919
+ :locale => "abc"
920
+ },
921
+ :organization => {
922
+ :slug => "appsignal",
923
+ :plan => "enterprise"
924
+ }
925
+ )
926
+
927
+ transaction._sample
928
+ expect(transaction).to include_custom_data(
929
+ "user" => {
930
+ "id" => 123,
931
+ "locale" => "abc"
932
+ },
933
+ "organization" => {
934
+ "slug" => "appsignal",
935
+ "plan" => "enterprise"
936
+ }
937
+ )
938
+ end
816
939
 
817
- context "when a queue time is found in a request header" do
818
- let(:header_time) { ((fixed_time + 10) * header_factor).to_i } # in milliseconds
819
- let(:env) { { "HTTP_X_REQUEST_START" => "t=#{header_time}" } }
940
+ it "stores custom Array data on the transaction" do
941
+ transaction.set_custom_data([
942
+ [123, "abc"],
943
+ ["appsignal", "enterprise"]
944
+ ])
945
+
946
+ transaction._sample
947
+ expect(transaction).to include_custom_data([
948
+ [123, "abc"],
949
+ ["appsignal", "enterprise"]
950
+ ])
951
+ end
820
952
 
821
- it "sets the http header value in milliseconds on the transaction" do
822
- expect(transaction).to receive(:set_queue_start).with(1_389_783_610_000)
953
+ it "does not store non Hash or Array custom data" do
954
+ logs =
955
+ capture_logs do
956
+ transaction.set_custom_data("abc")
957
+ transaction._sample
958
+ expect(transaction).to_not include_custom_data
959
+
960
+ transaction.set_custom_data(123)
961
+ transaction._sample
962
+ expect(transaction).to_not include_custom_data
963
+
964
+ transaction.set_custom_data(Object.new)
965
+ transaction._sample
966
+ expect(transaction).to_not include_custom_data
967
+ end
968
+
969
+ expect(logs).to contains_log(
970
+ :error,
971
+ "set_custom_data: Unsupported data type String received."
972
+ )
973
+ expect(logs).to contains_log(
974
+ :error,
975
+ "set_custom_data: Unsupported data type Integer received."
976
+ )
977
+ expect(logs).to contains_log(
978
+ :error,
979
+ "set_custom_data: Unsupported data type String received."
980
+ )
981
+ end
982
+
983
+ it "overwrites the custom data if called multiple times" do
984
+ transaction.set_custom_data("user" => { "id" => 123 })
985
+ transaction.set_custom_data("user" => { "id" => 456 })
986
+
987
+ transaction._sample
988
+ expect(transaction).to include_custom_data("user" => { "id" => 456 })
989
+ end
990
+ end
823
991
 
824
- transaction.set_http_or_background_queue_start
992
+ describe "#add_breadcrumb" do
993
+ let(:transaction) { new_transaction }
994
+
995
+ context "when over the limit" do
996
+ before do
997
+ 22.times do |i|
998
+ transaction.add_breadcrumb(
999
+ "network",
1000
+ "GET http://localhost",
1001
+ "User made external network request",
1002
+ { :code => i + 1 },
1003
+ Time.parse("10-10-2010 10:00:00 UTC")
1004
+ )
825
1005
  end
1006
+ transaction._sample
1007
+ end
826
1008
 
827
- context "when a :queue_start key is found in the transaction environment" do
828
- let(:env) do
829
- {
830
- "HTTP_X_REQUEST_START" => "t=#{header_time}",
831
- :queue_start => env_queue_start
832
- }
833
- end
1009
+ it "stores last <LIMIT> breadcrumbs on the transaction" do
1010
+ expect(transaction.to_h["sample_data"]["breadcrumbs"].length).to eql(20)
1011
+ expect(transaction.to_h["sample_data"]["breadcrumbs"][0]).to eq(
1012
+ "action" => "GET http://localhost",
1013
+ "category" => "network",
1014
+ "message" => "User made external network request",
1015
+ "metadata" => { "code" => 3 },
1016
+ "time" => 1286704800 # rubocop:disable Style/NumericLiterals
1017
+ )
1018
+ expect(transaction.to_h["sample_data"]["breadcrumbs"][19]).to eq(
1019
+ "action" => "GET http://localhost",
1020
+ "category" => "network",
1021
+ "message" => "User made external network request",
1022
+ "metadata" => { "code" => 22 },
1023
+ "time" => 1286704800 # rubocop:disable Style/NumericLiterals
1024
+ )
1025
+ end
1026
+ end
834
1027
 
835
- it "sets the http header value in milliseconds on the transaction" do
836
- expect(transaction).to receive(:set_queue_start).with(1_389_783_610_000)
1028
+ context "with defaults" do
1029
+ it "stores breadcrumb with defaults on transaction" do
1030
+ timeframe_start = Time.now.utc.to_i
1031
+ transaction.add_breadcrumb("user_action", "clicked HOME")
1032
+ transaction._sample
1033
+ timeframe_end = Time.now.utc.to_i
1034
+
1035
+ expect(transaction).to include_breadcrumb(
1036
+ "clicked HOME",
1037
+ "user_action",
1038
+ "",
1039
+ {},
1040
+ be_between(timeframe_start, timeframe_end)
1041
+ )
1042
+ end
1043
+ end
837
1044
 
838
- transaction.set_http_or_background_queue_start
1045
+ context "with metadata argument that's not a Hash" do
1046
+ it "does not add the breadcrumb and logs and error" do
1047
+ logs =
1048
+ capture_logs do
1049
+ transaction.add_breadcrumb("category", "action", "message", "invalid metadata")
839
1050
  end
840
- end
1051
+ transaction._sample
1052
+
1053
+ expect(transaction).to_not include_breadcrumbs
1054
+ expect(logs).to contains_log(
1055
+ :error,
1056
+ "add_breadcrumb: Cannot add breadcrumb. The given metadata argument is not a Hash."
1057
+ )
841
1058
  end
1059
+ end
1060
+ end
842
1061
 
843
- context "when a :queue_start key is found in the transaction environment" do
844
- let(:env) { { :queue_start => env_queue_start } } # in seconds
1062
+ describe "#set_action" do
1063
+ let(:transaction) { new_transaction }
845
1064
 
846
- it "sets the :queue_start value in milliseconds on the transaction" do
847
- expect(transaction).to receive(:set_queue_start).with(1_389_783_620_000)
1065
+ context "when the action is set" do
1066
+ it "updates the action name on the transaction" do
1067
+ action_name = "PagesController#show"
1068
+ transaction.set_action(action_name)
848
1069
 
849
- transaction.set_http_or_background_queue_start
850
- end
1070
+ expect(transaction.action).to eq(action_name)
1071
+ expect(transaction).to have_action(action_name)
851
1072
  end
852
1073
  end
853
1074
 
854
- describe "#set_metadata" do
855
- it "updates the metadata on the transaction" do
856
- transaction.set_metadata("request_method", "GET")
1075
+ context "when the action is nil" do
1076
+ it "does not update the action name on the transaction" do
1077
+ action_name = "PagesController#show"
1078
+ transaction.set_action(action_name)
1079
+ transaction.set_action(nil)
857
1080
 
858
- expect(transaction).to include_metadata("request_method" => "GET")
1081
+ expect(transaction.action).to eq(action_name)
1082
+ expect(transaction).to have_action(action_name)
859
1083
  end
1084
+ end
1085
+ end
860
1086
 
861
- context "when filter_metadata includes metadata key" do
862
- before { Appsignal.config[:filter_metadata] = ["filter_key"] }
863
- after { Appsignal.config[:filter_metadata] = [] }
1087
+ describe "#set_action_if_nil" do
1088
+ let(:transaction) { new_transaction }
864
1089
 
865
- it "does not set the metadata on the transaction" do
866
- transaction.set_metadata(:filter_key, "filtered value")
867
- transaction.set_metadata("filter_key", "filtered value")
1090
+ context "when the action is not set" do
1091
+ it "updates the action name on the transaction" do
1092
+ expect(transaction.action).to eq(nil)
1093
+ expect(transaction).to_not have_action
868
1094
 
869
- expect(transaction).to_not include_metadata("filter_key" => anything)
870
- end
1095
+ action_name = "PagesController#show"
1096
+ transaction.set_action_if_nil(action_name)
1097
+
1098
+ expect(transaction.action).to eq(action_name)
1099
+ expect(transaction).to have_action(action_name)
871
1100
  end
872
1101
 
873
- context "when the key is nil" do
874
- it "does not update the metadata on the transaction" do
875
- transaction.set_metadata(nil, "GET")
1102
+ context "when the given action is nil" do
1103
+ it "does not update the action name on the transaction" do
1104
+ action_name = "something"
1105
+ transaction.set_action("something")
1106
+ transaction.set_action_if_nil(nil)
876
1107
 
877
- expect(transaction).to_not include_metadata
1108
+ expect(transaction.action).to eq(action_name)
1109
+ expect(transaction).to have_action(action_name)
878
1110
  end
879
1111
  end
1112
+ end
880
1113
 
881
- context "when the value is nil" do
882
- it "does not update the metadata on the transaction" do
883
- transaction.set_metadata("request_method", nil)
1114
+ context "when the action is set" do
1115
+ it "does not update the action name on the transaction" do
1116
+ action_name = "something"
1117
+ transaction.set_action("something")
1118
+ transaction.set_action_if_nil("something else")
884
1119
 
885
- expect(transaction).to_not include_metadata
886
- end
1120
+ expect(transaction.action).to eq(action_name)
1121
+ expect(transaction).to have_action(action_name)
887
1122
  end
888
1123
  end
1124
+ end
889
1125
 
890
- describe "#set_sample_data" do
891
- it "updates the sample data on the transaction" do
892
- transaction.set_sample_data(
893
- "params",
894
- :controller => "blog_posts",
895
- :action => "show",
896
- :id => "1"
897
- )
1126
+ describe "#set_namespace" do
1127
+ let(:transaction) { new_transaction }
898
1128
 
899
- expect(transaction).to include_params(
900
- "action" => "show",
901
- "controller" => "blog_posts",
902
- "id" => "1"
1129
+ context "when the namespace is not nil" do
1130
+ it "updates the namespace on the transaction" do
1131
+ namespace = "custom"
1132
+ transaction.set_namespace(namespace)
1133
+
1134
+ expect(transaction.namespace).to eq namespace
1135
+ expect(transaction).to have_namespace(namespace)
1136
+ end
1137
+ end
1138
+
1139
+ context "when the namespace is nil" do
1140
+ it "does not update the namespace on the transaction" do
1141
+ namespace = "custom"
1142
+ transaction.set_namespace(namespace)
1143
+ transaction.set_namespace(nil)
1144
+
1145
+ expect(transaction.namespace).to eq(namespace)
1146
+ expect(transaction).to have_namespace(namespace)
1147
+ end
1148
+ end
1149
+ end
1150
+
1151
+ describe "#set_http_or_background_action" do
1152
+ let(:transaction) { new_transaction }
1153
+
1154
+ context "for a hash with controller and action" do
1155
+ it "sets the action" do
1156
+ transaction.set_http_or_background_action(
1157
+ :controller => "HomeController",
1158
+ :action => "show"
903
1159
  )
1160
+ expect(transaction).to have_action("HomeController#show")
904
1161
  end
1162
+ end
905
1163
 
906
- context "when the data is no Array or Hash" do
907
- it "does not update the sample data on the transaction" do
908
- transaction.set_sample_data("params", "string")
1164
+ context "for a hash with just action" do
1165
+ it "sets the action" do
1166
+ transaction.set_http_or_background_action(:action => "show")
1167
+ expect(transaction).to have_action("show")
1168
+ end
1169
+ end
909
1170
 
910
- expect(transaction.to_h["sample_data"]).to eq({})
911
- expect(log_contents(log)).to contains_log :error,
912
- %(Invalid sample data for 'params'. Value is not an Array or Hash: '"string"')
913
- end
1171
+ context "for a hash with class and method" do
1172
+ it "sets the action" do
1173
+ transaction.set_http_or_background_action(:class => "Worker", :method => "perform")
1174
+ expect(transaction).to have_action("Worker#perform")
914
1175
  end
1176
+ end
915
1177
 
916
- context "when the data cannot be converted to JSON" do
917
- it "does not update the sample data on the transaction" do
918
- klass = Class.new do
919
- def to_s
920
- raise "foo" # Cause a deliberate error
921
- end
922
- end
923
- transaction.set_sample_data("params", klass.new => 1)
1178
+ context "when action is already set" do
1179
+ it "does not overwrite the set action" do
1180
+ transaction.set_action("MyCustomAction#perform")
1181
+ transaction.set_http_or_background_action(:class => "Worker", :method => "perform")
1182
+ expect(transaction).to have_action("MyCustomAction#perform")
1183
+ end
1184
+ end
1185
+ end
924
1186
 
925
- expect(transaction).to_not include_params
926
- expect(log_contents(log)).to contains_log :error,
927
- "Error generating data (RuntimeError: foo) for"
928
- end
1187
+ describe "#set_queue_start" do
1188
+ let(:transaction) { new_transaction }
1189
+
1190
+ it "sets the queue start in extension" do
1191
+ transaction.set_queue_start(10)
1192
+
1193
+ expect(transaction).to have_queue_start(10)
1194
+ end
1195
+
1196
+ it "does not set the queue start in extension when value is nil" do
1197
+ transaction.set_queue_start(nil)
1198
+
1199
+ expect(transaction).to_not have_queue_start
1200
+ end
1201
+
1202
+ it "does not raise an error when the queue start is too big" do
1203
+ expect(transaction.ext).to receive(:set_queue_start).and_raise(RangeError)
1204
+
1205
+ expect(Appsignal.internal_logger).to receive(:warn).with("Queue start value 10 is too big")
1206
+
1207
+ transaction.set_queue_start(10)
1208
+ end
1209
+ end
1210
+
1211
+ describe "#set_http_or_background_queue_start" do
1212
+ let(:transaction) { legacy_new_transaction(:request => legacy_request(env)) }
1213
+ let(:err_stream) { std_stream }
1214
+ let(:stderr) { err_stream.read }
1215
+ let(:header_factor) { 1_000 }
1216
+ let(:env_queue_start) { fixed_time + 20 } # in seconds
1217
+
1218
+ def set_http_or_background_queue_start
1219
+ capture_std_streams(std_stream, err_stream) do
1220
+ transaction.set_http_or_background_queue_start
929
1221
  end
930
1222
  end
931
1223
 
932
- describe "#sample_data" do
933
- let(:env) { { "rack.session" => { "session" => "value" } } }
1224
+ context "when a queue time is found in a request header" do
1225
+ let(:header_time) { ((fixed_time + 10) * header_factor).to_i } # in milliseconds
1226
+ let(:env) { { "HTTP_X_REQUEST_START" => "t=#{header_time}" } }
934
1227
 
935
- it "sets sample data" do
936
- transaction.set_tags "tag" => "value"
937
- transaction.add_breadcrumb "category", "action", "message", "key" => "value"
938
- transaction.sample_data
1228
+ it "sets the http header value in milliseconds on the transaction" do
1229
+ set_http_or_background_queue_start
939
1230
 
940
- expect(transaction).to include_environment(
941
- "REQUEST_METHOD" => "GET",
942
- "SERVER_NAME" => "example.org",
943
- "SERVER_PORT" => "80",
944
- "PATH_INFO" => "/blog"
945
- )
946
- expect(transaction).to include_session_data("session" => "value")
947
- expect(transaction).to include_params(
948
- "controller" => "blog_posts",
949
- "action" => "show",
950
- "id" => "1"
1231
+ expect(transaction).to have_queue_start(1_389_783_610_000)
1232
+ end
1233
+
1234
+ it "logs a deprecation message" do
1235
+ logs = capture_logs { set_http_or_background_queue_start }
1236
+
1237
+ expect(logs).to contains_log(
1238
+ :warn,
1239
+ "The Appsignal::Transaction#set_http_or_background_queue_start " \
1240
+ "method has been deprecated."
951
1241
  )
952
- expect(transaction).to include_sample_metadata("key" => "value")
953
- expect(transaction).to include_tags("tag" => "value")
954
- expect(transaction).to include_breadcrumb(
955
- "action",
956
- "category",
957
- "message",
958
- { "key" => "value" },
959
- kind_of(Integer)
1242
+ end
1243
+
1244
+ it "prints a deprecation message" do
1245
+ set_http_or_background_queue_start
1246
+
1247
+ expect(stderr).to include(
1248
+ "The Appsignal::Transaction#set_http_or_background_queue_start " \
1249
+ "method has been deprecated."
960
1250
  )
961
1251
  end
962
1252
 
963
- context "when params is a callable object" do
964
- it "calls the params object and sets the return value as parametesr" do
965
- transaction.set_params { { "param1" => "value1" } }
1253
+ context "when a :queue_start key is found in the transaction environment" do
1254
+ let(:env) do
1255
+ {
1256
+ "HTTP_X_REQUEST_START" => "t=#{header_time}",
1257
+ :queue_start => env_queue_start
1258
+ }
1259
+ end
966
1260
 
967
- transaction.sample_data
968
- expect(transaction).to include_params(
969
- "param1" => "value1"
970
- )
1261
+ it "sets the http header value in milliseconds on the transaction" do
1262
+ set_http_or_background_queue_start
1263
+
1264
+ expect(transaction).to have_queue_start(1_389_783_610_000)
971
1265
  end
972
1266
  end
973
1267
  end
974
1268
 
975
- describe "#set_error" do
976
- let(:env) { http_request_env_with_data }
977
- let(:error) do
978
- e = ExampleStandardError.new("test message")
979
- allow(e).to receive(:backtrace).and_return(["line 1"])
980
- e
1269
+ context "when a :queue_start key is found in the transaction environment" do
1270
+ let(:env) { { :queue_start => env_queue_start } } # in seconds
1271
+
1272
+ it "sets the :queue_start value in milliseconds on the transaction" do
1273
+ set_http_or_background_queue_start
1274
+
1275
+ expect(transaction).to have_queue_start(1_389_783_620_000)
981
1276
  end
1277
+ end
1278
+ end
1279
+
1280
+ describe "#set_metadata" do
1281
+ let(:transaction) { new_transaction }
982
1282
 
983
- it "should also respond to add_exception for backwards compatibility" do
984
- expect(transaction).to respond_to(:add_exception)
1283
+ it "updates the metadata on the transaction" do
1284
+ transaction.set_metadata("request_method", "GET")
1285
+
1286
+ expect(transaction).to include_metadata("request_method" => "GET")
1287
+ end
1288
+
1289
+ context "when filter_metadata includes metadata key" do
1290
+ before { Appsignal.config[:filter_metadata] = ["filter_key"] }
1291
+ after { Appsignal.config[:filter_metadata] = [] }
1292
+
1293
+ it "does not set the metadata on the transaction" do
1294
+ transaction.set_metadata(:filter_key, "filtered value")
1295
+ transaction.set_metadata("filter_key", "filtered value")
1296
+
1297
+ expect(transaction).to_not include_metadata("filter_key" => anything)
985
1298
  end
1299
+ end
986
1300
 
987
- it "should not add the error if appsignal is not active" do
988
- allow(Appsignal).to receive(:active?).and_return(false)
989
- expect(transaction.ext).to_not receive(:set_error)
1301
+ context "when the key is nil" do
1302
+ it "does not update the metadata on the transaction" do
1303
+ transaction.set_metadata(nil, "GET")
990
1304
 
991
- transaction.set_error(error)
1305
+ expect(transaction).to_not include_metadata
992
1306
  end
1307
+ end
993
1308
 
994
- context "when error is not an error" do
995
- let(:error) { Object.new }
1309
+ context "when the value is nil" do
1310
+ it "does not update the metadata on the transaction" do
1311
+ transaction.set_metadata("request_method", nil)
996
1312
 
997
- it "does not add the error" do
998
- expect(Appsignal.internal_logger).to receive(:error).with(
999
- "Appsignal::Transaction#set_error: Cannot set error. " \
1000
- "The given value is not an exception: #{error.inspect}"
1001
- )
1002
- expect(transaction.ext).to_not receive(:set_error)
1313
+ expect(transaction).to_not include_metadata
1314
+ end
1315
+ end
1316
+ end
1317
+
1318
+ describe "storing sample data" do
1319
+ let(:transaction) { new_transaction }
1320
+
1321
+ it "stores sample data on the transaction" do
1322
+ transaction.set_params(
1323
+ "string_param" => "string_value",
1324
+ :symbol_param => "symbol_value",
1325
+ "integer" => 123,
1326
+ "float" => 123.45,
1327
+ "array" => ["abc", 456, { "option" => true }],
1328
+ "hash" => { "hash_key" => "hash_value" }
1329
+ )
1330
+
1331
+ transaction._sample
1332
+ expect(transaction).to include_params(
1333
+ "string_param" => "string_value",
1334
+ "symbol_param" => "symbol_value",
1335
+ "integer" => 123,
1336
+ "float" => 123.45,
1337
+ "array" => ["abc", 456, { "option" => true }],
1338
+ "hash" => { "hash_key" => "hash_value" }
1339
+ )
1340
+ end
1003
1341
 
1004
- transaction.set_error(error)
1342
+ it "does not store non-Array and non-Hash data" do
1343
+ logs =
1344
+ capture_logs do
1345
+ transaction.set_params("some string")
1346
+ transaction._sample
1347
+ expect(transaction).to_not include_params
1348
+
1349
+ transaction.set_params(123)
1350
+ transaction._sample
1351
+ expect(transaction).to_not include_params
1352
+
1353
+ transaction.set_params(Class.new)
1354
+ transaction._sample
1355
+ expect(transaction).to_not include_params
1356
+
1357
+ set = Set.new
1358
+ set.add("some value")
1359
+ transaction.set_params(set)
1360
+ transaction._sample
1361
+ expect(transaction).to_not include_params
1005
1362
  end
1006
- end
1007
1363
 
1008
- context "for a http request" do
1009
- it "should set an error in the extension" do
1010
- expect(transaction.ext).to receive(:set_error).with(
1011
- "ExampleStandardError",
1012
- "test message",
1013
- Appsignal::Utils::Data.generate(["line 1"])
1014
- )
1364
+ expect(logs).to contains_log :error,
1365
+ %(Invalid sample data for 'params'. Value is not an Array or Hash: '"some string"')
1366
+ expect(logs).to contains_log :error,
1367
+ %(Invalid sample data for 'params'. Value is not an Array or Hash: '123')
1368
+ expect(logs).to contains_log :error,
1369
+ %(Invalid sample data for 'params'. Value is not an Array or Hash: '"#<Class>"')
1370
+ expect(logs).to contains_log :error,
1371
+ %(Invalid sample data for 'params'. Value is not an Array or Hash: '"#<Set>"')
1372
+ end
1015
1373
 
1016
- transaction.set_error(error)
1374
+ it "does not store data that can't be converted to JSON" do
1375
+ klass = Class.new do
1376
+ def initialize
1377
+ @calls = 0
1017
1378
  end
1018
- end
1019
1379
 
1020
- context "when the error has no causes" do
1021
- it "should not send the causes information as sample data" do
1022
- expect(transaction.ext).to_not receive(:set_sample_data)
1380
+ def to_s
1381
+ raise "foo" if @calls > 0 # Cause a deliberate error
1023
1382
 
1024
- transaction.set_error(error)
1383
+ @calls += 1
1025
1384
  end
1026
1385
  end
1027
1386
 
1028
- context "when the error has multiple causes" do
1029
- let(:error) do
1030
- e = ExampleStandardError.new("test message")
1031
- e2 = RuntimeError.new("cause message")
1032
- e3 = StandardError.new("cause message 2")
1033
- allow(e).to receive(:backtrace).and_return(["line 1"])
1034
- allow(e).to receive(:cause).and_return(e2)
1035
- allow(e2).to receive(:cause).and_return(e3)
1036
- e
1037
- end
1387
+ transaction.set_params(klass.new => 1)
1388
+ logs = capture_logs { transaction._sample }
1038
1389
 
1039
- it "sends the causes information as sample data" do
1040
- expect(transaction.ext).to receive(:set_error).with(
1041
- "ExampleStandardError",
1042
- "test message",
1043
- Appsignal::Utils::Data.generate(["line 1"])
1044
- )
1390
+ expect(transaction).to_not include_params
1391
+ expect(logs).to contains_log :error,
1392
+ "Error generating data (RuntimeError: foo) for"
1393
+ end
1394
+ end
1045
1395
 
1046
- expect(transaction.ext).to receive(:set_sample_data).with(
1047
- "error_causes",
1048
- Appsignal::Utils::Data.generate(
1049
- [
1050
- {
1051
- :name => "RuntimeError",
1052
- :message => "cause message"
1053
- },
1054
- {
1055
- :name => "StandardError",
1056
- :message => "cause message 2"
1057
- }
1058
- ]
1059
- )
1060
- )
1396
+ describe "#set_sample_data" do
1397
+ let(:transaction) { new_transaction }
1061
1398
 
1062
- expect(Appsignal.internal_logger).to_not receive(:debug)
1399
+ it "updates the sample data on the transaction" do
1400
+ silence do
1401
+ transaction.set_sample_data(
1402
+ "params",
1403
+ :controller => "blog_posts",
1404
+ :action => "show",
1405
+ :id => "1"
1406
+ )
1407
+ end
1408
+
1409
+ expect(transaction).to include_params(
1410
+ "action" => "show",
1411
+ "controller" => "blog_posts",
1412
+ "id" => "1"
1413
+ )
1414
+ end
1415
+
1416
+ context "when the data is no Array or Hash" do
1417
+ it "does not update the sample data on the transaction" do
1418
+ logs =
1419
+ capture_logs do
1420
+ silence { transaction.set_sample_data("params", "string") }
1421
+ end
1422
+
1423
+ expect(transaction.to_h["sample_data"]).to eq({})
1424
+ expect(logs).to contains_log :error,
1425
+ %(Invalid sample data for 'params'. Value is not an Array or Hash: '"string"')
1426
+ end
1427
+ end
1063
1428
 
1064
- transaction.set_error(error)
1429
+ context "when the data cannot be converted to JSON" do
1430
+ it "does not update the sample data on the transaction" do
1431
+ klass = Class.new do
1432
+ def to_s
1433
+ raise "foo" # Cause a deliberate error
1434
+ end
1065
1435
  end
1436
+ logs =
1437
+ capture_logs do
1438
+ silence { transaction.set_sample_data("params", klass.new => 1) }
1439
+ end
1440
+
1441
+ expect(transaction).to_not include_params
1442
+ expect(logs).to contains_log :error,
1443
+ "Error generating data (RuntimeError: foo) for"
1444
+ end
1445
+ end
1446
+ end
1447
+
1448
+ describe "#sample_data" do
1449
+ let(:transaction) { legacy_new_transaction(:request => rack_request(env)) }
1450
+ let(:env) do
1451
+ Rack::MockRequest.env_for(
1452
+ "/blog",
1453
+ "REQUEST_METHOD" => "GET",
1454
+ "SERVER_NAME" => "example.org",
1455
+ "SERVER_PORT" => "80",
1456
+ "PATH_INFO" => "/blog",
1457
+ "rack.session" => { "session" => "value" },
1458
+ :params => {
1459
+ "controller" => "blog_posts",
1460
+ "action" => "show",
1461
+ "id" => "1"
1462
+ }
1463
+ ).merge(
1464
+ :metadata => { "metadata" => "value" }
1465
+ )
1466
+ end
1467
+
1468
+ it "sets sample data from request" do
1469
+ transaction.set_tags "tag" => "value"
1470
+ transaction.add_breadcrumb "category", "action", "message", "key" => "value"
1471
+ silence { transaction.sample_data }
1472
+
1473
+ expect(transaction).to include_environment(
1474
+ "REQUEST_METHOD" => "GET",
1475
+ "SERVER_NAME" => "example.org",
1476
+ "SERVER_PORT" => "80",
1477
+ "PATH_INFO" => "/blog"
1478
+ )
1479
+ expect(transaction).to include_session_data("session" => "value")
1480
+ expect(transaction).to include_params(
1481
+ "controller" => "blog_posts",
1482
+ "action" => "show",
1483
+ "id" => "1"
1484
+ )
1485
+ expect(transaction).to include_sample_metadata("metadata" => "value")
1486
+ expect(transaction).to include_tags("tag" => "value")
1487
+ expect(transaction).to include_breadcrumb(
1488
+ "action",
1489
+ "category",
1490
+ "message",
1491
+ { "key" => "value" },
1492
+ kind_of(Integer)
1493
+ )
1494
+ end
1495
+ end
1496
+
1497
+ describe "#set_error" do
1498
+ let(:transaction) { new_transaction }
1499
+ let(:env) { http_request_env_with_data }
1500
+ let(:error) do
1501
+ e = ExampleStandardError.new("test message")
1502
+ allow(e).to receive(:backtrace).and_return(["line 1"])
1503
+ e
1504
+ end
1505
+
1506
+ it "should also respond to add_exception for backwards compatibility" do
1507
+ expect(transaction).to respond_to(:add_exception)
1508
+ end
1509
+
1510
+ it "should not add the error if appsignal is not active" do
1511
+ allow(Appsignal).to receive(:active?).and_return(false)
1512
+ expect(transaction.ext).to_not receive(:set_error)
1513
+
1514
+ transaction.set_error(error)
1515
+ end
1516
+
1517
+ context "when error is not an error" do
1518
+ let(:error) { Object.new }
1519
+
1520
+ it "does not add the error" do
1521
+ expect(Appsignal.internal_logger).to receive(:error).with(
1522
+ "Appsignal::Transaction#set_error: Cannot set error. " \
1523
+ "The given value is not an exception: #{error.inspect}"
1524
+ )
1525
+ expect(transaction.ext).to_not receive(:set_error)
1526
+
1527
+ transaction.set_error(error)
1066
1528
  end
1529
+ end
1067
1530
 
1068
- context "when the error has too many causes" do
1069
- let(:error) do
1070
- e = ExampleStandardError.new("root cause error")
1531
+ context "for a http request" do
1532
+ it "should set an error in the extension" do
1533
+ expect(transaction.ext).to receive(:set_error).with(
1534
+ "ExampleStandardError",
1535
+ "test message",
1536
+ Appsignal::Utils::Data.generate(["line 1"])
1537
+ )
1071
1538
 
1072
- 11.times do |i|
1073
- next_e = ExampleStandardError.new("wrapper error #{i}")
1074
- allow(next_e).to receive(:cause).and_return(e)
1075
- e = next_e
1076
- end
1539
+ transaction.set_error(error)
1540
+ end
1541
+ end
1542
+
1543
+ context "when the error has no causes" do
1544
+ it "should not send the causes information as sample data" do
1545
+ expect(transaction.ext).to_not receive(:set_sample_data)
1546
+
1547
+ transaction.set_error(error)
1548
+ end
1549
+ end
1550
+
1551
+ context "when the error has multiple causes" do
1552
+ let(:error) do
1553
+ e = ExampleStandardError.new("test message")
1554
+ e2 = RuntimeError.new("cause message")
1555
+ e3 = StandardError.new("cause message 2")
1556
+ allow(e).to receive(:backtrace).and_return(["line 1"])
1557
+ allow(e).to receive(:cause).and_return(e2)
1558
+ allow(e2).to receive(:cause).and_return(e3)
1559
+ e
1560
+ end
1077
1561
 
1078
- allow(e).to receive(:backtrace).and_return(["line 1"])
1079
- e
1080
- end
1562
+ it "sends the causes information as sample data" do
1563
+ expect(transaction.ext).to receive(:set_error).with(
1564
+ "ExampleStandardError",
1565
+ "test message",
1566
+ Appsignal::Utils::Data.generate(["line 1"])
1567
+ )
1081
1568
 
1082
- it "sends only the first causes as sample data" do
1083
- expect(transaction.ext).to receive(:set_error).with(
1084
- "ExampleStandardError",
1085
- "wrapper error 10",
1086
- Appsignal::Utils::Data.generate(["line 1"])
1569
+ expect(transaction.ext).to receive(:set_sample_data).with(
1570
+ "error_causes",
1571
+ Appsignal::Utils::Data.generate(
1572
+ [
1573
+ {
1574
+ :name => "RuntimeError",
1575
+ :message => "cause message"
1576
+ },
1577
+ {
1578
+ :name => "StandardError",
1579
+ :message => "cause message 2"
1580
+ }
1581
+ ]
1087
1582
  )
1583
+ )
1088
1584
 
1089
- expected_error_causes = Array.new(10) do |i|
1090
- {
1091
- :name => "ExampleStandardError",
1092
- :message => "wrapper error #{9 - i}"
1093
- }
1094
- end
1095
-
1096
- expected_error_causes.last[:is_root_cause] = false
1585
+ expect(Appsignal.internal_logger).to_not receive(:debug)
1097
1586
 
1098
- expect(transaction.ext).to receive(:set_sample_data).with(
1099
- "error_causes",
1100
- Appsignal::Utils::Data.generate(expected_error_causes)
1101
- )
1587
+ transaction.set_error(error)
1588
+ end
1589
+ end
1102
1590
 
1103
- expect(Appsignal.internal_logger).to receive(:debug).with(
1104
- "Appsignal::Transaction#set_error: Error has more " \
1105
- "than 10 error causes. Only the first 10 " \
1106
- "will be reported."
1107
- )
1591
+ context "when the error has too many causes" do
1592
+ let(:error) do
1593
+ e = ExampleStandardError.new("root cause error")
1108
1594
 
1109
- transaction.set_error(error)
1595
+ 11.times do |i|
1596
+ next_e = ExampleStandardError.new("wrapper error #{i}")
1597
+ allow(next_e).to receive(:cause).and_return(e)
1598
+ e = next_e
1110
1599
  end
1600
+
1601
+ allow(e).to receive(:backtrace).and_return(["line 1"])
1602
+ e
1111
1603
  end
1112
1604
 
1113
- context "when error message is nil" do
1114
- let(:error) do
1115
- e = ExampleStandardError.new
1116
- allow(e).to receive(:message).and_return(nil)
1117
- allow(e).to receive(:backtrace).and_return(["line 1"])
1118
- e
1119
- end
1605
+ it "sends only the first causes as sample data" do
1606
+ expect(transaction.ext).to receive(:set_error).with(
1607
+ "ExampleStandardError",
1608
+ "wrapper error 10",
1609
+ Appsignal::Utils::Data.generate(["line 1"])
1610
+ )
1120
1611
 
1121
- it "should not raise an error" do
1122
- transaction.set_error(error)
1612
+ expected_error_causes = Array.new(10) do |i|
1613
+ {
1614
+ :name => "ExampleStandardError",
1615
+ :message => "wrapper error #{9 - i}"
1616
+ }
1123
1617
  end
1124
1618
 
1125
- it "should set an error in the extension" do
1126
- expect(transaction.ext).to receive(:set_error).with(
1127
- "ExampleStandardError",
1128
- "",
1129
- Appsignal::Utils::Data.generate(["line 1"])
1130
- )
1619
+ expected_error_causes.last[:is_root_cause] = false
1131
1620
 
1132
- transaction.set_error(error)
1133
- end
1621
+ expect(transaction.ext).to receive(:set_sample_data).with(
1622
+ "error_causes",
1623
+ Appsignal::Utils::Data.generate(expected_error_causes)
1624
+ )
1625
+
1626
+ expect(Appsignal.internal_logger).to receive(:debug).with(
1627
+ "Appsignal::Transaction#set_error: Error has more " \
1628
+ "than 10 error causes. Only the first 10 " \
1629
+ "will be reported."
1630
+ )
1631
+
1632
+ transaction.set_error(error)
1134
1633
  end
1135
1634
  end
1136
1635
 
1137
- describe "#start_event" do
1138
- it "starts the event in the extension" do
1139
- expect(transaction.ext).to receive(:start_event).with(0).and_call_original
1636
+ context "when error message is nil" do
1637
+ let(:error) do
1638
+ e = ExampleStandardError.new
1639
+ allow(e).to receive(:message).and_return(nil)
1640
+ allow(e).to receive(:backtrace).and_return(["line 1"])
1641
+ e
1642
+ end
1140
1643
 
1141
- transaction.start_event
1644
+ it "should not raise an error" do
1645
+ transaction.set_error(error)
1142
1646
  end
1143
1647
 
1144
- context "when transaction is paused" do
1145
- it "does not start the event" do
1146
- transaction.pause!
1147
- expect(transaction.ext).to_not receive(:start_event)
1648
+ it "should set an error in the extension" do
1649
+ expect(transaction.ext).to receive(:set_error).with(
1650
+ "ExampleStandardError",
1651
+ "",
1652
+ Appsignal::Utils::Data.generate(["line 1"])
1653
+ )
1148
1654
 
1149
- transaction.start_event
1150
- end
1655
+ transaction.set_error(error)
1151
1656
  end
1152
1657
  end
1658
+ end
1153
1659
 
1154
- describe "#finish_event" do
1155
- let(:fake_gc_time) { 0 }
1660
+ describe "#start_event" do
1661
+ let(:transaction) { new_transaction }
1156
1662
 
1157
- it "should finish the event in the extension" do
1158
- expect(transaction.ext).to receive(:finish_event).with(
1159
- "name",
1160
- "title",
1161
- "body",
1162
- 1,
1163
- fake_gc_time
1164
- ).and_call_original
1663
+ it "starts the event in the extension" do
1664
+ expect(transaction.ext).to receive(:start_event).with(0).and_call_original
1165
1665
 
1166
- transaction.finish_event(
1167
- "name",
1168
- "title",
1169
- "body",
1170
- 1
1171
- )
1172
- end
1666
+ transaction.start_event
1667
+ end
1173
1668
 
1174
- it "should finish the event in the extension with nil arguments" do
1175
- expect(transaction.ext).to receive(:finish_event).with(
1176
- "name",
1177
- "",
1178
- "",
1179
- 0,
1180
- fake_gc_time
1181
- ).and_call_original
1669
+ context "when transaction is paused" do
1670
+ it "does not start the event" do
1671
+ transaction.pause!
1672
+ expect(transaction.ext).to_not receive(:start_event)
1182
1673
 
1183
- transaction.finish_event(
1184
- "name",
1185
- nil,
1186
- nil,
1187
- nil
1188
- )
1674
+ transaction.start_event
1189
1675
  end
1676
+ end
1677
+ end
1190
1678
 
1191
- context "when transaction is paused" do
1192
- it "does not finish the event" do
1193
- transaction.pause!
1194
- expect(transaction.ext).to_not receive(:finish_event)
1195
-
1196
- transaction.start_event
1197
- end
1198
- end
1679
+ describe "#finish_event" do
1680
+ let(:transaction) { new_transaction }
1681
+ let(:fake_gc_time) { 0 }
1682
+
1683
+ it "should finish the event in the extension" do
1684
+ expect(transaction.ext).to receive(:finish_event).with(
1685
+ "name",
1686
+ "title",
1687
+ "body",
1688
+ 1,
1689
+ fake_gc_time
1690
+ ).and_call_original
1691
+
1692
+ transaction.finish_event(
1693
+ "name",
1694
+ "title",
1695
+ "body",
1696
+ 1
1697
+ )
1199
1698
  end
1200
1699
 
1201
- describe "#record_event" do
1202
- let(:fake_gc_time) { 0 }
1700
+ it "should finish the event in the extension with nil arguments" do
1701
+ expect(transaction.ext).to receive(:finish_event).with(
1702
+ "name",
1703
+ "",
1704
+ "",
1705
+ 0,
1706
+ fake_gc_time
1707
+ ).and_call_original
1708
+
1709
+ transaction.finish_event(
1710
+ "name",
1711
+ nil,
1712
+ nil,
1713
+ nil
1714
+ )
1715
+ end
1203
1716
 
1204
- it "should record the event in the extension" do
1205
- expect(transaction.ext).to receive(:record_event).with(
1206
- "name",
1207
- "title",
1208
- "body",
1209
- 1,
1210
- 1000,
1211
- fake_gc_time
1212
- ).and_call_original
1717
+ context "when transaction is paused" do
1718
+ it "does not finish the event" do
1719
+ transaction.pause!
1720
+ expect(transaction.ext).to_not receive(:finish_event)
1213
1721
 
1214
- transaction.record_event(
1215
- "name",
1216
- "title",
1217
- "body",
1218
- 1000,
1219
- 1
1220
- )
1722
+ transaction.start_event
1221
1723
  end
1724
+ end
1725
+ end
1222
1726
 
1223
- it "should finish the event in the extension with nil arguments" do
1224
- expect(transaction.ext).to receive(:record_event).with(
1225
- "name",
1226
- "",
1227
- "",
1228
- 0,
1229
- 1000,
1230
- fake_gc_time
1231
- ).and_call_original
1727
+ describe "#record_event" do
1728
+ let(:transaction) { new_transaction }
1729
+ let(:fake_gc_time) { 0 }
1730
+
1731
+ it "should record the event in the extension" do
1732
+ expect(transaction.ext).to receive(:record_event).with(
1733
+ "name",
1734
+ "title",
1735
+ "body",
1736
+ 1,
1737
+ 1000,
1738
+ fake_gc_time
1739
+ ).and_call_original
1740
+
1741
+ transaction.record_event(
1742
+ "name",
1743
+ "title",
1744
+ "body",
1745
+ 1000,
1746
+ 1
1747
+ )
1748
+ end
1749
+
1750
+ it "should finish the event in the extension with nil arguments" do
1751
+ expect(transaction.ext).to receive(:record_event).with(
1752
+ "name",
1753
+ "",
1754
+ "",
1755
+ 0,
1756
+ 1000,
1757
+ fake_gc_time
1758
+ ).and_call_original
1759
+
1760
+ transaction.record_event(
1761
+ "name",
1762
+ nil,
1763
+ nil,
1764
+ 1000,
1765
+ nil
1766
+ )
1767
+ end
1768
+
1769
+ context "when transaction is paused" do
1770
+ it "does not record the event" do
1771
+ transaction.pause!
1772
+ expect(transaction.ext).to_not receive(:record_event)
1232
1773
 
1233
1774
  transaction.record_event(
1234
1775
  "name",
@@ -1238,172 +1779,192 @@ describe Appsignal::Transaction do
1238
1779
  nil
1239
1780
  )
1240
1781
  end
1782
+ end
1783
+ end
1241
1784
 
1242
- context "when transaction is paused" do
1243
- it "does not record the event" do
1244
- transaction.pause!
1245
- expect(transaction.ext).to_not receive(:record_event)
1246
-
1247
- transaction.record_event(
1248
- "name",
1249
- nil,
1250
- nil,
1251
- 1000,
1252
- nil
1253
- )
1254
- end
1255
- end
1785
+ describe "#instrument" do
1786
+ it_behaves_like "instrument helper" do
1787
+ let(:transaction) { new_transaction }
1788
+ let(:instrumenter) { transaction }
1256
1789
  end
1790
+ end
1257
1791
 
1258
- describe "#instrument" do
1259
- it_behaves_like "instrument helper" do
1260
- let(:instrumenter) { transaction }
1261
- end
1792
+ context "GenericRequest" do
1793
+ let(:env) { {} }
1794
+ subject { Appsignal::Transaction::GenericRequest.new(env) }
1795
+
1796
+ it "prints a deprecation warning on use" do
1797
+ err_stream = std_stream
1798
+ capture_std_streams(std_stream, err_stream) { subject }
1799
+
1800
+ expect(err_stream.read).to include(
1801
+ "appsignal WARNING: The use of Appsignal::Transaction::GenericRequest is deprecated."
1802
+ )
1262
1803
  end
1263
1804
 
1264
- context "generic request" do
1265
- let(:env) { {} }
1266
- subject { Appsignal::Transaction::GenericRequest.new(env) }
1805
+ it "logs a deprecation warning on use" do
1806
+ logs = capture_logs { silence { subject } }
1267
1807
 
1268
- it "initializes with an empty env" do
1269
- expect(subject.env).to be_empty
1270
- end
1808
+ expect(logs).to contains_log(
1809
+ :warn,
1810
+ "The use of Appsignal::Transaction::GenericRequest is deprecated."
1811
+ )
1812
+ end
1271
1813
 
1272
- context "when given an env" do
1273
- let(:env) do
1274
- {
1275
- :params => { :id => 1 },
1276
- :queue_start => 10
1277
- }
1278
- end
1814
+ it "initializes with an empty env" do
1815
+ expect(subject.env).to be_empty
1816
+ end
1279
1817
 
1280
- it "sets the given env" do
1281
- expect(subject.env).to eq env
1282
- end
1818
+ context "when given an env" do
1819
+ let(:env) do
1820
+ {
1821
+ :params => { :id => 1 },
1822
+ :queue_start => 10
1823
+ }
1824
+ end
1283
1825
 
1284
- it "sets the params present in the env" do
1285
- expect(subject.params).to eq(:id => 1)
1286
- end
1826
+ it "sets the given env" do
1827
+ expect(subject.env).to eq env
1287
1828
  end
1829
+
1830
+ it "sets the params present in the env" do
1831
+ expect(subject.params).to eq(:id => 1)
1832
+ end
1833
+ end
1834
+ end
1835
+
1836
+ # private
1837
+
1838
+ describe "#background_queue_start" do
1839
+ let(:transaction) { legacy_new_transaction(:request => request) }
1840
+ let(:request) { rack_request(env) }
1841
+ let(:env) { {} }
1842
+ subject { transaction.send(:background_queue_start) }
1843
+
1844
+ context "when request is nil" do
1845
+ let(:request) { nil }
1846
+
1847
+ it { is_expected.to eq nil }
1848
+ end
1849
+
1850
+ context "when env is nil" do
1851
+ before { expect(request).to receive(:env).and_return(nil) }
1852
+
1853
+ it { is_expected.to eq nil }
1854
+ end
1855
+
1856
+ context "when queue start is nil" do
1857
+ it { is_expected.to eq nil }
1288
1858
  end
1289
1859
 
1290
- # private
1860
+ context "when queue start is set" do
1861
+ before do
1862
+ env[:queue_start] = fixed_time
1863
+ end
1864
+
1865
+ it { is_expected.to eq 1_389_783_600_000 }
1866
+ end
1867
+ end
1291
1868
 
1292
- describe "#background_queue_start" do
1293
- subject { transaction.send(:background_queue_start) }
1869
+ describe "#http_queue_start" do
1870
+ let(:transaction) { legacy_new_transaction(:request => request) }
1871
+ let(:request) { rack_request(env) }
1872
+ let(:env) { {} }
1873
+ let(:slightly_earlier_time) { fixed_time - 0.4 }
1874
+ let(:slightly_earlier_time_value) { (slightly_earlier_time * factor).to_i }
1875
+ subject { transaction.send(:http_queue_start) }
1294
1876
 
1877
+ shared_examples "http queue start" do
1295
1878
  context "when request is nil" do
1296
1879
  let(:request) { nil }
1297
1880
 
1298
- it { is_expected.to eq nil }
1881
+ it { is_expected.to be_nil }
1299
1882
  end
1300
1883
 
1301
1884
  context "when env is nil" do
1302
- before { expect(transaction.request).to receive(:env).and_return(nil) }
1303
-
1304
- it { is_expected.to eq nil }
1305
- end
1885
+ before { expect(request).to receive(:env).and_return(nil) }
1306
1886
 
1307
- context "when queue start is nil" do
1308
- it { is_expected.to eq nil }
1887
+ it { is_expected.to be_nil }
1309
1888
  end
1310
1889
 
1311
- context "when queue start is set" do
1312
- let(:env) { background_env_with_data }
1890
+ context "with no relevant header set" do
1891
+ let(:env) { {} }
1313
1892
 
1314
- it { is_expected.to eq 1_389_783_600_000 }
1893
+ it { is_expected.to be_nil }
1315
1894
  end
1316
- end
1317
1895
 
1318
- describe "#http_queue_start" do
1319
- let(:slightly_earlier_time) { fixed_time - 0.4 }
1320
- let(:slightly_earlier_time_value) { (slightly_earlier_time * factor).to_i }
1321
- subject { transaction.send(:http_queue_start) }
1896
+ context "with the HTTP_X_REQUEST_START header set" do
1897
+ let(:env) { { "HTTP_X_REQUEST_START" => "t=#{slightly_earlier_time_value}" } }
1322
1898
 
1323
- shared_examples "http queue start" do
1324
- context "when request is nil" do
1325
- let(:request) { nil }
1899
+ it { is_expected.to eq 1_389_783_599_600 }
1900
+
1901
+ context "with unparsable content" do
1902
+ let(:env) { { "HTTP_X_REQUEST_START" => "something" } }
1326
1903
 
1327
1904
  it { is_expected.to be_nil }
1328
1905
  end
1329
1906
 
1330
- context "when env is nil" do
1331
- before { expect(transaction.request).to receive(:env).and_return(nil) }
1907
+ context "with unparsable content at the end" do
1908
+ let(:env) { { "HTTP_X_REQUEST_START" => "t=#{slightly_earlier_time_value}aaaa" } }
1332
1909
 
1333
- it { is_expected.to be_nil }
1910
+ it { is_expected.to eq 1_389_783_599_600 }
1334
1911
  end
1335
1912
 
1336
- context "with no relevant header set" do
1337
- let(:env) { {} }
1913
+ context "with a really low number" do
1914
+ let(:env) { { "HTTP_X_REQUEST_START" => "t=100" } }
1338
1915
 
1339
1916
  it { is_expected.to be_nil }
1340
1917
  end
1341
1918
 
1342
- context "with the HTTP_X_REQUEST_START header set" do
1343
- let(:env) { { "HTTP_X_REQUEST_START" => "t=#{slightly_earlier_time_value}" } }
1919
+ context "with the alternate HTTP_X_QUEUE_START header set" do
1920
+ let(:env) { { "HTTP_X_QUEUE_START" => "t=#{slightly_earlier_time_value}" } }
1344
1921
 
1345
1922
  it { is_expected.to eq 1_389_783_599_600 }
1346
-
1347
- context "with unparsable content" do
1348
- let(:env) { { "HTTP_X_REQUEST_START" => "something" } }
1349
-
1350
- it { is_expected.to be_nil }
1351
- end
1352
-
1353
- context "with unparsable content at the end" do
1354
- let(:env) { { "HTTP_X_REQUEST_START" => "t=#{slightly_earlier_time_value}aaaa" } }
1355
-
1356
- it { is_expected.to eq 1_389_783_599_600 }
1357
- end
1358
-
1359
- context "with a really low number" do
1360
- let(:env) { { "HTTP_X_REQUEST_START" => "t=100" } }
1361
-
1362
- it { is_expected.to be_nil }
1363
- end
1364
-
1365
- context "with the alternate HTTP_X_QUEUE_START header set" do
1366
- let(:env) { { "HTTP_X_QUEUE_START" => "t=#{slightly_earlier_time_value}" } }
1367
-
1368
- it { is_expected.to eq 1_389_783_599_600 }
1369
- end
1370
1923
  end
1371
1924
  end
1925
+ end
1372
1926
 
1373
- context "time in milliseconds" do
1374
- let(:factor) { 1_000 }
1927
+ context "time in milliseconds" do
1928
+ let(:factor) { 1_000 }
1375
1929
 
1376
- it_should_behave_like "http queue start"
1377
- end
1930
+ it_should_behave_like "http queue start"
1931
+ end
1378
1932
 
1379
- context "time in microseconds" do
1380
- let(:factor) { 1_000_000 }
1933
+ context "time in microseconds" do
1934
+ let(:factor) { 1_000_000 }
1381
1935
 
1382
- it_should_behave_like "http queue start"
1383
- end
1936
+ it_should_behave_like "http queue start"
1384
1937
  end
1938
+ end
1385
1939
 
1386
- describe "#sanitized_params" do
1387
- subject { transaction.send(:sanitized_params) }
1940
+ describe "#sanitized_params" do
1941
+ let(:transaction) { new_transaction }
1942
+ subject { transaction.send(:sanitized_params) }
1388
1943
 
1389
- context "with custom params" do
1390
- before do
1391
- transaction.set_params(:foo => "bar", :baz => :bat)
1392
- end
1944
+ context "with params" do
1945
+ before do
1946
+ transaction.set_params(:foo => "bar", :baz => :bat)
1947
+ end
1393
1948
 
1394
- it "returns custom params" do
1395
- is_expected.to eq(:foo => "bar", :baz => :bat)
1396
- end
1949
+ it "returns params" do
1950
+ is_expected.to eq(:foo => "bar", :baz => :bat)
1951
+ end
1397
1952
 
1398
- context "with AppSignal filtering" do
1399
- before { Appsignal.config.config_hash[:filter_parameters] = %w[foo] }
1400
- after { Appsignal.config.config_hash[:filter_parameters] = [] }
1953
+ context "with AppSignal filtering" do
1954
+ before { Appsignal.config.config_hash[:filter_parameters] = %w[foo] }
1955
+ after { Appsignal.config.config_hash[:filter_parameters] = [] }
1401
1956
 
1402
- it "returns sanitized custom params" do
1403
- expect(subject).to eq(:foo => "[FILTERED]", :baz => :bat)
1404
- end
1957
+ it "returns sanitized custom params" do
1958
+ expect(subject).to eq(:foo => "[FILTERED]", :baz => :bat)
1405
1959
  end
1406
1960
  end
1961
+ end
1962
+
1963
+ context "params from request" do
1964
+ let(:transaction) { legacy_new_transaction(:request => request, :options => options) }
1965
+ let(:options) { {} }
1966
+ let(:request) { rack_request(env) }
1967
+ let(:env) { {} }
1407
1968
 
1408
1969
  context "without request params" do
1409
1970
  before { allow(transaction.request).to receive(:params).and_return(nil) }
@@ -1412,7 +1973,7 @@ describe Appsignal::Transaction do
1412
1973
  end
1413
1974
 
1414
1975
  context "when request params crashes" do
1415
- before { allow(transaction.request).to receive(:params).and_raise(NoMethodError) }
1976
+ before { expect(request).to receive(:params).and_raise(NoMethodError) }
1416
1977
 
1417
1978
  it { is_expected.to be_nil }
1418
1979
  end
@@ -1431,11 +1992,7 @@ describe Appsignal::Transaction do
1431
1992
  end
1432
1993
 
1433
1994
  context "with an array" do
1434
- let(:request) do
1435
- Appsignal::Transaction::GenericRequest.new(
1436
- background_env_with_data(:params => %w[arg1 arg2])
1437
- )
1438
- end
1995
+ let(:request) { legacy_request(:params => %w[arg1 arg2]) }
1439
1996
 
1440
1997
  it { is_expected.to eq %w[arg1 arg2] }
1441
1998
 
@@ -1449,11 +2006,7 @@ describe Appsignal::Transaction do
1449
2006
 
1450
2007
  context "with env" do
1451
2008
  context "with sanitization" do
1452
- let(:request) do
1453
- Appsignal::Transaction::GenericRequest.new(
1454
- http_request_env_with_data(:params => { :foo => :bar })
1455
- )
1456
- end
2009
+ let(:request) { legacy_request(:params => { :foo => :bar }) }
1457
2010
 
1458
2011
  it "should call the params sanitizer" do
1459
2012
  expect(subject).to eq(:foo => :bar)
@@ -1461,11 +2014,7 @@ describe Appsignal::Transaction do
1461
2014
  end
1462
2015
 
1463
2016
  context "with AppSignal filtering" do
1464
- let(:request) do
1465
- Appsignal::Transaction::GenericRequest.new(
1466
- http_request_env_with_data(:params => { :foo => :bar, :baz => :bat })
1467
- )
1468
- end
2017
+ let(:request) { legacy_request(:params => { :foo => :bar, :baz => :bat }) }
1469
2018
  before { Appsignal.config.config_hash[:filter_parameters] = %w[foo] }
1470
2019
  after { Appsignal.config.config_hash[:filter_parameters] = [] }
1471
2020
 
@@ -1475,93 +2024,139 @@ describe Appsignal::Transaction do
1475
2024
  end
1476
2025
  end
1477
2026
  end
2027
+ end
1478
2028
 
1479
- describe "#sanitized_environment" do
1480
- let(:allowlisted_keys) { Appsignal.config[:request_headers] }
1481
- subject { transaction.send(:sanitized_environment) }
2029
+ describe "#sanitized_environment" do
2030
+ let(:transaction) { legacy_new_transaction(:request => request) }
2031
+ let(:request) { rack_request(env) }
2032
+ let(:env) { {} }
2033
+ let(:allowlisted_keys) { Appsignal.config[:request_headers] }
2034
+ subject { transaction.send(:sanitized_environment) }
1482
2035
 
1483
- context "when request is nil" do
1484
- let(:request) { nil }
2036
+ context "when request is nil" do
2037
+ let(:request) { nil }
1485
2038
 
1486
- it { is_expected.to be_nil }
1487
- end
2039
+ it { is_expected.to be_nil }
2040
+ end
1488
2041
 
1489
- context "when env is nil" do
1490
- before { expect(transaction.request).to receive(:env).and_return(nil) }
2042
+ context "when env is nil" do
2043
+ before { expect(request).to receive(:env).and_return(nil) }
1491
2044
 
1492
- it { is_expected.to be_nil }
2045
+ it { is_expected.to be_nil }
2046
+ end
2047
+
2048
+ context "when env is present" do
2049
+ let(:env) do
2050
+ {}.tap do |hash|
2051
+ allowlisted_keys.each { |o| hash[o] = 1 } # use all allowlisted keys
2052
+ hash[allowlisted_keys] = nil # don't add if nil
2053
+ hash[:not_allowlisted] = "I will be sanitized"
2054
+ end
1493
2055
  end
1494
2056
 
1495
- context "when env is present" do
1496
- let(:env) do
1497
- {}.tap do |hash|
1498
- allowlisted_keys.each { |o| hash[o] = 1 } # use all allowlisted keys
1499
- hash[allowlisted_keys] = nil # don't add if nil
1500
- hash[:not_allowlisted] = "I will be sanitized"
1501
- end
2057
+ it "only sets allowlisted keys" do
2058
+ expect(subject.keys).to match_array(allowlisted_keys)
2059
+ end
2060
+
2061
+ context "with configured request_headers" do
2062
+ before do
2063
+ Appsignal.config.config_hash[:request_headers] = %w[CONTENT_LENGTH]
1502
2064
  end
1503
2065
 
1504
2066
  it "only sets allowlisted keys" do
1505
- expect(subject.keys).to match_array(allowlisted_keys)
2067
+ expect(subject.keys).to match_array(%w[CONTENT_LENGTH])
1506
2068
  end
2069
+ end
2070
+ end
2071
+ end
1507
2072
 
1508
- context "with configured request_headers" do
1509
- before do
1510
- Appsignal.config.config_hash[:request_headers] = %w[CONTENT_LENGTH]
1511
- end
2073
+ describe "#sanitized_session_data" do
2074
+ let(:transaction) { legacy_new_transaction(:request => request) }
2075
+ let(:request) { rack_request(env) }
2076
+ let(:env) { {} }
2077
+ subject { transaction.send(:sanitized_session_data) }
1512
2078
 
1513
- it "only sets allowlisted keys" do
1514
- expect(subject.keys).to match_array(%w[CONTENT_LENGTH])
1515
- end
1516
- end
1517
- end
2079
+ context "when request is nil" do
2080
+ let(:request) { nil }
2081
+
2082
+ it { is_expected.to be_nil }
1518
2083
  end
1519
2084
 
1520
- describe "#sanitized_session_data" do
1521
- subject { transaction.send(:sanitized_session_data) }
2085
+ context "when session is nil" do
2086
+ before { expect(transaction.request).to receive(:session).and_return(nil) }
1522
2087
 
1523
- context "when request is nil" do
1524
- let(:request) { nil }
2088
+ it { is_expected.to be_nil }
2089
+ end
1525
2090
 
1526
- it { is_expected.to be_nil }
1527
- end
2091
+ context "when session is empty" do
2092
+ before { expect(transaction.request).to receive(:session).and_return({}) }
1528
2093
 
1529
- context "when session is nil" do
1530
- before { expect(transaction.request).to receive(:session).and_return(nil) }
2094
+ it { is_expected.to eq({}) }
2095
+ end
1531
2096
 
1532
- it { is_expected.to be_nil }
1533
- end
2097
+ context "when request class does not have a session method" do
2098
+ let(:request) { Appsignal::Transaction::GenericRequest.new({}) }
2099
+
2100
+ it { is_expected.to be_nil }
2101
+ end
1534
2102
 
1535
- context "when session is empty" do
1536
- before { expect(transaction.request).to receive(:session).and_return({}) }
2103
+ context "with a session" do
2104
+ let(:session_data_filter) { [] }
2105
+ before { Appsignal.config[:filter_session_data] = session_data_filter }
2106
+ after { Appsignal.config[:filter_session_data] = [] }
1537
2107
 
1538
- it { is_expected.to eq({}) }
1539
- end
2108
+ context "with generic session object" do
2109
+ before do
2110
+ expect(transaction).to respond_to(:request)
2111
+ allow(transaction).to receive_message_chain(
2112
+ :request,
2113
+ :session => { :foo => :bar, :abc => :def }
2114
+ )
2115
+ allow(transaction).to receive_message_chain(:request, :fullpath => :bar)
2116
+ end
2117
+
2118
+ context "without session filtering" do
2119
+ it "keeps the session data intact" do
2120
+ expect(subject).to eq(:foo => :bar, :abc => :def)
2121
+ end
2122
+ end
1540
2123
 
1541
- context "when request class does not have a session method" do
1542
- let(:request) { Appsignal::Transaction::GenericRequest.new({}) }
2124
+ context "with session filtering" do
2125
+ let(:session_data_filter) { %w[foo] }
1543
2126
 
1544
- it { is_expected.to be_nil }
2127
+ it "filters the session data" do
2128
+ expect(subject).to eq(:foo => "[FILTERED]", :abc => :def)
2129
+ end
2130
+ end
1545
2131
  end
1546
2132
 
1547
- context "with a session" do
1548
- let(:session_data_filter) { [] }
1549
- before { Appsignal.config[:filter_session_data] = session_data_filter }
1550
- after { Appsignal.config[:filter_session_data] = [] }
2133
+ if defined? ActionDispatch::Request::Session
2134
+ context "with ActionDispatch::Request::Session" do
2135
+ let(:action_dispatch_session) do
2136
+ store = Class.new do
2137
+ def load_session(_env)
2138
+ [1, { :foo => :bar, :abc => :def }]
2139
+ end
1551
2140
 
1552
- context "with generic session object" do
2141
+ def session_exists?(_env)
2142
+ true
2143
+ end
2144
+ end.new
2145
+ ActionDispatch::Request::Session.create(store,
2146
+ ActionDispatch::Request.new("rack.input" => StringIO.new), {})
2147
+ end
1553
2148
  before do
1554
2149
  expect(transaction).to respond_to(:request)
1555
2150
  allow(transaction).to receive_message_chain(
1556
2151
  :request,
1557
- :session => { :foo => :bar, :abc => :def }
2152
+ :session => action_dispatch_session
1558
2153
  )
1559
2154
  allow(transaction).to receive_message_chain(:request, :fullpath => :bar)
1560
2155
  end
1561
2156
 
1562
2157
  context "without session filtering" do
1563
2158
  it "keeps the session data intact" do
1564
- expect(subject).to eq(:foo => :bar, :abc => :def)
2159
+ expect(subject).to eq("foo" => :bar, "abc" => :def)
1565
2160
  end
1566
2161
  end
1567
2162
 
@@ -1569,120 +2164,87 @@ describe Appsignal::Transaction do
1569
2164
  let(:session_data_filter) { %w[foo] }
1570
2165
 
1571
2166
  it "filters the session data" do
1572
- expect(subject).to eq(:foo => "[FILTERED]", :abc => :def)
1573
- end
1574
- end
1575
- end
1576
-
1577
- if defined? ActionDispatch::Request::Session
1578
- context "with ActionDispatch::Request::Session" do
1579
- let(:action_dispatch_session) do
1580
- store = Class.new do
1581
- def load_session(_env)
1582
- [1, { :foo => :bar, :abc => :def }]
1583
- end
1584
-
1585
- def session_exists?(_env)
1586
- true
1587
- end
1588
- end.new
1589
- ActionDispatch::Request::Session.create(store,
1590
- ActionDispatch::Request.new("rack.input" => StringIO.new), {})
1591
- end
1592
- before do
1593
- expect(transaction).to respond_to(:request)
1594
- allow(transaction).to receive_message_chain(
1595
- :request,
1596
- :session => action_dispatch_session
1597
- )
1598
- allow(transaction).to receive_message_chain(:request, :fullpath => :bar)
1599
- end
1600
-
1601
- context "without session filtering" do
1602
- it "keeps the session data intact" do
1603
- expect(subject).to eq("foo" => :bar, "abc" => :def)
1604
- end
1605
- end
1606
-
1607
- context "with session filtering" do
1608
- let(:session_data_filter) { %w[foo] }
1609
-
1610
- it "filters the session data" do
1611
- expect(subject).to eq("foo" => "[FILTERED]", "abc" => :def)
1612
- end
2167
+ expect(subject).to eq("foo" => "[FILTERED]", "abc" => :def)
1613
2168
  end
1614
2169
  end
1615
2170
  end
2171
+ end
1616
2172
 
1617
- context "when not sending session data" do
1618
- before { Appsignal.config[:send_session_data] = false }
2173
+ context "when not sending session data" do
2174
+ before { Appsignal.config[:send_session_data] = false }
1619
2175
 
1620
- it "does not set any session data on the transaction" do
1621
- expect(subject).to be_nil
1622
- end
2176
+ it "does not set any session data on the transaction" do
2177
+ expect(subject).to be_nil
1623
2178
  end
1624
2179
  end
1625
2180
  end
2181
+ end
1626
2182
 
1627
- describe "#sanitized_metadata" do
1628
- subject { transaction.send(:sanitized_metadata) }
2183
+ describe "#sanitized_metadata" do
2184
+ let(:transaction) { legacy_new_transaction(:request => request) }
2185
+ let(:request) { rack_request(env) }
2186
+ let(:env) { {} }
2187
+ subject { transaction.send(:sanitized_metadata) }
1629
2188
 
1630
- context "when request is nil" do
1631
- let(:request) { nil }
2189
+ context "when request is nil" do
2190
+ let(:request) { nil }
1632
2191
 
1633
- it { is_expected.to be_nil }
1634
- end
2192
+ it { is_expected.to be_nil }
2193
+ end
1635
2194
 
1636
- context "when env is nil" do
1637
- before { expect(transaction.request).to receive(:env).and_return(nil) }
2195
+ context "when env is nil" do
2196
+ before { expect(request).to receive(:env).and_return(nil) }
1638
2197
 
1639
- it { is_expected.to be_nil }
1640
- end
2198
+ it { is_expected.to be_nil }
2199
+ end
1641
2200
 
1642
- context "when env is present" do
1643
- let(:env) { { "key" => "value" } }
2201
+ context "when env is present" do
2202
+ let(:env) { { :metadata => { "key" => "value" } } }
1644
2203
 
1645
- it { is_expected.to eq("key" => "value") }
2204
+ it do
2205
+ is_expected.to eq("key" => "value")
2206
+ end
1646
2207
 
1647
- context "with filter_metadata option set" do
1648
- before { Appsignal.config[:filter_metadata] = ["key"] }
1649
- after { Appsignal.config[:filter_metadata] = [] }
2208
+ context "with filter_metadata option set" do
2209
+ before { Appsignal.config[:filter_metadata] = ["key"] }
2210
+ after { Appsignal.config[:filter_metadata] = [] }
1650
2211
 
1651
- it "filters out keys listed in the filter_metadata option" do
1652
- expect(subject.keys).to_not include("key")
1653
- end
2212
+ it "filters out keys listed in the filter_metadata option" do
2213
+ expect(subject.keys).to_not include("key")
1654
2214
  end
1655
2215
  end
1656
2216
  end
2217
+ end
1657
2218
 
1658
- describe "#cleaned_backtrace" do
1659
- subject { transaction.send(:cleaned_backtrace, ["line 1", "line 2"]) }
2219
+ describe "#cleaned_backtrace" do
2220
+ let(:transaction) { new_transaction }
2221
+ subject { transaction.send(:cleaned_backtrace, ["line 1", "line 2"]) }
1660
2222
 
1661
- it "returns the backtrace" do
1662
- expect(subject).to eq ["line 1", "line 2"]
1663
- end
2223
+ it "returns the backtrace" do
2224
+ expect(subject).to eq ["line 1", "line 2"]
2225
+ end
1664
2226
 
1665
- context "with Rails module but without backtrace_cleaner method" do
1666
- it "returns the backtrace uncleaned" do
1667
- stub_const("Rails", Module.new)
1668
- expect(subject).to eq ["line 1", "line 2"]
1669
- end
2227
+ context "with Rails module but without backtrace_cleaner method" do
2228
+ it "returns the backtrace uncleaned" do
2229
+ stub_const("Rails", Module.new)
2230
+ expect(subject).to eq ["line 1", "line 2"]
1670
2231
  end
2232
+ end
1671
2233
 
1672
- if rails_present?
1673
- context "with rails" do
1674
- it "cleans the backtrace with the Rails backtrace cleaner" do
1675
- ::Rails.backtrace_cleaner.add_filter do |line|
1676
- line.tr("2", "?")
1677
- end
1678
- expect(subject).to eq ["line 1", "line ?"]
2234
+ if rails_present?
2235
+ context "with rails" do
2236
+ it "cleans the backtrace with the Rails backtrace cleaner" do
2237
+ ::Rails.backtrace_cleaner.add_filter do |line|
2238
+ line.tr("2", "?")
1679
2239
  end
2240
+ expect(subject).to eq ["line 1", "line ?"]
1680
2241
  end
1681
2242
  end
1682
2243
  end
1683
2244
  end
1684
2245
 
1685
2246
  describe "#cleaned_error_message" do
2247
+ let(:transaction) { new_transaction }
1686
2248
  let(:error) { StandardError.new("Error message") }
1687
2249
  subject { transaction.send(:cleaned_error_message, error) }
1688
2250
 
@@ -1729,6 +2291,7 @@ describe Appsignal::Transaction do
1729
2291
  end
1730
2292
 
1731
2293
  describe ".to_hash / .to_h" do
2294
+ let(:transaction) { new_transaction }
1732
2295
  subject { transaction.to_hash }
1733
2296
 
1734
2297
  context "when extension returns serialized JSON" do
@@ -1737,9 +2300,9 @@ describe Appsignal::Transaction do
1737
2300
  "action" => nil,
1738
2301
  "error" => nil,
1739
2302
  "events" => [],
1740
- "id" => transaction_id,
2303
+ "id" => kind_of(String),
1741
2304
  "metadata" => {},
1742
- "namespace" => namespace,
2305
+ "namespace" => default_namespace,
1743
2306
  "sample_data" => {}
1744
2307
  )
1745
2308
  end
@@ -1772,7 +2335,7 @@ describe Appsignal::Transaction do
1772
2335
  subject.set_http_or_background_queue_start
1773
2336
  subject.set_metadata("key", "value")
1774
2337
  subject.set_sample_data("key", "data")
1775
- subject.sample_data
2338
+ subject._sample
1776
2339
  subject.set_error("a")
1777
2340
  end
1778
2341
  end