appsignal 3.10.0-java → 3.11.0-java

Sign up to get free protection for your applications and to get access to all the features.
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