appsignal 3.10.0-java → 3.11.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +88 -0
- data/Gemfile +1 -0
- data/benchmark.rake +99 -42
- data/lib/appsignal/cli/demo.rb +0 -1
- data/lib/appsignal/config.rb +54 -98
- data/lib/appsignal/demo.rb +15 -20
- data/lib/appsignal/event_formatter/rom/sql_formatter.rb +1 -0
- data/lib/appsignal/event_formatter.rb +3 -2
- data/lib/appsignal/helpers/instrumentation.rb +331 -19
- data/lib/appsignal/hooks/action_cable.rb +21 -16
- data/lib/appsignal/hooks/active_job.rb +14 -8
- data/lib/appsignal/hooks/delayed_job.rb +1 -1
- data/lib/appsignal/hooks/shoryuken.rb +3 -63
- data/lib/appsignal/integrations/action_cable.rb +5 -7
- data/lib/appsignal/integrations/active_support_notifications.rb +1 -0
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +36 -35
- data/lib/appsignal/integrations/data_mapper.rb +1 -0
- data/lib/appsignal/integrations/delayed_job_plugin.rb +27 -33
- data/lib/appsignal/integrations/dry_monitor.rb +1 -0
- data/lib/appsignal/integrations/excon.rb +1 -0
- data/lib/appsignal/integrations/http.rb +1 -0
- data/lib/appsignal/integrations/net_http.rb +1 -0
- data/lib/appsignal/integrations/object.rb +6 -0
- data/lib/appsignal/integrations/que.rb +13 -20
- data/lib/appsignal/integrations/railtie.rb +1 -1
- data/lib/appsignal/integrations/rake.rb +1 -5
- data/lib/appsignal/integrations/redis.rb +1 -0
- data/lib/appsignal/integrations/redis_client.rb +1 -0
- data/lib/appsignal/integrations/resque.rb +2 -5
- data/lib/appsignal/integrations/shoryuken.rb +75 -0
- data/lib/appsignal/integrations/sidekiq.rb +7 -15
- data/lib/appsignal/integrations/unicorn.rb +1 -0
- data/lib/appsignal/integrations/webmachine.rb +2 -5
- data/lib/appsignal/logger.rb +7 -3
- data/lib/appsignal/probes/helpers.rb +1 -0
- data/lib/appsignal/probes/mri.rb +1 -0
- data/lib/appsignal/probes/sidekiq.rb +1 -0
- data/lib/appsignal/probes.rb +3 -0
- data/lib/appsignal/rack/abstract_middleware.rb +18 -12
- data/lib/appsignal/rack/event_handler.rb +39 -8
- data/lib/appsignal/rack/generic_instrumentation.rb +1 -0
- data/lib/appsignal/rack/grape_middleware.rb +2 -1
- data/lib/appsignal/rack/streaming_listener.rb +1 -0
- data/lib/appsignal/rack.rb +29 -0
- data/lib/appsignal/span.rb +1 -0
- data/lib/appsignal/transaction.rb +308 -101
- data/lib/appsignal/utils/data.rb +0 -1
- data/lib/appsignal/utils/hash_sanitizer.rb +0 -1
- data/lib/appsignal/utils/integration_logger.rb +0 -13
- data/lib/appsignal/utils/integration_memory_logger.rb +0 -13
- data/lib/appsignal/utils/json.rb +0 -1
- data/lib/appsignal/utils/query_params_sanitizer.rb +0 -1
- data/lib/appsignal/utils/stdout_and_logger_message.rb +0 -1
- data/lib/appsignal/utils.rb +6 -0
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +6 -5
- data/spec/lib/appsignal/capistrano2_spec.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +138 -43
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +43 -74
- data/spec/lib/appsignal/hooks/activejob_spec.rb +9 -0
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +2 -443
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +0 -171
- data/spec/lib/appsignal/integrations/delayed_job_plugin_spec.rb +459 -0
- data/spec/lib/appsignal/integrations/que_spec.rb +3 -4
- data/spec/lib/appsignal/integrations/shoryuken_spec.rb +167 -0
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +4 -4
- data/spec/lib/appsignal/integrations/webmachine_spec.rb +13 -1
- data/spec/lib/appsignal/rack/abstract_middleware_spec.rb +48 -3
- data/spec/lib/appsignal/rack/event_handler_spec.rb +81 -10
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +4 -2
- data/spec/lib/appsignal/rack_spec.rb +63 -0
- data/spec/lib/appsignal/transaction_spec.rb +1634 -1071
- data/spec/lib/appsignal/utils/integration_logger_spec.rb +12 -16
- data/spec/lib/appsignal/utils/integration_memory_logger_spec.rb +0 -10
- data/spec/lib/appsignal_spec.rb +323 -10
- data/spec/support/helpers/transaction_helpers.rb +44 -20
- data/spec/support/matchers/transaction.rb +15 -1
- data/spec/support/testing.rb +1 -1
- metadata +6 -2
|
@@ -1,132 +1,211 @@
|
|
|
1
1
|
describe Appsignal::Transaction do
|
|
2
|
-
|
|
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
|
-
|
|
7
|
+
start_agent
|
|
8
|
+
keep_transactions do
|
|
20
9
|
example.run
|
|
21
10
|
end
|
|
22
11
|
end
|
|
23
12
|
|
|
24
|
-
describe "
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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 "
|
|
48
|
-
|
|
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
|
-
|
|
53
|
-
|
|
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
|
-
|
|
56
|
-
expect
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
117
|
-
|
|
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
|
-
|
|
123
|
-
|
|
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
|
|
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
|
-
|
|
145
|
-
|
|
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(
|
|
190
|
-
"Skipping transaction '
|
|
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 "
|
|
246
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
end
|
|
343
|
+
it "loads the AppSignal extension" do
|
|
344
|
+
expect(transaction.ext).to_not be_nil
|
|
345
|
+
end
|
|
255
346
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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 "
|
|
269
|
-
expect(transaction.
|
|
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
|
-
|
|
273
|
-
|
|
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
|
|
277
|
-
expect(transaction
|
|
369
|
+
it "sets the transaction id" do
|
|
370
|
+
expect(transaction).to have_id("mock_transaction_id")
|
|
278
371
|
end
|
|
372
|
+
end
|
|
279
373
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
374
|
+
it "sets the namespace to http_request" do
|
|
375
|
+
expect(transaction.namespace).to eq "http_request"
|
|
376
|
+
end
|
|
283
377
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
378
|
+
it "sets the request" do
|
|
379
|
+
expect(transaction.request).to be_a(Appsignal::Transaction::InternalGenericRequest)
|
|
380
|
+
end
|
|
287
381
|
|
|
288
|
-
|
|
289
|
-
|
|
382
|
+
it "sets the request not to paused" do
|
|
383
|
+
expect(transaction.paused?).to be_falsy
|
|
384
|
+
end
|
|
290
385
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
386
|
+
it "sets no tags by default" do
|
|
387
|
+
expect(transaction.tags).to be_empty
|
|
388
|
+
end
|
|
294
389
|
|
|
295
|
-
|
|
296
|
-
|
|
390
|
+
describe "#options" do
|
|
391
|
+
let(:options) { transaction.options }
|
|
297
392
|
|
|
298
|
-
|
|
299
|
-
|
|
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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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
|
-
|
|
311
|
-
|
|
312
|
-
transaction_store["transaction"] = "value"
|
|
409
|
+
describe "#store" do
|
|
410
|
+
let(:transaction) { new_transaction }
|
|
313
411
|
|
|
314
|
-
|
|
315
|
-
|
|
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
|
-
|
|
319
|
-
|
|
416
|
+
it "stores changes to the store" do
|
|
417
|
+
transaction_store = transaction.store("test")
|
|
418
|
+
transaction_store["transaction"] = "value"
|
|
320
419
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
end
|
|
420
|
+
expect(transaction.store("test")).to eql("transaction" => "value")
|
|
421
|
+
end
|
|
422
|
+
end
|
|
325
423
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
424
|
+
describe "#params" do
|
|
425
|
+
let(:transaction) { new_transaction }
|
|
426
|
+
let(:params) { transaction.params }
|
|
329
427
|
|
|
330
|
-
|
|
331
|
-
|
|
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
|
-
|
|
335
|
-
|
|
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 "
|
|
342
|
-
it "
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
-
|
|
353
|
-
|
|
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
|
-
|
|
356
|
-
|
|
357
|
-
|
|
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 "
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
-
|
|
376
|
-
|
|
468
|
+
describe "#params=" do
|
|
469
|
+
let(:transaction) { new_transaction }
|
|
377
470
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
-
|
|
393
|
-
|
|
394
|
-
expect(transaction).to include_params(params)
|
|
395
|
-
end
|
|
494
|
+
describe "#set_params" do
|
|
495
|
+
let(:transaction) { new_transaction }
|
|
396
496
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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
|
-
|
|
422
|
-
|
|
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
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
521
|
+
transaction._sample
|
|
522
|
+
expect(transaction.params).to eq(arg_params)
|
|
523
|
+
expect(transaction).to include_params(arg_params)
|
|
524
|
+
end
|
|
428
525
|
|
|
429
|
-
|
|
430
|
-
|
|
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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
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
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
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
|
-
|
|
449
|
-
|
|
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
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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
|
-
|
|
460
|
-
|
|
461
|
-
|
|
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
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
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
|
-
|
|
479
|
-
|
|
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(
|
|
482
|
-
transaction.set_params_if_nil
|
|
585
|
+
transaction.set_params(params)
|
|
586
|
+
transaction.set_params_if_nil(nil)
|
|
483
587
|
|
|
484
588
|
transaction._sample
|
|
485
|
-
expect(transaction.params).to eq(
|
|
486
|
-
expect(transaction).to include_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
|
-
|
|
492
|
-
|
|
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
|
|
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 "
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
transaction.
|
|
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
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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
|
-
|
|
531
|
-
|
|
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
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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
|
|
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 "
|
|
561
|
-
|
|
562
|
-
|
|
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
|
|
568
|
-
[123, "abc"],
|
|
569
|
-
["appsignal", "enterprise"]
|
|
570
|
-
])
|
|
637
|
+
expect(transaction).to include_session_data(data)
|
|
571
638
|
end
|
|
572
639
|
|
|
573
|
-
it "
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
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).
|
|
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).
|
|
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
|
-
"
|
|
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
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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
|
|
675
|
+
expect(transaction).to include_session_data(data)
|
|
606
676
|
end
|
|
607
677
|
end
|
|
678
|
+
end
|
|
608
679
|
|
|
609
|
-
|
|
610
|
-
|
|
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
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
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
|
-
|
|
644
|
-
|
|
645
|
-
|
|
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
|
-
|
|
651
|
-
|
|
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
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
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
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
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
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
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
|
-
|
|
681
|
-
|
|
682
|
-
end
|
|
728
|
+
transaction._sample
|
|
729
|
+
expect(transaction).to include_session_data(preset_data)
|
|
683
730
|
end
|
|
684
731
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
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
|
-
|
|
692
|
-
|
|
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
|
-
|
|
698
|
-
|
|
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
|
-
|
|
704
|
-
|
|
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
|
-
|
|
707
|
-
|
|
708
|
-
|
|
752
|
+
transaction._sample
|
|
753
|
+
expect(transaction).to include_environment(headers)
|
|
754
|
+
end
|
|
709
755
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
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
|
-
|
|
717
|
-
|
|
718
|
-
end
|
|
719
|
-
end
|
|
760
|
+
transaction._sample
|
|
761
|
+
expect(transaction).to include_environment(headers)
|
|
720
762
|
end
|
|
721
763
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
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
|
-
|
|
729
|
-
|
|
730
|
-
end
|
|
769
|
+
transaction._sample
|
|
770
|
+
expect(transaction).to include_environment(arg_data)
|
|
731
771
|
end
|
|
732
|
-
end
|
|
733
772
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
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
|
-
|
|
741
|
-
|
|
742
|
-
end
|
|
777
|
+
transaction._sample
|
|
778
|
+
expect(transaction).to include_environment("MY_HEADER" => "value1")
|
|
743
779
|
end
|
|
744
780
|
|
|
745
|
-
|
|
746
|
-
|
|
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
|
-
|
|
752
|
-
|
|
753
|
-
|
|
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
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
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
|
|
783
|
-
it "does not
|
|
784
|
-
|
|
785
|
-
transaction.
|
|
786
|
-
|
|
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
|
-
|
|
792
|
-
it "
|
|
793
|
-
|
|
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.
|
|
852
|
+
transaction._sample
|
|
853
|
+
expect(transaction).to include_environment(preset_headers)
|
|
796
854
|
end
|
|
797
855
|
|
|
798
|
-
it "does not
|
|
799
|
-
|
|
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.
|
|
862
|
+
transaction._sample
|
|
863
|
+
expect(transaction).to include_environment(preset_headers)
|
|
802
864
|
end
|
|
865
|
+
end
|
|
866
|
+
end
|
|
803
867
|
|
|
804
|
-
|
|
805
|
-
|
|
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
|
-
|
|
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
|
-
|
|
810
|
-
|
|
905
|
+
expect(transaction).to include_tags(
|
|
906
|
+
"key1" => "value1",
|
|
907
|
+
"key2" => "value2"
|
|
908
|
+
)
|
|
811
909
|
end
|
|
910
|
+
end
|
|
812
911
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
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
|
-
|
|
818
|
-
|
|
819
|
-
|
|
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
|
-
|
|
822
|
-
|
|
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
|
-
|
|
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
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
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
|
-
|
|
836
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
844
|
-
|
|
1062
|
+
describe "#set_action" do
|
|
1063
|
+
let(:transaction) { new_transaction }
|
|
845
1064
|
|
|
846
|
-
|
|
847
|
-
|
|
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
|
-
|
|
850
|
-
|
|
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
|
-
|
|
855
|
-
it "
|
|
856
|
-
|
|
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
|
|
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
|
-
|
|
862
|
-
|
|
863
|
-
after { Appsignal.config[:filter_metadata] = [] }
|
|
1087
|
+
describe "#set_action_if_nil" do
|
|
1088
|
+
let(:transaction) { new_transaction }
|
|
864
1089
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
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
|
-
|
|
870
|
-
|
|
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
|
|
874
|
-
it "does not update the
|
|
875
|
-
|
|
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).
|
|
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
|
-
|
|
882
|
-
|
|
883
|
-
|
|
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
|
-
|
|
886
|
-
|
|
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
|
-
|
|
891
|
-
|
|
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
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
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
|
-
|
|
907
|
-
|
|
908
|
-
|
|
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
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
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
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
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
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
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
|
-
|
|
933
|
-
let(:
|
|
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
|
|
936
|
-
|
|
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
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
expect(
|
|
947
|
-
|
|
948
|
-
"
|
|
949
|
-
|
|
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
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
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
|
|
964
|
-
|
|
965
|
-
|
|
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
|
-
|
|
968
|
-
|
|
969
|
-
|
|
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
|
-
|
|
976
|
-
let(:env) {
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
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
|
-
|
|
984
|
-
|
|
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
|
-
|
|
988
|
-
|
|
989
|
-
|
|
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.
|
|
1305
|
+
expect(transaction).to_not include_metadata
|
|
992
1306
|
end
|
|
1307
|
+
end
|
|
993
1308
|
|
|
994
|
-
|
|
995
|
-
|
|
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
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1021
|
-
|
|
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
|
-
|
|
1383
|
+
@calls += 1
|
|
1025
1384
|
end
|
|
1026
1385
|
end
|
|
1027
1386
|
|
|
1028
|
-
|
|
1029
|
-
|
|
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
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
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
|
-
|
|
1047
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
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
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
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
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
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
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
)
|
|
1587
|
+
transaction.set_error(error)
|
|
1588
|
+
end
|
|
1589
|
+
end
|
|
1102
1590
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
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
|
-
|
|
1122
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1133
|
-
|
|
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
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
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
|
-
|
|
1644
|
+
it "should not raise an error" do
|
|
1645
|
+
transaction.set_error(error)
|
|
1142
1646
|
end
|
|
1143
1647
|
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
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
|
-
|
|
1150
|
-
end
|
|
1655
|
+
transaction.set_error(error)
|
|
1151
1656
|
end
|
|
1152
1657
|
end
|
|
1658
|
+
end
|
|
1153
1659
|
|
|
1154
|
-
|
|
1155
|
-
|
|
1660
|
+
describe "#start_event" do
|
|
1661
|
+
let(:transaction) { new_transaction }
|
|
1156
1662
|
|
|
1157
|
-
|
|
1158
|
-
|
|
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
|
-
|
|
1167
|
-
|
|
1168
|
-
"title",
|
|
1169
|
-
"body",
|
|
1170
|
-
1
|
|
1171
|
-
)
|
|
1172
|
-
end
|
|
1666
|
+
transaction.start_event
|
|
1667
|
+
end
|
|
1173
1668
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
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.
|
|
1184
|
-
"name",
|
|
1185
|
-
nil,
|
|
1186
|
-
nil,
|
|
1187
|
-
nil
|
|
1188
|
-
)
|
|
1674
|
+
transaction.start_event
|
|
1189
1675
|
end
|
|
1676
|
+
end
|
|
1677
|
+
end
|
|
1190
1678
|
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
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
|
-
|
|
1202
|
-
|
|
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
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
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.
|
|
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
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
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
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
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
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
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
|
-
|
|
1265
|
-
|
|
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
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1808
|
+
expect(logs).to contains_log(
|
|
1809
|
+
:warn,
|
|
1810
|
+
"The use of Appsignal::Transaction::GenericRequest is deprecated."
|
|
1811
|
+
)
|
|
1812
|
+
end
|
|
1271
1813
|
|
|
1272
|
-
|
|
1273
|
-
|
|
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
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
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
|
-
|
|
1285
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1293
|
-
|
|
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
|
|
1881
|
+
it { is_expected.to be_nil }
|
|
1299
1882
|
end
|
|
1300
1883
|
|
|
1301
1884
|
context "when env is nil" do
|
|
1302
|
-
before { expect(
|
|
1303
|
-
|
|
1304
|
-
it { is_expected.to eq nil }
|
|
1305
|
-
end
|
|
1885
|
+
before { expect(request).to receive(:env).and_return(nil) }
|
|
1306
1886
|
|
|
1307
|
-
|
|
1308
|
-
it { is_expected.to eq nil }
|
|
1887
|
+
it { is_expected.to be_nil }
|
|
1309
1888
|
end
|
|
1310
1889
|
|
|
1311
|
-
context "
|
|
1312
|
-
let(:env) {
|
|
1890
|
+
context "with no relevant header set" do
|
|
1891
|
+
let(:env) { {} }
|
|
1313
1892
|
|
|
1314
|
-
it { is_expected.to
|
|
1893
|
+
it { is_expected.to be_nil }
|
|
1315
1894
|
end
|
|
1316
|
-
end
|
|
1317
1895
|
|
|
1318
|
-
|
|
1319
|
-
|
|
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
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
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 "
|
|
1331
|
-
|
|
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
|
|
1910
|
+
it { is_expected.to eq 1_389_783_599_600 }
|
|
1334
1911
|
end
|
|
1335
1912
|
|
|
1336
|
-
context "with
|
|
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
|
|
1343
|
-
let(:env) { { "
|
|
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
|
-
|
|
1374
|
-
|
|
1927
|
+
context "time in milliseconds" do
|
|
1928
|
+
let(:factor) { 1_000 }
|
|
1375
1929
|
|
|
1376
|
-
|
|
1377
|
-
|
|
1930
|
+
it_should_behave_like "http queue start"
|
|
1931
|
+
end
|
|
1378
1932
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1933
|
+
context "time in microseconds" do
|
|
1934
|
+
let(:factor) { 1_000_000 }
|
|
1381
1935
|
|
|
1382
|
-
|
|
1383
|
-
end
|
|
1936
|
+
it_should_behave_like "http queue start"
|
|
1384
1937
|
end
|
|
1938
|
+
end
|
|
1385
1939
|
|
|
1386
|
-
|
|
1387
|
-
|
|
1940
|
+
describe "#sanitized_params" do
|
|
1941
|
+
let(:transaction) { new_transaction }
|
|
1942
|
+
subject { transaction.send(:sanitized_params) }
|
|
1388
1943
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1944
|
+
context "with params" do
|
|
1945
|
+
before do
|
|
1946
|
+
transaction.set_params(:foo => "bar", :baz => :bat)
|
|
1947
|
+
end
|
|
1393
1948
|
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1949
|
+
it "returns params" do
|
|
1950
|
+
is_expected.to eq(:foo => "bar", :baz => :bat)
|
|
1951
|
+
end
|
|
1397
1952
|
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
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
|
-
|
|
1403
|
-
|
|
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 {
|
|
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)
|
|
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)
|
|
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)
|
|
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
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
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
|
-
|
|
1484
|
-
|
|
2036
|
+
context "when request is nil" do
|
|
2037
|
+
let(:request) { nil }
|
|
1485
2038
|
|
|
1486
|
-
|
|
1487
|
-
|
|
2039
|
+
it { is_expected.to be_nil }
|
|
2040
|
+
end
|
|
1488
2041
|
|
|
1489
|
-
|
|
1490
|
-
|
|
2042
|
+
context "when env is nil" do
|
|
2043
|
+
before { expect(request).to receive(:env).and_return(nil) }
|
|
1491
2044
|
|
|
1492
|
-
|
|
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
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
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(
|
|
2067
|
+
expect(subject.keys).to match_array(%w[CONTENT_LENGTH])
|
|
1506
2068
|
end
|
|
2069
|
+
end
|
|
2070
|
+
end
|
|
2071
|
+
end
|
|
1507
2072
|
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
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
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
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
|
-
|
|
1521
|
-
|
|
2085
|
+
context "when session is nil" do
|
|
2086
|
+
before { expect(transaction.request).to receive(:session).and_return(nil) }
|
|
1522
2087
|
|
|
1523
|
-
|
|
1524
|
-
|
|
2088
|
+
it { is_expected.to be_nil }
|
|
2089
|
+
end
|
|
1525
2090
|
|
|
1526
|
-
|
|
1527
|
-
|
|
2091
|
+
context "when session is empty" do
|
|
2092
|
+
before { expect(transaction.request).to receive(:session).and_return({}) }
|
|
1528
2093
|
|
|
1529
|
-
|
|
1530
|
-
|
|
2094
|
+
it { is_expected.to eq({}) }
|
|
2095
|
+
end
|
|
1531
2096
|
|
|
1532
|
-
|
|
1533
|
-
|
|
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
|
-
|
|
1536
|
-
|
|
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
|
-
|
|
1539
|
-
|
|
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
|
-
|
|
1542
|
-
|
|
2124
|
+
context "with session filtering" do
|
|
2125
|
+
let(:session_data_filter) { %w[foo] }
|
|
1543
2126
|
|
|
1544
|
-
|
|
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
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
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
|
-
|
|
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 =>
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1618
|
-
|
|
2173
|
+
context "when not sending session data" do
|
|
2174
|
+
before { Appsignal.config[:send_session_data] = false }
|
|
1619
2175
|
|
|
1620
|
-
|
|
1621
|
-
|
|
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
|
-
|
|
1628
|
-
|
|
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
|
-
|
|
1631
|
-
|
|
2189
|
+
context "when request is nil" do
|
|
2190
|
+
let(:request) { nil }
|
|
1632
2191
|
|
|
1633
|
-
|
|
1634
|
-
|
|
2192
|
+
it { is_expected.to be_nil }
|
|
2193
|
+
end
|
|
1635
2194
|
|
|
1636
|
-
|
|
1637
|
-
|
|
2195
|
+
context "when env is nil" do
|
|
2196
|
+
before { expect(request).to receive(:env).and_return(nil) }
|
|
1638
2197
|
|
|
1639
|
-
|
|
1640
|
-
|
|
2198
|
+
it { is_expected.to be_nil }
|
|
2199
|
+
end
|
|
1641
2200
|
|
|
1642
|
-
|
|
1643
|
-
|
|
2201
|
+
context "when env is present" do
|
|
2202
|
+
let(:env) { { :metadata => { "key" => "value" } } }
|
|
1644
2203
|
|
|
1645
|
-
|
|
2204
|
+
it do
|
|
2205
|
+
is_expected.to eq("key" => "value")
|
|
2206
|
+
end
|
|
1646
2207
|
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
2208
|
+
context "with filter_metadata option set" do
|
|
2209
|
+
before { Appsignal.config[:filter_metadata] = ["key"] }
|
|
2210
|
+
after { Appsignal.config[:filter_metadata] = [] }
|
|
1650
2211
|
|
|
1651
|
-
|
|
1652
|
-
|
|
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
|
-
|
|
1659
|
-
|
|
2219
|
+
describe "#cleaned_backtrace" do
|
|
2220
|
+
let(:transaction) { new_transaction }
|
|
2221
|
+
subject { transaction.send(:cleaned_backtrace, ["line 1", "line 2"]) }
|
|
1660
2222
|
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
2223
|
+
it "returns the backtrace" do
|
|
2224
|
+
expect(subject).to eq ["line 1", "line 2"]
|
|
2225
|
+
end
|
|
1664
2226
|
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
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
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
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" =>
|
|
2303
|
+
"id" => kind_of(String),
|
|
1741
2304
|
"metadata" => {},
|
|
1742
|
-
"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.
|
|
2338
|
+
subject._sample
|
|
1776
2339
|
subject.set_error("a")
|
|
1777
2340
|
end
|
|
1778
2341
|
end
|