appsignal 3.4.0 → 3.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +63 -21
- data/.rubocop_todo.yml +68 -54
- data/.semaphore/semaphore.yml +11 -11
- data/CHANGELOG.md +37 -0
- data/Rakefile +15 -99
- data/appsignal.gemspec +3 -4
- data/bin/appsignal +4 -2
- data/build_matrix.yml +4 -4
- data/ext/._appsignal-agent +0 -0
- data/ext/Rakefile +22 -21
- data/ext/agent.rb +2 -0
- data/ext/base.rb +14 -17
- data/ext/extconf.rb +4 -1
- data/lib/appsignal/auth_check.rb +3 -3
- data/lib/appsignal/capistrano.rb +1 -1
- data/lib/appsignal/cli/demo.rb +5 -2
- data/lib/appsignal/cli/diagnose/paths.rb +4 -1
- data/lib/appsignal/cli/diagnose/utils.rb +7 -3
- data/lib/appsignal/cli/diagnose.rb +7 -5
- data/lib/appsignal/cli/helpers.rb +1 -4
- data/lib/appsignal/cli/install.rb +4 -10
- data/lib/appsignal/cli.rb +3 -2
- data/lib/appsignal/config.rb +105 -102
- data/lib/appsignal/demo.rb +2 -1
- data/lib/appsignal/environment.rb +2 -0
- data/lib/appsignal/event_formatter/action_view/render_formatter.rb +2 -1
- data/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter.rb +13 -13
- data/lib/appsignal/event_formatter.rb +5 -4
- data/lib/appsignal/extension/jruby.rb +11 -9
- data/lib/appsignal/extension.rb +1 -1
- data/lib/appsignal/helpers/instrumentation.rb +50 -35
- data/lib/appsignal/hooks/action_cable.rb +6 -4
- data/lib/appsignal/hooks/action_mailer.rb +2 -0
- data/lib/appsignal/hooks/active_job.rb +11 -10
- data/lib/appsignal/hooks/active_support_notifications.rb +3 -4
- data/lib/appsignal/hooks/data_mapper.rb +1 -1
- data/lib/appsignal/hooks/gvl.rb +3 -0
- data/lib/appsignal/hooks/http.rb +1 -1
- data/lib/appsignal/hooks/mri.rb +2 -0
- data/lib/appsignal/hooks/net_http.rb +1 -1
- data/lib/appsignal/hooks/que.rb +1 -1
- data/lib/appsignal/hooks/rake.rb +1 -1
- data/lib/appsignal/hooks/redis.rb +1 -1
- data/lib/appsignal/hooks/resque.rb +1 -1
- data/lib/appsignal/hooks/shoryuken.rb +2 -4
- data/lib/appsignal/hooks/sidekiq.rb +1 -1
- data/lib/appsignal/hooks/unicorn.rb +2 -2
- data/lib/appsignal/hooks/webmachine.rb +1 -1
- data/lib/appsignal/hooks.rb +2 -2
- data/lib/appsignal/integrations/active_support_notifications.rb +1 -1
- data/lib/appsignal/integrations/capistrano/appsignal.cap +6 -3
- data/lib/appsignal/integrations/capistrano/capistrano_2_tasks.rb +5 -4
- data/lib/appsignal/integrations/delayed_job_plugin.rb +3 -5
- data/lib/appsignal/integrations/grape.rb +1 -1
- data/lib/appsignal/integrations/hanami.rb +1 -1
- data/lib/appsignal/integrations/object.rb +2 -3
- data/lib/appsignal/integrations/padrino.rb +2 -4
- data/lib/appsignal/integrations/que.rb +6 -6
- data/lib/appsignal/integrations/railtie.rb +72 -0
- data/lib/appsignal/integrations/sidekiq.rb +9 -11
- data/lib/appsignal/integrations/sinatra.rb +1 -3
- data/lib/appsignal/integrations/webmachine.rb +4 -6
- data/lib/appsignal/logger.rb +31 -6
- data/lib/appsignal/marker.rb +4 -5
- data/lib/appsignal/minutely.rb +7 -7
- data/lib/appsignal/probes/gvl.rb +9 -4
- data/lib/appsignal/probes/helpers.rb +4 -6
- data/lib/appsignal/probes/mri.rb +7 -5
- data/lib/appsignal/probes/sidekiq.rb +3 -0
- data/lib/appsignal/probes.rb +2 -0
- data/lib/appsignal/rack/generic_instrumentation.rb +1 -5
- data/lib/appsignal/rack/sinatra_instrumentation.rb +3 -5
- data/lib/appsignal/rack/streaming_listener.rb +11 -13
- data/lib/appsignal/span.rb +5 -5
- data/lib/appsignal/system.rb +10 -11
- data/lib/appsignal/transaction.rb +49 -25
- data/lib/appsignal/transmitter.rb +4 -2
- data/lib/appsignal/utils/deprecation_message.rb +2 -0
- data/lib/appsignal/utils/hash_sanitizer.rb +1 -1
- data/lib/appsignal/utils/integration_logger.rb +5 -3
- data/lib/appsignal/utils/json.rb +1 -1
- data/lib/appsignal/utils/query_params_sanitizer.rb +1 -1
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +5 -4
- data/lib/puma/plugin/appsignal.rb +16 -18
- data/script/lint_git +1 -1
- data/spec/lib/appsignal/capistrano2_spec.rb +6 -3
- data/spec/lib/appsignal/capistrano3_spec.rb +6 -3
- data/spec/lib/appsignal/cli/diagnose/utils_spec.rb +1 -3
- data/spec/lib/appsignal/cli/diagnose_spec.rb +33 -30
- data/spec/lib/appsignal/cli/install_spec.rb +5 -6
- data/spec/lib/appsignal/cli_spec.rb +1 -1
- data/spec/lib/appsignal/config_spec.rb +43 -37
- data/spec/lib/appsignal/event_formatter/action_view/render_formatter_spec.rb +11 -5
- data/spec/lib/appsignal/event_formatter/elastic_search/search_formatter_spec.rb +4 -4
- data/spec/lib/appsignal/event_formatter/mongo_ruby_driver/query_formatter_spec.rb +1 -4
- data/spec/lib/appsignal/event_formatter_spec.rb +11 -9
- data/spec/lib/appsignal/hooks/action_cable_spec.rb +5 -2
- data/spec/lib/appsignal/hooks/action_mailer_spec.rb +2 -1
- data/spec/lib/appsignal/hooks/active_support_notifications/instrument_shared_examples.rb +1 -1
- data/spec/lib/appsignal/hooks/active_support_notifications/start_finish_shared_examples.rb +1 -1
- data/spec/lib/appsignal/hooks/activejob_spec.rb +21 -12
- data/spec/lib/appsignal/hooks/data_mapper_spec.rb +1 -0
- data/spec/lib/appsignal/hooks/delayed_job_spec.rb +12 -12
- data/spec/lib/appsignal/hooks/excon_spec.rb +2 -2
- data/spec/lib/appsignal/hooks/mongo_ruby_driver_spec.rb +3 -1
- data/spec/lib/appsignal/hooks/shoryuken_spec.rb +4 -2
- data/spec/lib/appsignal/hooks/sidekiq_spec.rb +2 -1
- data/spec/lib/appsignal/hooks_spec.rb +5 -4
- data/spec/lib/appsignal/integrations/grape_spec.rb +8 -4
- data/spec/lib/appsignal/integrations/hanami_spec.rb +16 -8
- data/spec/lib/appsignal/integrations/mongo_ruby_driver_spec.rb +2 -4
- data/spec/lib/appsignal/integrations/object_spec.rb +6 -1
- data/spec/lib/appsignal/integrations/padrino_spec.rb +4 -2
- data/spec/lib/appsignal/integrations/railtie_spec.rb +213 -6
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +54 -41
- data/spec/lib/appsignal/logger_spec.rb +20 -4
- data/spec/lib/appsignal/marker_spec.rb +2 -2
- data/spec/lib/appsignal/minutely_spec.rb +3 -3
- data/spec/lib/appsignal/probes/gvl_spec.rb +60 -12
- data/spec/lib/appsignal/probes/mri_spec.rb +7 -4
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +2 -1
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +2 -1
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +10 -5
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +7 -5
- data/spec/lib/appsignal/transaction_spec.rb +20 -13
- data/spec/lib/appsignal/utils/data_spec.rb +10 -1
- data/spec/lib/appsignal/utils/hash_sanitizer_spec.rb +11 -11
- data/spec/lib/appsignal/utils/json_spec.rb +4 -2
- data/spec/lib/appsignal_spec.rb +49 -35
- data/spec/lib/puma/appsignal_spec.rb +9 -11
- data/spec/spec_helper.rb +14 -2
- data/spec/support/fixtures/projects/valid/config/appsignal.yml +1 -1
- data/spec/support/helpers/config_helpers.rb +2 -1
- data/spec/support/helpers/dependency_helper.rb +1 -9
- data/spec/support/helpers/std_streams_helper.rb +1 -3
- data/spec/support/helpers/wait_for_helper.rb +2 -3
- data/spec/support/mocks/appsignal_mock.rb +1 -1
- data/spec/support/mocks/fake_gvl_tools.rb +2 -10
- data/spec/support/testing.rb +4 -3
- metadata +9 -135
@@ -153,7 +153,8 @@ if DependencyHelper.grape_present?
|
|
153
153
|
end
|
154
154
|
|
155
155
|
it "sets non-unique route_param path" do
|
156
|
-
expect(transaction).to receive(:set_action_if_nil)
|
156
|
+
expect(transaction).to receive(:set_action_if_nil)
|
157
|
+
.with("GET::GrapeExample::Api#/users/:id/")
|
157
158
|
expect(transaction).to receive(:set_metadata).with("path", "/users/:id/")
|
158
159
|
expect(transaction).to receive(:set_metadata).with("method", "GET")
|
159
160
|
end
|
@@ -177,7 +178,8 @@ if DependencyHelper.grape_present?
|
|
177
178
|
end
|
178
179
|
|
179
180
|
it "sets namespaced path" do
|
180
|
-
expect(transaction).to receive(:set_action_if_nil)
|
181
|
+
expect(transaction).to receive(:set_action_if_nil)
|
182
|
+
.with("POST::GrapeExample::Api#/v1/beta/ping")
|
181
183
|
expect(transaction).to receive(:set_metadata).with("path", "/v1/beta/ping")
|
182
184
|
expect(transaction).to receive(:set_metadata).with("method", "POST")
|
183
185
|
end
|
@@ -199,7 +201,8 @@ if DependencyHelper.grape_present?
|
|
199
201
|
end
|
200
202
|
|
201
203
|
it "sets namespaced path" do
|
202
|
-
expect(transaction).to receive(:set_action_if_nil)
|
204
|
+
expect(transaction).to receive(:set_action_if_nil)
|
205
|
+
.with("POST::GrapeExample::Api#/v1/beta/ping")
|
203
206
|
expect(transaction).to receive(:set_metadata).with("path", "/v1/beta/ping")
|
204
207
|
expect(transaction).to receive(:set_metadata).with("method", "POST")
|
205
208
|
end
|
@@ -220,7 +223,8 @@ if DependencyHelper.grape_present?
|
|
220
223
|
end
|
221
224
|
|
222
225
|
it "sets namespaced path" do
|
223
|
-
expect(transaction).to receive(:set_action_if_nil)
|
226
|
+
expect(transaction).to receive(:set_action_if_nil)
|
227
|
+
.with("POST::GrapeExample::Api#/v1/beta/ping")
|
224
228
|
expect(transaction).to receive(:set_metadata).with("path", "/v1/beta/ping")
|
225
229
|
expect(transaction).to receive(:set_metadata).with("method", "POST")
|
226
230
|
end
|
@@ -20,14 +20,16 @@ if DependencyHelper.hanami2_present?
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "prepends the integration to Hanami" do
|
23
|
-
expect(::Hanami::Action).to receive(:
|
23
|
+
expect(::Hanami::Action).to receive(:prepend)
|
24
|
+
.with(Appsignal::Integrations::HanamiIntegration)
|
24
25
|
end
|
25
26
|
|
26
27
|
context "when not active" do
|
27
28
|
before { allow(Appsignal).to receive(:active?).and_return(false) }
|
28
29
|
|
29
30
|
it "does not prepend the integration" do
|
30
|
-
expect(::Hanami::Action).to_not receive(:
|
31
|
+
expect(::Hanami::Action).to_not receive(:prepend)
|
32
|
+
.with(Appsignal::Integrations::HanamiIntegration)
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
@@ -71,17 +73,22 @@ if DependencyHelper.hanami2_present?
|
|
71
73
|
end
|
72
74
|
|
73
75
|
it "sets the action name" do
|
74
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_action_if_nil)
|
76
|
+
expect_any_instance_of(Appsignal::Transaction).to receive(:set_action_if_nil)
|
77
|
+
.with("HanamiApp::Actions::Books::Index")
|
75
78
|
end
|
76
79
|
|
77
80
|
it "sets the metadata" do
|
78
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
79
|
-
|
80
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
81
|
+
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
82
|
+
.with("status", "200")
|
83
|
+
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
84
|
+
.with("path", "/books")
|
85
|
+
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
86
|
+
.with("method", "GET")
|
81
87
|
end
|
82
88
|
|
83
89
|
it "sets the queue start" do
|
84
|
-
expect_any_instance_of(Appsignal::Transaction)
|
90
|
+
expect_any_instance_of(Appsignal::Transaction)
|
91
|
+
.to receive(:set_http_or_background_queue_start)
|
85
92
|
end
|
86
93
|
|
87
94
|
context "with error", :error => true do
|
@@ -92,7 +99,8 @@ if DependencyHelper.hanami2_present?
|
|
92
99
|
end
|
93
100
|
|
94
101
|
it "sets the status to 500" do
|
95
|
-
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
102
|
+
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata)
|
103
|
+
.with("status", "500")
|
96
104
|
expect_any_instance_of(Appsignal::Transaction).to receive(:set_metadata).twice
|
97
105
|
end
|
98
106
|
end
|
@@ -19,11 +19,8 @@ describe Appsignal::Hooks::MongoMonitorSubscriber do
|
|
19
19
|
it "should sanitize command" do
|
20
20
|
# TODO: additional curly brackets required for issue
|
21
21
|
# https://github.com/rspec/rspec-mocks/issues/1460
|
22
|
-
# rubocop:disable Style/BracesAroundHashParameters
|
23
22
|
expect(Appsignal::EventFormatter::MongoRubyDriver::QueryFormatter)
|
24
23
|
.to receive(:format).with("find", { "foo" => "bar" })
|
25
|
-
# rubocop:enable Style/BracesAroundHashParameters
|
26
|
-
|
27
24
|
subscriber.started(event)
|
28
25
|
end
|
29
26
|
|
@@ -107,7 +104,8 @@ describe Appsignal::Hooks::MongoMonitorSubscriber do
|
|
107
104
|
|
108
105
|
context "without transaction" do
|
109
106
|
before do
|
110
|
-
allow(Appsignal::Transaction).to receive(:current)
|
107
|
+
allow(Appsignal::Transaction).to receive(:current)
|
108
|
+
.and_return(Appsignal::Transaction::NilTransaction.new)
|
111
109
|
end
|
112
110
|
|
113
111
|
it "should not attempt to start an event" do
|
@@ -25,7 +25,8 @@ describe Object do
|
|
25
25
|
let(:transaction) { http_request_transaction }
|
26
26
|
before do
|
27
27
|
Appsignal.config = project_fixture_config
|
28
|
-
expect(Appsignal::Transaction).to receive(:current)
|
28
|
+
expect(Appsignal::Transaction).to receive(:current)
|
29
|
+
.at_least(:once).and_return(transaction)
|
29
30
|
expect(Appsignal.active?).to be_truthy
|
30
31
|
end
|
31
32
|
after { Appsignal.config = nil }
|
@@ -43,9 +44,11 @@ describe Object do
|
|
43
44
|
end
|
44
45
|
appsignal_instrument_method :positional_arguments_splat
|
45
46
|
|
47
|
+
# rubocop:disable Naming/MethodParameterName
|
46
48
|
def keyword_arguments(a: nil, b: nil)
|
47
49
|
[a, b]
|
48
50
|
end
|
51
|
+
# rubocop:enable Naming/MethodParameterName
|
49
52
|
appsignal_instrument_method :keyword_arguments
|
50
53
|
|
51
54
|
def keyword_arguments_splat(**kwargs)
|
@@ -213,9 +216,11 @@ describe Object do
|
|
213
216
|
end
|
214
217
|
appsignal_instrument_class_method :positional_arguments_splat
|
215
218
|
|
219
|
+
# rubocop:disable Naming/MethodParameterName
|
216
220
|
def self.keyword_arguments(a: nil, b: nil)
|
217
221
|
[a, b]
|
218
222
|
end
|
223
|
+
# rubocop:enable Naming/MethodParameterName
|
219
224
|
appsignal_instrument_class_method :keyword_arguments
|
220
225
|
|
221
226
|
def self.keyword_arguments_splat(**kwargs)
|
@@ -283,7 +283,8 @@ if DependencyHelper.padrino_present?
|
|
283
283
|
|
284
284
|
it "sets the action with the app name, controller name and action name" do
|
285
285
|
expect_a_transaction_to_be_created
|
286
|
-
expect(transaction).to receive(:set_action_if_nil)
|
286
|
+
expect(transaction).to receive(:set_action_if_nil)
|
287
|
+
.with("PadrinoTestApp:my_controller#index")
|
287
288
|
end
|
288
289
|
end
|
289
290
|
|
@@ -295,7 +296,8 @@ if DependencyHelper.padrino_present?
|
|
295
296
|
|
296
297
|
it "sets the action with the app name, controller name and action path" do
|
297
298
|
expect_a_transaction_to_be_created
|
298
|
-
expect(transaction).to receive(:set_action_if_nil)
|
299
|
+
expect(transaction).to receive(:set_action_if_nil)
|
300
|
+
.with("PadrinoTestApp:/my_controller#index")
|
299
301
|
end
|
300
302
|
end
|
301
303
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
if DependencyHelper.rails_present?
|
2
|
+
require "action_mailer"
|
3
|
+
|
2
4
|
describe Appsignal::Integrations::Railtie do
|
3
5
|
context "after initializing the app" do
|
4
6
|
it "should call initialize_appsignal" do
|
@@ -10,11 +12,7 @@ if DependencyHelper.rails_present?
|
|
10
12
|
end
|
11
13
|
|
12
14
|
describe "#initialize_appsignal" do
|
13
|
-
let(:app) { MyApp::Application }
|
14
|
-
before do
|
15
|
-
allow(app.middleware).to receive(:insert_before)
|
16
|
-
allow(app.middleware).to receive(:insert_after)
|
17
|
-
end
|
15
|
+
let(:app) { MyApp::Application.new }
|
18
16
|
|
19
17
|
describe ".logger" do
|
20
18
|
before { Appsignal::Integrations::Railtie.initialize_appsignal(app) }
|
@@ -58,6 +56,52 @@ if DependencyHelper.rails_present?
|
|
58
56
|
expect(config.env).to eq "env_test"
|
59
57
|
end
|
60
58
|
end
|
59
|
+
|
60
|
+
if Rails.respond_to?(:error)
|
61
|
+
context "when Rails listens to `error`" do
|
62
|
+
class ErrorReporterMock
|
63
|
+
attr_reader :subscribers
|
64
|
+
|
65
|
+
def initialize
|
66
|
+
@subscribers = []
|
67
|
+
end
|
68
|
+
|
69
|
+
def subscribe(subscriber)
|
70
|
+
@subscribers << subscriber
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
let(:error_reporter) { ErrorReporterMock.new }
|
75
|
+
before do
|
76
|
+
allow(Rails).to receive(:error).and_return(error_reporter)
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when enable_rails_error_reporter is enabled" do
|
80
|
+
it "subscribes to the error reporter" do
|
81
|
+
Appsignal::Integrations::Railtie.initialize_appsignal(app)
|
82
|
+
|
83
|
+
expect(error_reporter.subscribers)
|
84
|
+
.to eq([Appsignal::Integrations::RailsErrorReporterSubscriber])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when enable_rails_error_reporter is disabled" do
|
89
|
+
it "does not subscribe to the error reporter" do
|
90
|
+
ENV["APPSIGNAL_ENABLE_RAILS_ERROR_REPORTER"] = "false"
|
91
|
+
Appsignal::Integrations::Railtie.initialize_appsignal(app)
|
92
|
+
|
93
|
+
expect(error_reporter.subscribers)
|
94
|
+
.to_not eq([Appsignal::Integrations::RailsErrorReporterSubscriber])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
else
|
99
|
+
context "when Rails does not listen to `error`" do
|
100
|
+
it "does not error trying to subscribe to the error reporter" do
|
101
|
+
Appsignal::Integrations::Railtie.initialize_appsignal(app)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
61
105
|
end
|
62
106
|
|
63
107
|
describe ".initial_config" do
|
@@ -75,9 +119,172 @@ if DependencyHelper.rails_present?
|
|
75
119
|
ActionDispatch::DebugExceptions,
|
76
120
|
Appsignal::Rack::RailsInstrumentation
|
77
121
|
)
|
122
|
+
Appsignal::Integrations::Railtie.initialize_appsignal(app)
|
78
123
|
end
|
124
|
+
end
|
125
|
+
|
126
|
+
if Rails.respond_to?(:error)
|
127
|
+
describe "Rails error reporter" do
|
128
|
+
before do
|
129
|
+
Appsignal::Integrations::Railtie.initialize_appsignal(app)
|
130
|
+
start_agent
|
131
|
+
end
|
132
|
+
around { |example| keep_transactions { example.run } }
|
133
|
+
|
134
|
+
context "when error is not handled (reraises the error)" do
|
135
|
+
it "does nothing" do
|
136
|
+
expect do
|
137
|
+
Rails.error.record { raise ExampleStandardError }
|
138
|
+
end.to raise_error(ExampleStandardError)
|
139
|
+
|
140
|
+
expect(created_transactions).to be_empty
|
141
|
+
end
|
142
|
+
end
|
79
143
|
|
80
|
-
|
144
|
+
context "when error is handled (not reraised)" do
|
145
|
+
context "when a transaction is active" do
|
146
|
+
it "duplicates the transaction namespace, action and tags" do
|
147
|
+
current_transaction = http_request_transaction
|
148
|
+
current_transaction.set_namespace "custom"
|
149
|
+
current_transaction.set_action "CustomAction"
|
150
|
+
current_transaction.set_tags(
|
151
|
+
:duplicated_tag => "duplicated value"
|
152
|
+
)
|
153
|
+
|
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
|
+
}
|
172
|
+
)
|
173
|
+
)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it "overwrites duplicated tags with tags from context" do
|
178
|
+
current_transaction = http_request_transaction
|
179
|
+
current_transaction.set_tags(:tag1 => "duplicated value")
|
180
|
+
|
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
|
+
}
|
194
|
+
)
|
195
|
+
)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
it "overwrites duplicated namespace and action with custom from context" do
|
200
|
+
current_transaction = http_request_transaction
|
201
|
+
current_transaction.set_namespace "custom"
|
202
|
+
current_transaction.set_action "CustomAction"
|
203
|
+
|
204
|
+
with_current_transaction current_transaction do
|
205
|
+
given_context = {
|
206
|
+
:appsignal => { :namespace => "context", :action => "ContextAction" }
|
207
|
+
}
|
208
|
+
Rails.error.handle(:context => given_context) { raise ExampleStandardError }
|
209
|
+
|
210
|
+
transaction = last_transaction
|
211
|
+
transaction_hash = transaction.to_h
|
212
|
+
expect(transaction_hash).to include(
|
213
|
+
"namespace" => "context",
|
214
|
+
"action" => "ContextAction"
|
215
|
+
)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context "when no transaction is active" do
|
221
|
+
class ExampleRailsControllerMock
|
222
|
+
def action_name
|
223
|
+
"index"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
class ExampleRailsJobMock
|
228
|
+
end
|
229
|
+
|
230
|
+
class ExampleRailsMailerMock < ActionMailer::MailDeliveryJob
|
231
|
+
def arguments
|
232
|
+
["ExampleRailsMailerMock", "send_mail"]
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
before do
|
237
|
+
clear_current_transaction!
|
238
|
+
end
|
239
|
+
|
240
|
+
it "fetches the action from the controller in the context" do
|
241
|
+
# The controller key is set by Rails when raised in a controller
|
242
|
+
given_context = { :controller => ExampleRailsControllerMock.new }
|
243
|
+
Rails.error.handle(:context => given_context) { raise ExampleStandardError }
|
244
|
+
|
245
|
+
transaction = last_transaction
|
246
|
+
transaction_hash = transaction.to_h
|
247
|
+
expect(transaction_hash).to include(
|
248
|
+
"action" => "ExampleRailsControllerMock#index"
|
249
|
+
)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "sets no action if no execution context is present" do
|
253
|
+
# The controller key is set by Rails when raised in a controller
|
254
|
+
Rails.error.handle { raise ExampleStandardError }
|
255
|
+
|
256
|
+
transaction = last_transaction
|
257
|
+
transaction_hash = transaction.to_h
|
258
|
+
expect(transaction_hash).to include(
|
259
|
+
"action" => nil
|
260
|
+
)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
it "sets the error context as tags" do
|
265
|
+
given_context = {
|
266
|
+
:controller => ExampleRailsControllerMock.new, # Not set as tag
|
267
|
+
:job => ExampleRailsJobMock.new, # Not set as tag
|
268
|
+
:appsignal => { :something => "not used" }, # Not set as tag
|
269
|
+
:tag1 => "value1",
|
270
|
+
:tag2 => "value2"
|
271
|
+
}
|
272
|
+
Rails.error.handle(:context => given_context) { raise ExampleStandardError }
|
273
|
+
|
274
|
+
transaction = last_transaction
|
275
|
+
transaction_hash = transaction.to_h
|
276
|
+
expect(transaction_hash).to include(
|
277
|
+
"sample_data" => hash_including(
|
278
|
+
"tags" => {
|
279
|
+
"tag1" => "value1",
|
280
|
+
"tag2" => "value2",
|
281
|
+
"severity" => "warning"
|
282
|
+
}
|
283
|
+
)
|
284
|
+
)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
81
288
|
end
|
82
289
|
end
|
83
290
|
end
|
@@ -10,11 +10,9 @@ describe Appsignal::Integrations::SidekiqErrorHandler do
|
|
10
10
|
|
11
11
|
context "without a current transction" do
|
12
12
|
let(:exception) do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
error
|
17
|
-
end
|
13
|
+
raise ExampleStandardError, "uh oh"
|
14
|
+
rescue => error
|
15
|
+
error
|
18
16
|
end
|
19
17
|
let(:job_context) do
|
20
18
|
{
|
@@ -74,14 +72,14 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
|
|
74
72
|
let(:jid) { "b4a577edbccf1d805744efa9" }
|
75
73
|
let(:item) do
|
76
74
|
{
|
77
|
-
"jid"
|
78
|
-
"class"
|
75
|
+
"jid" => jid,
|
76
|
+
"class" => job_class,
|
79
77
|
"retry_count" => 0,
|
80
|
-
"queue"
|
81
|
-
"created_at"
|
78
|
+
"queue" => "default",
|
79
|
+
"created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
|
82
80
|
"enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
|
83
|
-
"args"
|
84
|
-
"extra"
|
81
|
+
"args" => given_args,
|
82
|
+
"extra" => "data"
|
85
83
|
}
|
86
84
|
end
|
87
85
|
let(:plugin) { Appsignal::Integrations::SidekiqMiddleware.new }
|
@@ -230,13 +228,10 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
|
|
230
228
|
it "creates a transaction and adds the error" do
|
231
229
|
# TODO: additional curly brackets required for issue
|
232
230
|
# https://github.com/rspec/rspec-mocks/issues/1460
|
233
|
-
# rubocop:disable Style/BracesAroundHashParameters
|
234
231
|
expect(Appsignal).to receive(:increment_counter)
|
235
232
|
.with("sidekiq_queue_job_count", 1, { :queue => "default", :status => :failed })
|
236
233
|
expect(Appsignal).to receive(:increment_counter)
|
237
234
|
.with("sidekiq_queue_job_count", 1, { :queue => "default", :status => :processed })
|
238
|
-
# rubocop:enable Style/BracesAroundHashParameters
|
239
|
-
|
240
235
|
expect do
|
241
236
|
perform_job { raise error, "uh oh" }
|
242
237
|
end.to raise_error(error)
|
@@ -269,15 +264,40 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
|
|
269
264
|
end
|
270
265
|
end
|
271
266
|
|
267
|
+
if DependencyHelper.rails7_present?
|
268
|
+
context "with Rails error reporter" do
|
269
|
+
it "reports the worker name as the action, copies the namespace and tags" do
|
270
|
+
Appsignal::Integrations::Railtie.initialize_appsignal(MyApp::Application.new)
|
271
|
+
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"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
expect(created_transactions.count).to eq(2)
|
280
|
+
expected_transaction = {
|
281
|
+
"namespace" => "background_job",
|
282
|
+
"action" => "TestClass#perform",
|
283
|
+
"sample_data" => hash_including(
|
284
|
+
"tags" => hash_including("test_tag" => "value")
|
285
|
+
)
|
286
|
+
}
|
287
|
+
sidekiq_transaction = created_transactions.first.to_h
|
288
|
+
error_reporter_transaction = created_transactions.last.to_h
|
289
|
+
expect(sidekiq_transaction).to include(expected_transaction)
|
290
|
+
expect(error_reporter_transaction).to include(expected_transaction)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
272
295
|
context "without an error" do
|
273
296
|
it "creates a transaction with events" do
|
274
297
|
# TODO: additional curly brackets required for issue
|
275
298
|
# https://github.com/rspec/rspec-mocks/issues/1460
|
276
|
-
# rubocop:disable Style/BracesAroundHashParameters
|
277
299
|
expect(Appsignal).to receive(:increment_counter)
|
278
300
|
.with("sidekiq_queue_job_count", 1, { :queue => "default", :status => :processed })
|
279
|
-
# rubocop:enable Style/BracesAroundHashParameters
|
280
|
-
|
281
301
|
perform_job
|
282
302
|
|
283
303
|
transaction_hash = transaction.to_h
|
@@ -309,18 +329,14 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
|
|
309
329
|
|
310
330
|
def perform_job
|
311
331
|
Timecop.freeze(Time.parse("2001-01-01 10:01:00UTC")) do
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
yield if block_given?
|
316
|
-
end
|
317
|
-
rescue Exception => exception # rubocop:disable Lint/RescueException
|
318
|
-
raise exception
|
319
|
-
ensure
|
320
|
-
if exception
|
321
|
-
Appsignal::Integrations::SidekiqErrorHandler.new.call(exception, :job => item)
|
322
|
-
end
|
332
|
+
exception = nil
|
333
|
+
plugin.call(worker, item, queue) do
|
334
|
+
yield if block_given?
|
323
335
|
end
|
336
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
337
|
+
raise exception
|
338
|
+
ensure
|
339
|
+
Appsignal::Integrations::SidekiqErrorHandler.new.call(exception, :job => item) if exception
|
324
340
|
end
|
325
341
|
end
|
326
342
|
|
@@ -516,7 +532,8 @@ if DependencyHelper.active_job_present?
|
|
516
532
|
expect(transaction_hash).to include(
|
517
533
|
"action" => "ActionMailerSidekiqTestJob#welcome",
|
518
534
|
"sample_data" => hash_including(
|
519
|
-
"params" => ["ActionMailerSidekiqTestJob", "welcome",
|
535
|
+
"params" => ["ActionMailerSidekiqTestJob", "welcome",
|
536
|
+
"deliver_now"] + expected_wrapped_args
|
520
537
|
)
|
521
538
|
)
|
522
539
|
end
|
@@ -524,18 +541,14 @@ if DependencyHelper.active_job_present?
|
|
524
541
|
|
525
542
|
def perform_sidekiq
|
526
543
|
Timecop.freeze(time) do
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
if exception
|
536
|
-
Appsignal::Integrations::SidekiqErrorHandler.new.call(exception, {})
|
537
|
-
end
|
538
|
-
end
|
544
|
+
yield
|
545
|
+
# Combined with Sidekiq::Testing.fake! and drain_all we get a
|
546
|
+
# enqueue_at in the job data.
|
547
|
+
Sidekiq::Worker.drain_all
|
548
|
+
rescue Exception => exception # rubocop:disable Lint/RescueException
|
549
|
+
raise exception
|
550
|
+
ensure
|
551
|
+
Appsignal::Integrations::SidekiqErrorHandler.new.call(exception, {}) if exception
|
539
552
|
end
|
540
553
|
end
|
541
554
|
|
@@ -60,13 +60,31 @@ describe Appsignal::Logger do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
it "should log with a level, message and group" do
|
63
|
-
expect(Appsignal::Extension).to receive(:log)
|
64
|
-
|
63
|
+
expect(Appsignal::Extension).to receive(:log).with(
|
64
|
+
"other_group",
|
65
|
+
3,
|
66
|
+
0,
|
67
|
+
"formatted: 'Log message'",
|
68
|
+
instance_of(Appsignal::Extension::Data)
|
69
|
+
)
|
65
70
|
logger.add(::Logger::INFO, "Log message", "other_group")
|
66
71
|
end
|
67
72
|
end
|
68
73
|
end
|
69
74
|
|
75
|
+
describe "#silence" do
|
76
|
+
it "calls the given block" do
|
77
|
+
num = 1
|
78
|
+
|
79
|
+
logger.silence do
|
80
|
+
num += 1
|
81
|
+
end
|
82
|
+
|
83
|
+
expect(num).to eq(2)
|
84
|
+
expect(Appsignal::Extension).not_to receive(:log)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
70
88
|
[
|
71
89
|
["debug", 2, ::Logger::INFO],
|
72
90
|
["info", 3, ::Logger::WARN],
|
@@ -76,11 +94,9 @@ describe Appsignal::Logger do
|
|
76
94
|
].each do |method|
|
77
95
|
describe "##{method[0]}" do
|
78
96
|
it "should log with a message" do
|
79
|
-
# rubocop:disable Style/BracesAroundHashParameters
|
80
97
|
expect(Appsignal::Utils::Data).to receive(:generate)
|
81
98
|
.with({ :attribute => "value" })
|
82
99
|
.and_call_original
|
83
|
-
# rubocop:enable Style/BracesAroundHashParameters
|
84
100
|
expect(Appsignal::Extension).to receive(:log)
|
85
101
|
.with("group", method[1], 0, "Log message", instance_of(Appsignal::Extension::Data))
|
86
102
|
|
@@ -41,8 +41,8 @@ describe Appsignal::Marker do
|
|
41
41
|
run
|
42
42
|
expect(output).to include \
|
43
43
|
"Notifying AppSignal of deploy with: revision: 503ce0923ed177a3ce000005, user: batman",
|
44
|
-
"Something went wrong while trying to notify AppSignal: 500 at "\
|
45
|
-
|
44
|
+
"Something went wrong while trying to notify AppSignal: 500 at " \
|
45
|
+
"#{config[:endpoint]}/1/markers"
|
46
46
|
expect(output).to_not include \
|
47
47
|
"AppSignal has been notified of this deploy!"
|
48
48
|
end
|
@@ -133,7 +133,7 @@ describe Appsignal::Minutely do
|
|
133
133
|
"oh no initialize!"
|
134
134
|
)
|
135
135
|
# Start of the error backtrace as debug log
|
136
|
-
expect(log).to contains_log :debug, File.expand_path("
|
136
|
+
expect(log).to contains_log :debug, File.expand_path("../../..", __dir__)
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
@@ -166,7 +166,7 @@ describe Appsignal::Minutely do
|
|
166
166
|
expect(log).to contains_log(:debug, "Gathering minutely metrics with 'my_probe' probe")
|
167
167
|
expect(log).to contains_log(:debug, "Gathering minutely metrics with 'broken_probe' probe")
|
168
168
|
expect(log).to contains_log(:error, "Error in minutely probe 'broken_probe': oh no!")
|
169
|
-
gem_path = File.expand_path("
|
169
|
+
gem_path = File.expand_path("../../..", __dir__) # Start of backtrace
|
170
170
|
expect(log).to contains_log(:debug, gem_path)
|
171
171
|
end
|
172
172
|
end
|
@@ -191,7 +191,7 @@ describe Appsignal::Minutely do
|
|
191
191
|
# Fetch old thread
|
192
192
|
thread = Appsignal::Minutely.instance_variable_get(:@thread)
|
193
193
|
Appsignal::Minutely.start
|
194
|
-
thread
|
194
|
+
thread&.join # Wait for old thread to exit
|
195
195
|
end.to_not(change { alive_thread_counter.call })
|
196
196
|
end
|
197
197
|
end
|