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