appsignal 3.4.11-java → 3.4.13-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.
@@ -36,9 +36,14 @@ module Appsignal
36
36
 
37
37
  Appsignal.start
38
38
 
39
- if Appsignal.config[:enable_rails_error_reporter] && Rails.respond_to?(:error) # rubocop:disable Style/GuardClause
40
- Rails.error.subscribe(Appsignal::Integrations::RailsErrorReporterSubscriber)
41
- end
39
+ initialize_error_reporter
40
+ end
41
+
42
+ def self.initialize_error_reporter
43
+ return unless Appsignal.config[:enable_rails_error_reporter]
44
+ return unless Rails.respond_to?(:error)
45
+
46
+ Rails.error.subscribe(Appsignal::Integrations::RailsErrorReporterSubscriber)
42
47
  end
43
48
  end
44
49
 
@@ -320,7 +320,14 @@ module Appsignal
320
320
  end
321
321
 
322
322
  def set_sample_data(key, data)
323
- return unless key && data && (data.is_a?(Array) || data.is_a?(Hash))
323
+ return unless key && data
324
+
325
+ if !data.is_a?(Array) && !data.is_a?(Hash)
326
+ Appsignal.logger.error(
327
+ "Invalid sample data for '#{key}'. Value is not an Array or Hash: '#{data.inspect}'"
328
+ )
329
+ return
330
+ end
324
331
 
325
332
  @ext.set_sample_data(
326
333
  key.to_s,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.4.11"
4
+ VERSION = "3.4.13"
5
5
  end
@@ -781,6 +781,9 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
781
781
  "file" => {},
782
782
  "env" => {},
783
783
  "override" => { "send_session_data" => true }
784
+ },
785
+ "modifiers" => {
786
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" => ""
784
787
  }
785
788
  )
786
789
  end
@@ -912,6 +915,28 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
912
915
  end
913
916
  end
914
917
 
918
+ describe "modifiers" do
919
+ before do
920
+ ENV["APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR"] = "1"
921
+ run
922
+ end
923
+
924
+ it "outputs config modifiers" do
925
+ expect(output).to include(
926
+ "Configuration modifiers\n" \
927
+ " APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR: \"1\""
928
+ )
929
+ end
930
+
931
+ it "transmits config modifiers in report" do
932
+ expect(received_report["config"]).to include(
933
+ "modifiers" => {
934
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" => "1"
935
+ }
936
+ )
937
+ end
938
+ end
939
+
915
940
  it "transmits config in report" do
916
941
  run
917
942
  additional_initial_config = {}
@@ -935,6 +960,9 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
935
960
  "file" => hash_with_string_keys(config.file_config),
936
961
  "env" => {},
937
962
  "override" => { "send_session_data" => true }
963
+ },
964
+ "modifiers" => {
965
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" => ""
938
966
  }
939
967
  )
940
968
  end
@@ -963,6 +991,9 @@ describe Appsignal::CLI::Diagnose, :api_stub => true, :send_report => :yes_cli_i
963
991
  "file" => hash_with_string_keys(config.file_config),
964
992
  "env" => {},
965
993
  "override" => { "send_session_data" => true }
994
+ },
995
+ "modifiers" => {
996
+ "APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR" => ""
966
997
  }
967
998
  )
968
999
  end
@@ -294,19 +294,48 @@ describe Appsignal::Config do
294
294
  end
295
295
  let(:config) { Appsignal::Config.new(config_path, "foo") }
296
296
 
297
- it "logs & prints an error, skipping the file source" do
298
- stdout = std_stream
299
- stderr = std_stream
300
- log = capture_logs { capture_std_streams(stdout, stderr) { config } }
301
- message = "An error occured while loading the AppSignal config file. " \
302
- "Skipping file config.\n" \
303
- "File: #{File.join(config_path, "config", "appsignal.yml").inspect}\n" \
304
- "KeyError: key not found"
305
- expect(log).to contains_log :error, message
306
- expect(log).to include("/appsignal/config.rb:") # Backtrace
307
- expect(stdout.read).to_not include("appsignal:")
308
- expect(stderr.read).to include "appsignal: #{message}"
309
- expect(config.file_config).to eql({})
297
+ context "when APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR is not set" do
298
+ it "logs & prints an error, skipping the file source" do
299
+ stdout = std_stream
300
+ stderr = std_stream
301
+ log = capture_logs { capture_std_streams(stdout, stderr) { config } }
302
+ message = "An error occured while loading the AppSignal config file. " \
303
+ "Skipping file config. " \
304
+ "In future versions AppSignal will not start on a config file " \
305
+ "error. To opt-in to this new behavior set " \
306
+ "'APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR=1' in your system " \
307
+ "environment.\n" \
308
+ "File: #{File.join(config_path, "config", "appsignal.yml").inspect}\n" \
309
+ "KeyError: key not found"
310
+ expect(log).to contains_log :error, message
311
+ expect(log).to include("/appsignal/config.rb:") # Backtrace
312
+ expect(stdout.read).to_not include("appsignal:")
313
+ expect(stderr.read).to include "appsignal: #{message}"
314
+ expect(config.file_config).to eql({})
315
+ end
316
+ end
317
+
318
+ context "when APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR=1 is set" do
319
+ it "does not start AppSignal, logs & prints an error" do
320
+ stdout = std_stream
321
+ stderr = std_stream
322
+ ENV["APPSIGNAL_ACTIVE"] = "true"
323
+ ENV["APPSIGNAL_APP_NAME"] = "My app"
324
+ ENV["APPSIGNAL_APP_ENV"] = "dev"
325
+ ENV["APPSIGNAL_PUSH_API_KEY"] = "something valid"
326
+ ENV["APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR"] = "1"
327
+ log = capture_logs { capture_std_streams(stdout, stderr) { config } }
328
+ message = "An error occured while loading the AppSignal config file. " \
329
+ "Not starting AppSignal because APPSIGNAL_INACTIVE_ON_CONFIG_FILE_ERROR is set.\n" \
330
+ "File: #{File.join(config_path, "config", "appsignal.yml").inspect}\n" \
331
+ "KeyError: key not found"
332
+ expect(log).to contains_log :error, message
333
+ expect(log).to include("/appsignal/config.rb:") # Backtrace
334
+ expect(stdout.read).to_not include("appsignal:")
335
+ expect(stderr.read).to include "appsignal: #{message}"
336
+ expect(config.file_config).to eql({})
337
+ expect(config.active?).to be(false)
338
+ end
310
339
  end
311
340
  end
312
341
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Appsignal::EventFormatter::Rom::SqlFormatter do
4
+ let(:klass) { described_class }
5
+ let(:formatter) { klass.new }
6
+
7
+ it "registers the sql event formatter" do
8
+ expect(Appsignal::EventFormatter.registered?("sql.dry", klass)).to be_truthy
9
+ end
10
+
11
+ describe "#format" do
12
+ let(:payload) do
13
+ {
14
+ :name => "postgres",
15
+ :query => "SELECT * FROM users"
16
+ }
17
+ end
18
+ subject { formatter.format(payload) }
19
+
20
+ it { is_expected.to eq ["query.postgres", "SELECT * FROM users", 1] }
21
+ end
22
+ end
@@ -22,6 +22,12 @@ describe Appsignal::Hooks::ActiveSupportNotificationsHook do
22
22
 
23
23
  it_behaves_like "activesupport instrument override"
24
24
 
25
+ if defined?(::ActiveSupport::Notifications::Fanout::Handle)
26
+ require_relative "./active_support_notifications/start_finish_shared_examples"
27
+
28
+ it_behaves_like "activesupport start finish override"
29
+ end
30
+
25
31
  if ::ActiveSupport::Notifications::Instrumenter.method_defined?(:start)
26
32
  require_relative "./active_support_notifications/start_finish_shared_examples"
27
33
 
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ if DependencyHelper.dry_monitor_present?
4
+ require "dry-monitor"
5
+
6
+ describe Appsignal::Hooks::DryMonitorHook do
7
+ describe "#dependencies_present?" do
8
+ subject { described_class.new.dependencies_present? }
9
+
10
+ context "when Dry::Monitor::Notifications constant is found" do
11
+ before { stub_const "Dry::Monitor::Notifications", Class.new }
12
+
13
+ it { is_expected.to be_truthy }
14
+ end
15
+
16
+ context "when Dry::Monitor::Notifications constant is not found" do
17
+ before { hide_const "Dry::Monitor::Notifications" }
18
+
19
+ it { is_expected.to be_falsy }
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "#install" do
25
+ it "installs the dry-monitor hook" do
26
+ start_agent
27
+
28
+ expect(Dry::Monitor::Notifications.included_modules).to include(
29
+ Appsignal::Integrations::DryMonitorIntegration
30
+ )
31
+ end
32
+ end
33
+
34
+ describe "Dry Monitor Integration" do
35
+ before :context do
36
+ start_agent
37
+ end
38
+
39
+ let!(:transaction) do
40
+ Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
41
+ end
42
+
43
+ let(:notifications) { Dry::Monitor::Notifications.new(:test) }
44
+
45
+ context "when is a dry-sql event" do
46
+ let(:event_id) { :sql }
47
+ let(:payload) do
48
+ {
49
+ :name => "postgres",
50
+ :query => "SELECT * FROM users"
51
+ }
52
+ end
53
+
54
+ it "creates an sql event" do
55
+ notifications.instrument(event_id, payload)
56
+ expect(transaction.to_h["events"]).to match([
57
+ {
58
+ "allocation_count" => kind_of(Integer),
59
+ "body" => "SELECT * FROM users",
60
+ "body_format" => Appsignal::EventFormatter::SQL_BODY_FORMAT,
61
+ "child_allocation_count" => kind_of(Integer),
62
+ "child_duration" => kind_of(Float),
63
+ "child_gc_duration" => kind_of(Float),
64
+ "count" => 1,
65
+ "duration" => kind_of(Float),
66
+ "gc_duration" => kind_of(Float),
67
+ "name" => "query.postgres",
68
+ "start" => kind_of(Float),
69
+ "title" => "query.postgres"
70
+ }
71
+ ])
72
+ end
73
+ end
74
+
75
+ context "when is an unregistered formatter event" do
76
+ let(:event_id) { :foo }
77
+ let(:payload) do
78
+ {
79
+ :name => "foo"
80
+ }
81
+ end
82
+
83
+ it "creates a generic event" do
84
+ notifications.instrument(event_id, payload)
85
+ expect(transaction.to_h["events"]).to match([
86
+ {
87
+ "allocation_count" => kind_of(Integer),
88
+ "body" => "",
89
+ "body_format" => Appsignal::EventFormatter::DEFAULT,
90
+ "child_allocation_count" => kind_of(Integer),
91
+ "child_duration" => kind_of(Float),
92
+ "child_gc_duration" => kind_of(Float),
93
+ "count" => 1,
94
+ "duration" => kind_of(Float),
95
+ "gc_duration" => kind_of(Float),
96
+ "name" => "foo",
97
+ "start" => kind_of(Float),
98
+ "title" => ""
99
+ }
100
+ ])
101
+ end
102
+ end
103
+ end
104
+ end
@@ -2,6 +2,10 @@ if DependencyHelper.rails_present?
2
2
  require "action_mailer"
3
3
 
4
4
  describe Appsignal::Integrations::Railtie do
5
+ include RailsHelper
6
+
7
+ after { clear_rails_error_reporter! }
8
+
5
9
  context "after initializing the app" do
6
10
  it "should call initialize_appsignal" do
7
11
  expect(Appsignal::Integrations::Railtie).to receive(:initialize_appsignal)
@@ -125,17 +129,16 @@ if DependencyHelper.rails_present?
125
129
 
126
130
  if Rails.respond_to?(:error)
127
131
  describe "Rails error reporter" do
128
- before do
129
- Appsignal::Integrations::Railtie.initialize_appsignal(app)
130
- start_agent
131
- end
132
+ before { start_agent }
132
133
  around { |example| keep_transactions { example.run } }
133
134
 
134
135
  context "when error is not handled (reraises the error)" do
135
136
  it "does nothing" do
136
- expect do
137
- Rails.error.record { raise ExampleStandardError }
138
- end.to raise_error(ExampleStandardError)
137
+ with_rails_error_reporter do
138
+ expect do
139
+ Rails.error.record { raise ExampleStandardError }
140
+ end.to raise_error(ExampleStandardError)
141
+ end
139
142
 
140
143
  expect(created_transactions).to be_empty
141
144
  end
@@ -151,26 +154,28 @@ if DependencyHelper.rails_present?
151
154
  :duplicated_tag => "duplicated value"
152
155
  )
153
156
 
154
- with_current_transaction current_transaction do
155
- Rails.error.handle { raise ExampleStandardError }
156
-
157
- transaction = last_transaction
158
- transaction_hash = transaction.to_h
159
- expect(transaction_hash).to include(
160
- "action" => "CustomAction",
161
- "namespace" => "custom",
162
- "error" => {
163
- "name" => "ExampleStandardError",
164
- "message" => "ExampleStandardError",
165
- "backtrace" => kind_of(String)
166
- },
167
- "sample_data" => hash_including(
168
- "tags" => {
169
- "duplicated_tag" => "duplicated value",
170
- "severity" => "warning"
171
- }
157
+ with_rails_error_reporter do
158
+ with_current_transaction current_transaction do
159
+ Rails.error.handle { raise ExampleStandardError }
160
+
161
+ transaction = last_transaction
162
+ transaction_hash = transaction.to_h
163
+ expect(transaction_hash).to include(
164
+ "action" => "CustomAction",
165
+ "namespace" => "custom",
166
+ "error" => {
167
+ "name" => "ExampleStandardError",
168
+ "message" => "ExampleStandardError",
169
+ "backtrace" => kind_of(String)
170
+ },
171
+ "sample_data" => hash_including(
172
+ "tags" => hash_including(
173
+ "duplicated_tag" => "duplicated value",
174
+ "severity" => "warning"
175
+ )
176
+ )
172
177
  )
173
- )
178
+ end
174
179
  end
175
180
  end
176
181
 
@@ -178,48 +183,52 @@ if DependencyHelper.rails_present?
178
183
  current_transaction = http_request_transaction
179
184
  current_transaction.set_tags(:tag1 => "duplicated value")
180
185
 
181
- with_current_transaction current_transaction do
182
- given_context = { :tag1 => "value1", :tag2 => "value2" }
183
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
184
-
185
- transaction = last_transaction
186
- transaction_hash = transaction.to_h
187
- expect(transaction_hash).to include(
188
- "sample_data" => hash_including(
189
- "tags" => {
190
- "tag1" => "value1",
191
- "tag2" => "value2",
192
- "severity" => "warning"
193
- }
186
+ with_rails_error_reporter do
187
+ with_current_transaction current_transaction do
188
+ given_context = { :tag1 => "value1", :tag2 => "value2" }
189
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
190
+
191
+ transaction = last_transaction
192
+ transaction_hash = transaction.to_h
193
+ expect(transaction_hash).to include(
194
+ "sample_data" => hash_including(
195
+ "tags" => hash_including(
196
+ "tag1" => "value1",
197
+ "tag2" => "value2",
198
+ "severity" => "warning"
199
+ )
200
+ )
194
201
  )
195
- )
202
+ end
196
203
  end
197
204
  end
198
205
 
199
206
  it "sends tags stored in :appsignal -> :custom_data as custom data" do
200
207
  current_transaction = http_request_transaction
201
208
 
202
- with_current_transaction current_transaction do
203
- given_context = {
204
- :appsignal => {
205
- :custom_data => {
206
- :array => [1, 2],
207
- :hash => { :one => 1, :two => 2 }
209
+ with_rails_error_reporter do
210
+ with_current_transaction current_transaction do
211
+ given_context = {
212
+ :appsignal => {
213
+ :custom_data => {
214
+ :array => [1, 2],
215
+ :hash => { :one => 1, :two => 2 }
216
+ }
208
217
  }
209
218
  }
210
- }
211
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
212
-
213
- transaction = last_transaction
214
- transaction_hash = transaction.to_h
215
- expect(transaction_hash).to include(
216
- "sample_data" => hash_including(
217
- "custom_data" => {
218
- "array" => [1, 2],
219
- "hash" => { "one" => 1, "two" => 2 }
220
- }
219
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
220
+
221
+ transaction = last_transaction
222
+ transaction_hash = transaction.to_h
223
+ expect(transaction_hash).to include(
224
+ "sample_data" => hash_including(
225
+ "custom_data" => {
226
+ "array" => [1, 2],
227
+ "hash" => { "one" => 1, "two" => 2 }
228
+ }
229
+ )
221
230
  )
222
- )
231
+ end
223
232
  end
224
233
  end
225
234
 
@@ -228,18 +237,20 @@ if DependencyHelper.rails_present?
228
237
  current_transaction.set_namespace "custom"
229
238
  current_transaction.set_action "CustomAction"
230
239
 
231
- with_current_transaction current_transaction do
232
- given_context = {
233
- :appsignal => { :namespace => "context", :action => "ContextAction" }
234
- }
235
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
240
+ with_rails_error_reporter do
241
+ with_current_transaction current_transaction do
242
+ given_context = {
243
+ :appsignal => { :namespace => "context", :action => "ContextAction" }
244
+ }
245
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
236
246
 
237
- transaction = last_transaction
238
- transaction_hash = transaction.to_h
239
- expect(transaction_hash).to include(
240
- "namespace" => "context",
241
- "action" => "ContextAction"
242
- )
247
+ transaction = last_transaction
248
+ transaction_hash = transaction.to_h
249
+ expect(transaction_hash).to include(
250
+ "namespace" => "context",
251
+ "action" => "ContextAction"
252
+ )
253
+ end
243
254
  end
244
255
  end
245
256
  end
@@ -267,7 +278,9 @@ if DependencyHelper.rails_present?
267
278
  it "fetches the action from the controller in the context" do
268
279
  # The controller key is set by Rails when raised in a controller
269
280
  given_context = { :controller => ExampleRailsControllerMock.new }
270
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
281
+ with_rails_error_reporter do
282
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
283
+ end
271
284
 
272
285
  transaction = last_transaction
273
286
  transaction_hash = transaction.to_h
@@ -278,7 +291,9 @@ if DependencyHelper.rails_present?
278
291
 
279
292
  it "sets no action if no execution context is present" do
280
293
  # The controller key is set by Rails when raised in a controller
281
- Rails.error.handle { raise ExampleStandardError }
294
+ with_rails_error_reporter do
295
+ Rails.error.handle { raise ExampleStandardError }
296
+ end
282
297
 
283
298
  transaction = last_transaction
284
299
  transaction_hash = transaction.to_h
@@ -296,17 +311,19 @@ if DependencyHelper.rails_present?
296
311
  :tag1 => "value1",
297
312
  :tag2 => "value2"
298
313
  }
299
- Rails.error.handle(:context => given_context) { raise ExampleStandardError }
314
+ with_rails_error_reporter do
315
+ Rails.error.handle(:context => given_context) { raise ExampleStandardError }
316
+ end
300
317
 
301
318
  transaction = last_transaction
302
319
  transaction_hash = transaction.to_h
303
320
  expect(transaction_hash).to include(
304
321
  "sample_data" => hash_including(
305
- "tags" => {
322
+ "tags" => hash_including(
306
323
  "tag1" => "value1",
307
324
  "tag2" => "value2",
308
325
  "severity" => "warning"
309
- }
326
+ )
310
327
  )
311
328
  )
312
329
  end
@@ -266,13 +266,16 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
266
266
 
267
267
  if DependencyHelper.rails7_present?
268
268
  context "with Rails error reporter" do
269
+ include RailsHelper
270
+
269
271
  it "reports the worker name as the action, copies the namespace and tags" do
270
- Appsignal::Integrations::Railtie.initialize_appsignal(MyApp::Application.new)
271
272
  Appsignal.config = project_fixture_config("production")
272
- perform_job do
273
- Appsignal.tag_job("test_tag" => "value")
274
- Rails.error.handle do
275
- raise error, "uh oh"
273
+ with_rails_error_reporter do
274
+ perform_job do
275
+ Appsignal.tag_job("test_tag" => "value")
276
+ Rails.error.handle do
277
+ raise ExampleStandardError, "uh oh"
278
+ end
276
279
  end
277
280
  end
278
281
 
@@ -363,7 +366,9 @@ if DependencyHelper.active_job_present?
363
366
  require "sidekiq/testing"
364
367
 
365
368
  describe "Sidekiq ActiveJob integration" do
369
+ include RailsHelper
366
370
  include ActiveJobHelpers
371
+
367
372
  let(:namespace) { Appsignal::Transaction::BACKGROUND_JOB }
368
373
  let(:time) { Time.parse("2001-01-01 10:00:00UTC") }
369
374
  let(:log) { StringIO.new }
@@ -416,7 +421,7 @@ if DependencyHelper.active_job_present?
416
421
  ["perform_job.sidekiq", "perform_start.active_job", "perform.active_job"]
417
422
  end
418
423
  end
419
- before do
424
+ around do |example|
420
425
  start_agent
421
426
  Appsignal.logger = test_logger(log)
422
427
  ActiveJob::Base.queue_adapter = :sidekiq
@@ -441,11 +446,11 @@ if DependencyHelper.active_job_present?
441
446
  Sidekiq::Testing.server_middleware do |chain|
442
447
  chain.add Appsignal::Integrations::SidekiqMiddleware
443
448
  end
444
- end
445
- around do |example|
446
- keep_transactions do
447
- Sidekiq::Testing.fake! do
448
- example.run
449
+ with_rails_error_reporter do
450
+ keep_transactions do
451
+ Sidekiq::Testing.fake! do
452
+ example.run
453
+ end
449
454
  end
450
455
  end
451
456
  end
@@ -688,6 +688,8 @@ describe Appsignal::Transaction do
688
688
  transaction.set_sample_data("params", "string")
689
689
 
690
690
  expect(transaction.to_h["sample_data"]).to eq({})
691
+ expect(log_contents(log)).to contains_log :error,
692
+ %(Invalid sample data for 'params'. Value is not an Array or Hash: '"string"')
691
693
  end
692
694
  end
693
695
 
@@ -115,6 +115,10 @@ module DependencyHelper
115
115
  dependency_present? "hanami"
116
116
  end
117
117
 
118
+ def dry_monitor_present?
119
+ dependency_present? "dry-monitor"
120
+ end
121
+
118
122
  def hanami2_present?
119
123
  hanami_present? && Gem.loaded_specs["hanami"].version >= Gem::Version.new("2.0")
120
124
  end
@@ -0,0 +1,28 @@
1
+ module RailsHelper
2
+ def with_railtie(app)
3
+ clear_rails_error_reporter! if Rails.respond_to? :error
4
+ Appsignal::Integrations::Railtie.initialize_appsignal(app)
5
+ yield
6
+ ensure
7
+ clear_rails_error_reporter!
8
+ end
9
+
10
+ def with_rails_error_reporter
11
+ if Rails.respond_to? :error
12
+ clear_rails_error_reporter!
13
+ Appsignal::Integrations::Railtie.initialize_error_reporter
14
+ end
15
+ yield
16
+ ensure
17
+ clear_rails_error_reporter!
18
+ end
19
+
20
+ def clear_rails_error_reporter!
21
+ return unless Rails.respond_to? :error
22
+
23
+ Rails
24
+ .error
25
+ .instance_variable_get(:@subscribers)
26
+ .reject! { |s| s == Appsignal::Integrations::RailsErrorReporterSubscriber }
27
+ end
28
+ end