appsignal 4.0.6-java → 4.0.7-java

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