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
@@ -4,36 +4,84 @@ describe Appsignal::Probes::GvlProbe do
|
|
4
4
|
|
5
5
|
let(:hostname) { "some-host" }
|
6
6
|
|
7
|
+
def gauges_for(metric)
|
8
|
+
gauges = appsignal_mock.gauges.select do |gauge|
|
9
|
+
gauge[0] == metric
|
10
|
+
end
|
11
|
+
|
12
|
+
gauges.map do |gauge|
|
13
|
+
gauge.drop(1)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
7
17
|
after(:each) { FakeGVLTools.reset }
|
8
18
|
|
9
|
-
|
10
|
-
|
19
|
+
it "gauges the global timer delta" do
|
20
|
+
FakeGVLTools::GlobalTimer.monotonic_time = 100_000_000
|
21
|
+
probe.call
|
22
|
+
|
23
|
+
expect(gauges_for("gvl_global_timer")).to be_empty
|
24
|
+
|
25
|
+
FakeGVLTools::GlobalTimer.monotonic_time = 300_000_000
|
26
|
+
probe.call
|
11
27
|
|
12
|
-
|
13
|
-
|
28
|
+
expect(gauges_for("gvl_global_timer")).to eq [
|
29
|
+
[200, { :hostname => hostname }]
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when the delta is negative" do
|
34
|
+
it "does not gauge the global timer delta" do
|
35
|
+
FakeGVLTools::GlobalTimer.monotonic_time = 300_000_000
|
14
36
|
probe.call
|
15
37
|
|
16
|
-
expect(
|
38
|
+
expect(gauges_for("gvl_global_timer")).to be_empty
|
39
|
+
|
40
|
+
FakeGVLTools::GlobalTimer.monotonic_time = 0
|
41
|
+
probe.call
|
42
|
+
|
43
|
+
expect(gauges_for("gvl_global_timer")).to be_empty
|
44
|
+
end
|
45
|
+
end
|
17
46
|
|
47
|
+
context "when the delta is zero" do
|
48
|
+
it "does not gauge the global timer delta" do
|
18
49
|
FakeGVLTools::GlobalTimer.monotonic_time = 300_000_000
|
19
50
|
probe.call
|
20
51
|
|
21
|
-
expect(
|
22
|
-
|
23
|
-
|
52
|
+
expect(gauges_for("gvl_global_timer")).to be_empty
|
53
|
+
|
54
|
+
probe.call
|
55
|
+
|
56
|
+
expect(gauges_for("gvl_global_timer")).to be_empty
|
24
57
|
end
|
25
58
|
end
|
26
59
|
|
27
|
-
context "
|
28
|
-
before(:each)
|
60
|
+
context "when the waiting threads count is enabled" do
|
61
|
+
before(:each) do
|
62
|
+
FakeGVLTools::WaitingThreads.enabled = true
|
63
|
+
end
|
29
64
|
|
30
65
|
it "gauges the waiting threads count" do
|
31
66
|
FakeGVLTools::WaitingThreads.count = 3
|
32
67
|
probe.call
|
33
68
|
|
34
|
-
expect(
|
35
|
-
[
|
69
|
+
expect(gauges_for("gvl_waiting_threads")).to eq [
|
70
|
+
[3, { :hostname => hostname }]
|
36
71
|
]
|
37
72
|
end
|
38
73
|
end
|
74
|
+
|
75
|
+
context "when the waiting threads count is disabled" do
|
76
|
+
before(:each) do
|
77
|
+
FakeGVLTools::WaitingThreads.enabled = false
|
78
|
+
end
|
79
|
+
|
80
|
+
it "does not gauge the waiting threads count" do
|
81
|
+
FakeGVLTools::WaitingThreads.count = 3
|
82
|
+
probe.call
|
83
|
+
|
84
|
+
expect(gauges_for("gvl_waiting_threads")).to be_empty
|
85
|
+
end
|
86
|
+
end
|
39
87
|
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
describe Appsignal::Probes::MriProbe do
|
2
2
|
let(:appsignal_mock) { AppsignalMock.new(:hostname => hostname) }
|
3
3
|
let(:gc_profiler_mock) { instance_double("Appsignal::GarbageCollectionProfiler") }
|
4
|
-
let(:probe)
|
4
|
+
let(:probe) do
|
5
|
+
described_class.new(:appsignal => appsignal_mock, :gc_profiler => gc_profiler_mock)
|
6
|
+
end
|
5
7
|
|
6
8
|
describe ".dependencies_present?" do
|
7
|
-
if DependencyHelper.running_jruby?
|
9
|
+
if DependencyHelper.running_jruby?
|
8
10
|
it "should not be present" do
|
9
11
|
expect(described_class.dependencies_present?).to be_falsy
|
10
12
|
end
|
@@ -15,7 +17,7 @@ describe Appsignal::Probes::MriProbe do
|
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
|
-
unless DependencyHelper.running_jruby?
|
20
|
+
unless DependencyHelper.running_jruby?
|
19
21
|
describe "#call" do
|
20
22
|
let(:hostname) { nil }
|
21
23
|
before do
|
@@ -126,7 +128,8 @@ describe Appsignal::Probes::MriProbe do
|
|
126
128
|
|
127
129
|
it "reports custom hostname tag value" do
|
128
130
|
probe.call
|
129
|
-
expect_gauge_value("heap_slots",
|
131
|
+
expect_gauge_value("heap_slots",
|
132
|
+
:tags => { :metric => :heap_live, :hostname => hostname })
|
130
133
|
end
|
131
134
|
end
|
132
135
|
end
|
@@ -42,7 +42,8 @@ describe Appsignal::Rack::GenericInstrumentation do
|
|
42
42
|
kind_of(String),
|
43
43
|
Appsignal::Transaction::HTTP_REQUEST,
|
44
44
|
kind_of(Rack::Request)
|
45
|
-
).and_return(double(:set_action_if_nil => nil, :set_http_or_background_queue_start => nil,
|
45
|
+
).and_return(double(:set_action_if_nil => nil, :set_http_or_background_queue_start => nil,
|
46
|
+
:set_metadata => nil))
|
46
47
|
end
|
47
48
|
|
48
49
|
it "should call the app" do
|
@@ -113,7 +113,8 @@ if DependencyHelper.rails_present?
|
|
113
113
|
|
114
114
|
transaction_hash = last_transaction.to_h
|
115
115
|
expect(transaction_hash["metadata"]).to_not have_key("method")
|
116
|
-
expect(log_contents(log)).to contains_log(:error,
|
116
|
+
expect(log_contents(log)).to contains_log(:error,
|
117
|
+
"Unable to report HTTP request method: '")
|
117
118
|
end
|
118
119
|
end
|
119
120
|
|
@@ -110,7 +110,8 @@ if DependencyHelper.sinatra_present?
|
|
110
110
|
Appsignal::Transaction::HTTP_REQUEST,
|
111
111
|
kind_of(Sinatra::Request),
|
112
112
|
kind_of(Hash)
|
113
|
-
).and_return(double(:set_action_if_nil => nil, :set_http_or_background_queue_start => nil,
|
113
|
+
).and_return(double(:set_action_if_nil => nil, :set_http_or_background_queue_start => nil,
|
114
|
+
:set_metadata => nil))
|
114
115
|
end
|
115
116
|
|
116
117
|
it "should call the app" do
|
@@ -158,7 +159,8 @@ if DependencyHelper.sinatra_present?
|
|
158
159
|
|
159
160
|
describe "action name" do
|
160
161
|
it "should set the action" do
|
161
|
-
expect_any_instance_of(Appsignal::Transaction)
|
162
|
+
expect_any_instance_of(Appsignal::Transaction)
|
163
|
+
.to receive(:set_action_if_nil).with("GET /")
|
162
164
|
end
|
163
165
|
|
164
166
|
context "without 'sinatra.route' env" do
|
@@ -173,14 +175,16 @@ if DependencyHelper.sinatra_present?
|
|
173
175
|
before { env["SCRIPT_NAME"] = "/api" }
|
174
176
|
|
175
177
|
it "should call set_action with an application prefix path" do
|
176
|
-
expect_any_instance_of(Appsignal::Transaction)
|
178
|
+
expect_any_instance_of(Appsignal::Transaction)
|
179
|
+
.to receive(:set_action_if_nil).with("GET /api/")
|
177
180
|
end
|
178
181
|
|
179
182
|
context "without 'sinatra.route' env" do
|
180
183
|
let(:env) { { :path => "/", :method => "GET" } }
|
181
184
|
|
182
185
|
it "returns nil" do
|
183
|
-
expect_any_instance_of(Appsignal::Transaction)
|
186
|
+
expect_any_instance_of(Appsignal::Transaction)
|
187
|
+
.to receive(:set_action_if_nil).with(nil)
|
184
188
|
end
|
185
189
|
end
|
186
190
|
end
|
@@ -191,7 +195,8 @@ if DependencyHelper.sinatra_present?
|
|
191
195
|
end
|
192
196
|
|
193
197
|
it "should set the queue start" do
|
194
|
-
expect_any_instance_of(Appsignal::Transaction)
|
198
|
+
expect_any_instance_of(Appsignal::Transaction)
|
199
|
+
.to receive(:set_http_or_background_queue_start)
|
195
200
|
end
|
196
201
|
|
197
202
|
context "with overridden request class and params method" do
|
@@ -4,10 +4,10 @@ describe Appsignal::Rack::StreamingListener do
|
|
4
4
|
let(:headers) { {} }
|
5
5
|
let(:env) do
|
6
6
|
{
|
7
|
-
"rack.input"
|
7
|
+
"rack.input" => StringIO.new,
|
8
8
|
"REQUEST_METHOD" => "GET",
|
9
|
-
"PATH_INFO"
|
10
|
-
"QUERY_STRING"
|
9
|
+
"PATH_INFO" => "/homepage",
|
10
|
+
"QUERY_STRING" => "param=something"
|
11
11
|
}
|
12
12
|
end
|
13
13
|
let(:app) { double(:call => [200, headers, "body"]) }
|
@@ -114,8 +114,10 @@ end
|
|
114
114
|
|
115
115
|
describe Appsignal::StreamWrapper do
|
116
116
|
let(:stream) { double }
|
117
|
-
let(:transaction)
|
118
|
-
|
117
|
+
let(:transaction) do
|
118
|
+
Appsignal::Transaction.create(SecureRandom.uuid, Appsignal::Transaction::HTTP_REQUEST, {})
|
119
|
+
end
|
120
|
+
let(:wrapper) { Appsignal::StreamWrapper.new(stream, transaction) }
|
119
121
|
|
120
122
|
describe "#each" do
|
121
123
|
it "calls the original stream" do
|
@@ -66,8 +66,8 @@ describe Appsignal::Transaction do
|
|
66
66
|
create_transaction("2")
|
67
67
|
expect(log_contents(log)).to contains_log :warn,
|
68
68
|
"Trying to start new transaction with id '2', but a " \
|
69
|
-
|
70
|
-
|
69
|
+
"transaction with id '#{transaction_id}' is already " \
|
70
|
+
"running. Using transaction '#{transaction_id}'."
|
71
71
|
end
|
72
72
|
|
73
73
|
context "with option :force => true" do
|
@@ -741,7 +741,7 @@ describe Appsignal::Transaction do
|
|
741
741
|
it "does not add the error" do
|
742
742
|
expect(Appsignal.logger).to receive(:error).with(
|
743
743
|
"Appsignal::Transaction#set_error: Cannot set error. " \
|
744
|
-
|
744
|
+
"The given value is not an exception: #{error.inspect}"
|
745
745
|
)
|
746
746
|
expect(transaction.ext).to_not receive(:set_error)
|
747
747
|
|
@@ -1083,7 +1083,9 @@ describe Appsignal::Transaction do
|
|
1083
1083
|
|
1084
1084
|
context "with an array" do
|
1085
1085
|
let(:request) do
|
1086
|
-
Appsignal::Transaction::GenericRequest.new(
|
1086
|
+
Appsignal::Transaction::GenericRequest.new(
|
1087
|
+
background_env_with_data(:params => %w[arg1 arg2])
|
1088
|
+
)
|
1087
1089
|
end
|
1088
1090
|
|
1089
1091
|
it { is_expected.to eq %w[arg1 arg2] }
|
@@ -1099,8 +1101,9 @@ describe Appsignal::Transaction do
|
|
1099
1101
|
context "with env" do
|
1100
1102
|
context "with sanitization" do
|
1101
1103
|
let(:request) do
|
1102
|
-
Appsignal::Transaction::GenericRequest.new
|
1104
|
+
Appsignal::Transaction::GenericRequest.new(
|
1103
1105
|
http_request_env_with_data(:params => { :foo => :bar })
|
1106
|
+
)
|
1104
1107
|
end
|
1105
1108
|
|
1106
1109
|
it "should call the params sanitizer" do
|
@@ -1110,8 +1113,9 @@ describe Appsignal::Transaction do
|
|
1110
1113
|
|
1111
1114
|
context "with AppSignal filtering" do
|
1112
1115
|
let(:request) do
|
1113
|
-
Appsignal::Transaction::GenericRequest.new
|
1116
|
+
Appsignal::Transaction::GenericRequest.new(
|
1114
1117
|
http_request_env_with_data(:params => { :foo => :bar, :baz => :bat })
|
1118
|
+
)
|
1115
1119
|
end
|
1116
1120
|
before { Appsignal.config.config_hash[:filter_parameters] = %w[foo] }
|
1117
1121
|
after { Appsignal.config.config_hash[:filter_parameters] = [] }
|
@@ -1233,7 +1237,8 @@ describe Appsignal::Transaction do
|
|
1233
1237
|
true
|
1234
1238
|
end
|
1235
1239
|
end.new
|
1236
|
-
ActionDispatch::Request::Session.create(store,
|
1240
|
+
ActionDispatch::Request::Session.create(store,
|
1241
|
+
ActionDispatch::Request.new("rack.input" => StringIO.new), {})
|
1237
1242
|
end
|
1238
1243
|
before do
|
1239
1244
|
expect(transaction).to respond_to(:request)
|
@@ -1334,12 +1339,14 @@ describe Appsignal::Transaction do
|
|
1334
1339
|
|
1335
1340
|
let(:error) do
|
1336
1341
|
PG::UniqueViolation.new(
|
1337
|
-
"ERROR: duplicate key value violates unique constraint
|
1342
|
+
"ERROR: duplicate key value violates unique constraint " \
|
1343
|
+
"\"index_users_on_email\" DETAIL: Key (email)=(test@test.com) already exists."
|
1338
1344
|
)
|
1339
1345
|
end
|
1340
1346
|
|
1341
1347
|
it "returns a sanizited error message" do
|
1342
|
-
expect(subject).to eq "ERROR: duplicate key value violates unique constraint
|
1348
|
+
expect(subject).to eq "ERROR: duplicate key value violates unique constraint " \
|
1349
|
+
"\"index_users_on_email\" DETAIL: Key (email)=(?) already exists."
|
1343
1350
|
end
|
1344
1351
|
end
|
1345
1352
|
|
@@ -1350,15 +1357,15 @@ describe Appsignal::Transaction do
|
|
1350
1357
|
|
1351
1358
|
let(:error) do
|
1352
1359
|
ActiveRecord::RecordNotUnique.new(
|
1353
|
-
"PG::UniqueViolation: ERROR: duplicate key value violates unique constraint
|
1354
|
-
|
1360
|
+
"PG::UniqueViolation: ERROR: duplicate key value violates unique constraint " \
|
1361
|
+
"\"example_constraint\"\nDETAIL: Key (email)=(foo@example.com) already exists."
|
1355
1362
|
)
|
1356
1363
|
end
|
1357
1364
|
|
1358
1365
|
it "returns a sanizited error message" do
|
1359
1366
|
expect(subject).to eq \
|
1360
|
-
"PG::UniqueViolation: ERROR: duplicate key value violates unique constraint
|
1361
|
-
|
1367
|
+
"PG::UniqueViolation: ERROR: duplicate key value violates unique constraint " \
|
1368
|
+
"\"example_constraint\"\nDETAIL: Key (email)=(?) already exists."
|
1362
1369
|
end
|
1363
1370
|
end
|
1364
1371
|
end
|
@@ -47,6 +47,7 @@ describe Appsignal::Utils::Data do
|
|
47
47
|
|
48
48
|
describe "#to_s" do
|
49
49
|
it "returns a serialized hash" do
|
50
|
+
# rubocop:disable Style/StringConcatenation
|
50
51
|
expect(subject.to_s).to eq %({"":"test",) +
|
51
52
|
%("1":true,) +
|
52
53
|
%("bar":null,) +
|
@@ -59,6 +60,7 @@ describe Appsignal::Utils::Data do
|
|
59
60
|
%("int63":"bigint:#{1 << 63}",) +
|
60
61
|
%("int64":"bigint:#{1 << 64}",) +
|
61
62
|
%("the":"payload"})
|
63
|
+
# rubocop:enable Style/StringConcatenation
|
62
64
|
end
|
63
65
|
end
|
64
66
|
end
|
@@ -73,6 +75,7 @@ describe Appsignal::Utils::Data do
|
|
73
75
|
|
74
76
|
describe "#to_s" do
|
75
77
|
it "returns a serialized array" do
|
78
|
+
# rubocop:disable Style/StringConcatenation, Style/RedundantStringEscape
|
76
79
|
expect(subject.to_s).to eq %([null,) +
|
77
80
|
%(true,) +
|
78
81
|
%(false,) +
|
@@ -84,6 +87,7 @@ describe Appsignal::Utils::Data do
|
|
84
87
|
%("bigint:#{1 << 63}",) +
|
85
88
|
%("bigint:#{1 << 64}",) +
|
86
89
|
%({\"arr\":[1,2,\"three\"],\"foo\":\"bʊr\"}])
|
90
|
+
# rubocop:enable Style/StringConcatenation, Style/RedundantStringEscape
|
87
91
|
end
|
88
92
|
end
|
89
93
|
end
|
@@ -105,7 +109,12 @@ describe Appsignal::Utils::Data do
|
|
105
109
|
|
106
110
|
describe "#to_s" do
|
107
111
|
it "returns a JSON representation in a String" do
|
108
|
-
|
112
|
+
# rubocop:disable Style/StringConcatenation
|
113
|
+
expect(subject.to_s).to eq %({"field_four":{"one":"aa�"},) +
|
114
|
+
%("field_one":"aa",) +
|
115
|
+
%("field_three":["one","aa�"],) +
|
116
|
+
%("field_two":"aa�"})
|
117
|
+
# rubocop:enable Style/StringConcatenation
|
109
118
|
end
|
110
119
|
end
|
111
120
|
end
|
@@ -2,23 +2,23 @@ describe Appsignal::Utils::HashSanitizer do
|
|
2
2
|
let(:file) { uploaded_file }
|
3
3
|
let(:params) do
|
4
4
|
{
|
5
|
-
:text
|
6
|
-
"string"
|
7
|
-
:file
|
8
|
-
:float
|
9
|
-
:bool_true
|
5
|
+
:text => "string",
|
6
|
+
"string" => "string key value",
|
7
|
+
:file => file,
|
8
|
+
:float => 0.0,
|
9
|
+
:bool_true => true,
|
10
10
|
:bool_false => false,
|
11
|
-
:nil
|
12
|
-
:int
|
13
|
-
:int64
|
14
|
-
:hash
|
15
|
-
:nested_text
|
11
|
+
:nil => nil,
|
12
|
+
:int => 1, # Fixnum
|
13
|
+
:int64 => 1 << 64, # Bignum
|
14
|
+
:hash => {
|
15
|
+
:nested_text => "string",
|
16
16
|
:nested_array => [
|
17
17
|
"something",
|
18
18
|
"else",
|
19
19
|
file,
|
20
20
|
{
|
21
|
-
:key
|
21
|
+
:key => "value",
|
22
22
|
:file => file
|
23
23
|
}
|
24
24
|
]
|
@@ -15,7 +15,8 @@ describe Appsignal::Utils::JSON do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
it "returns a JSON string" do
|
18
|
-
is_expected.to eq %({"the":"payload","1":true,"":"test",
|
18
|
+
is_expected.to eq %({"the":"payload","1":true,"":"test",) +
|
19
|
+
%("foo":[1,2,"three"],"bar":null,"baz":{"foo":"bar"}})
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -35,7 +36,8 @@ describe Appsignal::Utils::JSON do
|
|
35
36
|
end
|
36
37
|
|
37
38
|
it "returns a JSON string with invalid UTF-8 content" do
|
38
|
-
is_expected.to eq %({"field_one":"aa","field_two":"aa�",
|
39
|
+
is_expected.to eq %({"field_one":"aa","field_two":"aa�",) +
|
40
|
+
%("field_three":["one","aa�"],"field_four":{"one":"aa�"}})
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
data/spec/lib/appsignal_spec.rb
CHANGED
@@ -22,12 +22,10 @@ describe Appsignal do
|
|
22
22
|
describe ".start" do
|
23
23
|
context "with no config set beforehand" do
|
24
24
|
it "should do nothing when config is not set and there is no valid config in the env" do
|
25
|
-
expect(Appsignal.logger).to receive(:error)
|
26
|
-
"Push API key not set after loading config"
|
27
|
-
).
|
28
|
-
|
29
|
-
"Not starting, no valid config for this environment"
|
30
|
-
).once
|
25
|
+
expect(Appsignal.logger).to receive(:error)
|
26
|
+
.with("Push API key not set after loading config").once
|
27
|
+
expect(Appsignal.logger).to receive(:error)
|
28
|
+
.with("Not starting, no valid config for this environment").once
|
31
29
|
expect(Appsignal::Extension).to_not receive(:start)
|
32
30
|
Appsignal.start
|
33
31
|
end
|
@@ -249,7 +247,7 @@ describe Appsignal do
|
|
249
247
|
end
|
250
248
|
|
251
249
|
it "logs an error" do
|
252
|
-
Appsignal.monitor_transaction("unknown.sidekiq") {}
|
250
|
+
Appsignal.monitor_transaction("unknown.sidekiq") {} # rubocop:disable Lint/EmptyBlock
|
253
251
|
expect(log).to contains_log(
|
254
252
|
:error,
|
255
253
|
"Unrecognized name 'unknown.sidekiq': names must start with either 'perform_job' " \
|
@@ -317,9 +315,8 @@ describe Appsignal do
|
|
317
315
|
describe ".monitor_transaction" do
|
318
316
|
context "with a successful call" do
|
319
317
|
it "should instrument and complete for a background job" do
|
320
|
-
expect(Appsignal).to receive(:instrument)
|
321
|
-
"perform_job.something"
|
322
|
-
).and_yield
|
318
|
+
expect(Appsignal).to receive(:instrument)
|
319
|
+
.with("perform_job.something").and_yield
|
323
320
|
expect(Appsignal::Transaction).to receive(:complete_current!)
|
324
321
|
object = double
|
325
322
|
expect(object).to receive(:some_method).and_return(1)
|
@@ -336,9 +333,8 @@ describe Appsignal do
|
|
336
333
|
end
|
337
334
|
|
338
335
|
it "should instrument and complete for a http request" do
|
339
|
-
expect(Appsignal).to receive(:instrument)
|
340
|
-
"process_action.something"
|
341
|
-
).and_yield
|
336
|
+
expect(Appsignal).to receive(:instrument)
|
337
|
+
.with("process_action.something").and_yield
|
342
338
|
expect(Appsignal::Transaction).to receive(:complete_current!)
|
343
339
|
object = double
|
344
340
|
expect(object).to receive(:some_method)
|
@@ -378,7 +374,7 @@ describe Appsignal do
|
|
378
374
|
end
|
379
375
|
|
380
376
|
it "logs an error" do
|
381
|
-
Appsignal.monitor_transaction("unknown.sidekiq") {}
|
377
|
+
Appsignal.monitor_transaction("unknown.sidekiq") {} # rubocop:disable Lint/EmptyBlock
|
382
378
|
expect(log).to contains_log(
|
383
379
|
:error,
|
384
380
|
"Unrecognized name 'unknown.sidekiq': names must start with either 'perform_job' " \
|
@@ -529,7 +525,8 @@ describe Appsignal do
|
|
529
525
|
|
530
526
|
describe ".set_gauge" do
|
531
527
|
it "should call set_gauge on the extension with a string key and float" do
|
532
|
-
expect(Appsignal::Extension).to receive(:set_gauge)
|
528
|
+
expect(Appsignal::Extension).to receive(:set_gauge)
|
529
|
+
.with("key", 0.1, Appsignal::Extension.data_map_new)
|
533
530
|
Appsignal.set_gauge("key", 0.1)
|
534
531
|
end
|
535
532
|
|
@@ -540,12 +537,14 @@ describe Appsignal do
|
|
540
537
|
end
|
541
538
|
|
542
539
|
it "should call set_gauge on the extension with a symbol key and int" do
|
543
|
-
expect(Appsignal::Extension).to receive(:set_gauge)
|
540
|
+
expect(Appsignal::Extension).to receive(:set_gauge)
|
541
|
+
.with("key", 1.0, Appsignal::Extension.data_map_new)
|
544
542
|
Appsignal.set_gauge(:key, 1)
|
545
543
|
end
|
546
544
|
|
547
545
|
it "should not raise an exception when out of range" do
|
548
|
-
expect(Appsignal::Extension).to receive(:set_gauge).with("key", 10,
|
546
|
+
expect(Appsignal::Extension).to receive(:set_gauge).with("key", 10,
|
547
|
+
Appsignal::Extension.data_map_new).and_raise(RangeError)
|
549
548
|
expect(Appsignal.logger).to receive(:warn).with("Gauge value 10 for key 'key' is too big")
|
550
549
|
expect do
|
551
550
|
Appsignal.set_gauge("key", 10)
|
@@ -565,8 +564,10 @@ describe Appsignal do
|
|
565
564
|
end
|
566
565
|
|
567
566
|
it "should not raise an exception when out of range" do
|
568
|
-
expect(Appsignal::Extension).to receive(:set_host_gauge).with("key",
|
569
|
-
|
567
|
+
expect(Appsignal::Extension).to receive(:set_host_gauge).with("key",
|
568
|
+
10).and_raise(RangeError)
|
569
|
+
expect(Appsignal.logger).to receive(:warn)
|
570
|
+
.with("Host gauge value 10 for key 'key' is too big")
|
570
571
|
expect do
|
571
572
|
Appsignal.set_host_gauge("key", 10)
|
572
573
|
end.to_not raise_error
|
@@ -585,8 +586,10 @@ describe Appsignal do
|
|
585
586
|
end
|
586
587
|
|
587
588
|
it "should not raise an exception when out of range" do
|
588
|
-
expect(Appsignal::Extension).to receive(:set_process_gauge).with("key",
|
589
|
-
|
589
|
+
expect(Appsignal::Extension).to receive(:set_process_gauge).with("key",
|
590
|
+
10).and_raise(RangeError)
|
591
|
+
expect(Appsignal.logger).to receive(:warn)
|
592
|
+
.with("Process gauge value 10 for key 'key' is too big")
|
590
593
|
expect do
|
591
594
|
Appsignal.set_process_gauge("key", 10)
|
592
595
|
end.to_not raise_error
|
@@ -595,7 +598,8 @@ describe Appsignal do
|
|
595
598
|
|
596
599
|
describe ".increment_counter" do
|
597
600
|
it "should call increment_counter on the extension with a string key" do
|
598
|
-
expect(Appsignal::Extension).to receive(:increment_counter)
|
601
|
+
expect(Appsignal::Extension).to receive(:increment_counter)
|
602
|
+
.with("key", 1, Appsignal::Extension.data_map_new)
|
599
603
|
Appsignal.increment_counter("key")
|
600
604
|
end
|
601
605
|
|
@@ -606,18 +610,22 @@ describe Appsignal do
|
|
606
610
|
end
|
607
611
|
|
608
612
|
it "should call increment_counter on the extension with a symbol key" do
|
609
|
-
expect(Appsignal::Extension).to receive(:increment_counter)
|
613
|
+
expect(Appsignal::Extension).to receive(:increment_counter)
|
614
|
+
.with("key", 1, Appsignal::Extension.data_map_new)
|
610
615
|
Appsignal.increment_counter(:key)
|
611
616
|
end
|
612
617
|
|
613
618
|
it "should call increment_counter on the extension with a count" do
|
614
|
-
expect(Appsignal::Extension).to receive(:increment_counter)
|
619
|
+
expect(Appsignal::Extension).to receive(:increment_counter)
|
620
|
+
.with("key", 5, Appsignal::Extension.data_map_new)
|
615
621
|
Appsignal.increment_counter("key", 5)
|
616
622
|
end
|
617
623
|
|
618
624
|
it "should not raise an exception when out of range" do
|
619
|
-
expect(Appsignal::Extension).to receive(:increment_counter)
|
620
|
-
|
625
|
+
expect(Appsignal::Extension).to receive(:increment_counter)
|
626
|
+
.with("key", 10, Appsignal::Extension.data_map_new).and_raise(RangeError)
|
627
|
+
expect(Appsignal.logger).to receive(:warn)
|
628
|
+
.with("Counter value 10 for key 'key' is too big")
|
621
629
|
expect do
|
622
630
|
Appsignal.increment_counter("key", 10)
|
623
631
|
end.to_not raise_error
|
@@ -626,7 +634,8 @@ describe Appsignal do
|
|
626
634
|
|
627
635
|
describe ".add_distribution_value" do
|
628
636
|
it "should call add_distribution_value on the extension with a string key and float" do
|
629
|
-
expect(Appsignal::Extension).to receive(:add_distribution_value)
|
637
|
+
expect(Appsignal::Extension).to receive(:add_distribution_value)
|
638
|
+
.with("key", 0.1, Appsignal::Extension.data_map_new)
|
630
639
|
Appsignal.add_distribution_value("key", 0.1)
|
631
640
|
end
|
632
641
|
|
@@ -637,13 +646,16 @@ describe Appsignal do
|
|
637
646
|
end
|
638
647
|
|
639
648
|
it "should call add_distribution_value on the extension with a symbol key and int" do
|
640
|
-
expect(Appsignal::Extension).to receive(:add_distribution_value)
|
649
|
+
expect(Appsignal::Extension).to receive(:add_distribution_value)
|
650
|
+
.with("key", 1.0, Appsignal::Extension.data_map_new)
|
641
651
|
Appsignal.add_distribution_value(:key, 1)
|
642
652
|
end
|
643
653
|
|
644
654
|
it "should not raise an exception when out of range" do
|
645
|
-
expect(Appsignal::Extension).to receive(:add_distribution_value)
|
646
|
-
|
655
|
+
expect(Appsignal::Extension).to receive(:add_distribution_value)
|
656
|
+
.with("key", 10, Appsignal::Extension.data_map_new).and_raise(RangeError)
|
657
|
+
expect(Appsignal.logger).to receive(:warn)
|
658
|
+
.with("Distribution value 10 for key 'key' is too big")
|
647
659
|
expect do
|
648
660
|
Appsignal.add_distribution_value("key", 10)
|
649
661
|
end.to_not raise_error
|
@@ -1053,14 +1065,16 @@ describe Appsignal do
|
|
1053
1065
|
it_behaves_like "instrument helper" do
|
1054
1066
|
let(:instrumenter) { Appsignal }
|
1055
1067
|
before do
|
1056
|
-
expect(Appsignal::Transaction).to receive(:current).at_least(:once)
|
1068
|
+
expect(Appsignal::Transaction).to receive(:current).at_least(:once)
|
1069
|
+
.and_return(transaction)
|
1057
1070
|
end
|
1058
1071
|
end
|
1059
1072
|
end
|
1060
1073
|
|
1061
1074
|
describe ".instrument_sql" do
|
1062
1075
|
before do
|
1063
|
-
expect(Appsignal::Transaction).to receive(:current).at_least(:once)
|
1076
|
+
expect(Appsignal::Transaction).to receive(:current).at_least(:once)
|
1077
|
+
.and_return(transaction)
|
1064
1078
|
end
|
1065
1079
|
|
1066
1080
|
it "creates an SQL event on the transaction" do
|
@@ -1119,7 +1133,7 @@ describe Appsignal do
|
|
1119
1133
|
|
1120
1134
|
context "when the log path is writable" do
|
1121
1135
|
context "when the log file is writable" do
|
1122
|
-
let(:log_file_contents) { File.
|
1136
|
+
let(:log_file_contents) { File.read(log_file) }
|
1123
1137
|
|
1124
1138
|
before do
|
1125
1139
|
capture_stdout(out_stream) do
|
@@ -1198,8 +1212,8 @@ describe Appsignal do
|
|
1198
1212
|
|
1199
1213
|
it "outputs a warning" do
|
1200
1214
|
expect(output).to include \
|
1201
|
-
"appsignal: Unable to log to '#{log_path}' "\
|
1202
|
-
|
1215
|
+
"appsignal: Unable to log to '#{log_path}' " \
|
1216
|
+
"or the '#{Appsignal::Config.system_tmp_dir}' fallback."
|
1203
1217
|
end
|
1204
1218
|
end
|
1205
1219
|
|