appsignal 3.4.11-java → 3.4.13-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.semaphore/semaphore.yml +126 -0
- data/CHANGELOG.md +29 -0
- data/README.md +1 -0
- data/build_matrix.yml +14 -0
- data/ext/agent.rb +27 -27
- data/gemfiles/dry-monitor.gemfile +5 -0
- data/gemfiles/rails-7.1.gemfile +7 -0
- data/lib/appsignal/cli/diagnose.rb +9 -0
- data/lib/appsignal/config.rb +27 -2
- data/lib/appsignal/event_formatter/rom/sql_formatter.rb +18 -0
- data/lib/appsignal/hooks/active_support_notifications.rb +18 -9
- data/lib/appsignal/hooks/dry_monitor.rb +20 -0
- data/lib/appsignal/hooks.rb +1 -0
- data/lib/appsignal/integrations/active_support_notifications.rb +26 -0
- data/lib/appsignal/integrations/dry_monitor.rb +22 -0
- data/lib/appsignal/integrations/railtie.rb +8 -3
- data/lib/appsignal/transaction.rb +8 -1
- data/lib/appsignal/version.rb +1 -1
- data/spec/lib/appsignal/cli/diagnose_spec.rb +31 -0
- data/spec/lib/appsignal/config_spec.rb +42 -13
- data/spec/lib/appsignal/event_formatter/rom/sql_formatter_spec.rb +22 -0
- data/spec/lib/appsignal/hooks/active_support_notifications_spec.rb +6 -0
- data/spec/lib/appsignal/hooks/dry_monitor_spec.rb +104 -0
- data/spec/lib/appsignal/integrations/railtie_spec.rb +91 -74
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +16 -11
- data/spec/lib/appsignal/transaction_spec.rb +2 -0
- data/spec/support/helpers/dependency_helper.rb +4 -0
- data/spec/support/helpers/rails_helper.rb +28 -0
- metadata +10 -2
@@ -36,9 +36,14 @@ module Appsignal
|
|
36
36
|
|
37
37
|
Appsignal.start
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
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,
|
data/lib/appsignal/version.rb
CHANGED
@@ -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
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
"
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
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
|
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
|
-
|
137
|
-
|
138
|
-
|
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
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
"
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
"
|
169
|
-
"
|
170
|
-
|
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
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
"
|
190
|
-
"
|
191
|
-
|
192
|
-
|
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
|
-
|
203
|
-
|
204
|
-
|
205
|
-
:
|
206
|
-
:
|
207
|
-
|
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
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
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
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
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
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
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
|
-
|
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
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
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
|