appsignal 3.4.13 → 3.6.1
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.
- checksums.yaml +4 -4
- data/.semaphore/semaphore.yml +180 -14
- data/CHANGELOG.md +164 -0
- data/README.md +2 -0
- data/Rakefile +3 -1
- data/build_matrix.yml +7 -13
- data/ext/Rakefile +8 -1
- data/ext/agent.rb +27 -27
- data/ext/appsignal_extension.c +0 -24
- data/ext/base.rb +4 -1
- data/gemfiles/redis-4.gemfile +5 -0
- data/gemfiles/redis-5.gemfile +6 -0
- data/lib/appsignal/cli/diagnose/paths.rb +33 -10
- data/lib/appsignal/cli/diagnose.rb +6 -1
- data/lib/appsignal/config.rb +19 -5
- data/lib/appsignal/demo.rb +1 -1
- data/lib/appsignal/environment.rb +24 -13
- data/lib/appsignal/event_formatter.rb +1 -1
- data/lib/appsignal/extension/jruby.rb +4 -17
- data/lib/appsignal/extension.rb +1 -1
- data/lib/appsignal/helpers/instrumentation.rb +10 -10
- data/lib/appsignal/helpers/metrics.rb +15 -13
- data/lib/appsignal/hooks/active_job.rb +9 -1
- data/lib/appsignal/hooks/redis.rb +1 -0
- data/lib/appsignal/hooks/redis_client.rb +27 -0
- data/lib/appsignal/hooks.rb +3 -2
- data/lib/appsignal/integrations/hanami.rb +1 -1
- data/lib/appsignal/integrations/padrino.rb +1 -1
- data/lib/appsignal/integrations/railtie.rb +1 -1
- data/lib/appsignal/integrations/redis_client.rb +20 -0
- data/lib/appsignal/integrations/sidekiq.rb +2 -2
- data/lib/appsignal/integrations/sinatra.rb +1 -1
- data/lib/appsignal/logger.rb +2 -0
- data/lib/appsignal/minutely.rb +4 -4
- data/lib/appsignal/probes/gvl.rb +1 -1
- data/lib/appsignal/probes/helpers.rb +1 -1
- data/lib/appsignal/probes/mri.rb +1 -1
- data/lib/appsignal/probes/sidekiq.rb +10 -8
- data/lib/appsignal/rack/body_wrapper.rb +161 -0
- data/lib/appsignal/rack/generic_instrumentation.rb +18 -5
- data/lib/appsignal/rack/rails_instrumentation.rb +17 -5
- data/lib/appsignal/rack/sinatra_instrumentation.rb +17 -5
- data/lib/appsignal/rack/streaming_listener.rb +27 -36
- data/lib/appsignal/span.rb +2 -2
- data/lib/appsignal/transaction.rb +46 -10
- data/lib/appsignal/utils/deprecation_message.rb +2 -2
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +38 -31
- data/resources/cacert.pem +321 -159
- data/spec/lib/appsignal/cli/diagnose/utils_spec.rb +11 -0
- data/spec/lib/appsignal/cli/diagnose_spec.rb +38 -12
- data/spec/lib/appsignal/config_spec.rb +3 -2
- data/spec/lib/appsignal/hooks/activejob_spec.rb +26 -1
- data/spec/lib/appsignal/hooks/redis_client_spec.rb +222 -0
- data/spec/lib/appsignal/hooks/redis_spec.rb +98 -76
- data/spec/lib/appsignal/hooks_spec.rb +4 -4
- data/spec/lib/appsignal/integrations/railtie_spec.rb +2 -2
- data/spec/lib/appsignal/integrations/sidekiq_spec.rb +3 -3
- data/spec/lib/appsignal/integrations/sinatra_spec.rb +2 -2
- data/spec/lib/appsignal/minutely_spec.rb +2 -2
- data/spec/lib/appsignal/probes/sidekiq_spec.rb +29 -6
- data/spec/lib/appsignal/rack/body_wrapper_spec.rb +220 -0
- data/spec/lib/appsignal/rack/generic_instrumentation_spec.rb +3 -2
- data/spec/lib/appsignal/rack/rails_instrumentation_spec.rb +5 -3
- data/spec/lib/appsignal/rack/sinatra_instrumentation_spec.rb +3 -1
- data/spec/lib/appsignal/rack/streaming_listener_spec.rb +9 -53
- data/spec/lib/appsignal/transaction_spec.rb +95 -2
- data/spec/lib/appsignal_spec.rb +62 -60
- data/spec/spec_helper.rb +1 -1
- data/spec/support/fixtures/projects/valid/config/appsignal.yml +3 -3
- data/spec/support/helpers/config_helpers.rb +6 -2
- data/spec/support/helpers/dependency_helper.rb +9 -1
- data/spec/support/helpers/log_helpers.rb +2 -2
- metadata +9 -2
@@ -152,6 +152,7 @@ describe Appsignal::Config do
|
|
152
152
|
it "merges with the default config" do
|
153
153
|
expect(config.config_hash).to eq(
|
154
154
|
:active => true,
|
155
|
+
:activejob_report_errors => "all",
|
155
156
|
:ca_file_path => File.join(resources_dir, "cacert.pem"),
|
156
157
|
:debug => false,
|
157
158
|
:dns_servers => [],
|
@@ -265,7 +266,7 @@ describe Appsignal::Config do
|
|
265
266
|
|
266
267
|
context "with an overriden config file" do
|
267
268
|
let(:config) do
|
268
|
-
project_fixture_config("production", {}, Appsignal.
|
269
|
+
project_fixture_config("production", {}, Appsignal.internal_logger,
|
269
270
|
File.join(project_fixture_path, "config", "appsignal.yml"))
|
270
271
|
end
|
271
272
|
|
@@ -276,7 +277,7 @@ describe Appsignal::Config do
|
|
276
277
|
|
277
278
|
context "with an invalid overriden config file" do
|
278
279
|
let(:config) do
|
279
|
-
project_fixture_config("production", {}, Appsignal.
|
280
|
+
project_fixture_config("production", {}, Appsignal.internal_logger,
|
280
281
|
File.join(project_fixture_path, "config", "missing.yml"))
|
281
282
|
end
|
282
283
|
|
@@ -76,7 +76,7 @@ if DependencyHelper.active_job_present?
|
|
76
76
|
ActiveJob::Base.queue_adapter = :inline
|
77
77
|
|
78
78
|
start_agent
|
79
|
-
Appsignal.
|
79
|
+
Appsignal.internal_logger = test_logger(log)
|
80
80
|
class ActiveJobTestJob < ActiveJob::Base
|
81
81
|
def perform(*_args)
|
82
82
|
end
|
@@ -222,6 +222,31 @@ if DependencyHelper.active_job_present?
|
|
222
222
|
expect(events).to eq(expected_perform_events)
|
223
223
|
end
|
224
224
|
|
225
|
+
context "with activejob_report_errors set to none" do
|
226
|
+
it "does not report the error" do
|
227
|
+
Appsignal.config = project_fixture_config("production")
|
228
|
+
Appsignal.config[:activejob_report_errors] = "none"
|
229
|
+
|
230
|
+
# Other calls we're testing in another test
|
231
|
+
allow(Appsignal).to receive(:increment_counter)
|
232
|
+
tags = { :queue => queue }
|
233
|
+
expect(Appsignal).to receive(:increment_counter)
|
234
|
+
.with("active_job_queue_job_count", 1, tags.merge(:status => :failed))
|
235
|
+
expect(Appsignal).to receive(:increment_counter)
|
236
|
+
.with("active_job_queue_job_count", 1, tags.merge(:status => :processed))
|
237
|
+
|
238
|
+
expect do
|
239
|
+
perform_job(ActiveJobErrorTestJob)
|
240
|
+
end.to raise_error(RuntimeError, "uh oh")
|
241
|
+
|
242
|
+
transaction = last_transaction
|
243
|
+
transaction_hash = transaction.to_h
|
244
|
+
expect(transaction_hash).to include(
|
245
|
+
"error" => nil
|
246
|
+
)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
225
250
|
if DependencyHelper.rails_version >= Gem::Version.new("5.0.0")
|
226
251
|
context "with priority" do
|
227
252
|
before do
|
@@ -0,0 +1,222 @@
|
|
1
|
+
describe Appsignal::Hooks::RedisClientHook do
|
2
|
+
before do
|
3
|
+
Appsignal.config = project_fixture_config
|
4
|
+
end
|
5
|
+
|
6
|
+
if DependencyHelper.redis_client_present?
|
7
|
+
context "with redis_client" do
|
8
|
+
context "with instrumentation enabled" do
|
9
|
+
describe "#dependencies_present?" do
|
10
|
+
subject { described_class.new.dependencies_present? }
|
11
|
+
|
12
|
+
it { is_expected.to be_truthy }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with rest-client gem" do
|
16
|
+
describe "integration" do
|
17
|
+
before do
|
18
|
+
Appsignal.config.config_hash[:instrument_redis] = true
|
19
|
+
end
|
20
|
+
|
21
|
+
context "install" do
|
22
|
+
before do
|
23
|
+
Appsignal::Hooks.load_hooks
|
24
|
+
end
|
25
|
+
|
26
|
+
it "includes the integration for the ruby connection" do
|
27
|
+
# Test if the last included module (prepended module) was our
|
28
|
+
# integration. That's not certain with the assertions below
|
29
|
+
# because we have to overwrite the `process` method for the test.
|
30
|
+
expect(RedisClient::RubyConnection.included_modules.first)
|
31
|
+
.to eql(Appsignal::Integrations::RedisClientIntegration)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "requirements" do
|
36
|
+
it "driver should have the write method" do
|
37
|
+
# Since we stub the driver class below, to make sure that we don't
|
38
|
+
# create a real connection, the test won't fail if the method definition
|
39
|
+
# is changed.
|
40
|
+
method = RedisClient::RubyConnection.instance_method(:write)
|
41
|
+
expect(method.arity).to eql(1)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "instrumentation" do
|
46
|
+
before do
|
47
|
+
start_agent
|
48
|
+
# Stub RedisClient::RubyConnection class so that it doesn't perform an actual
|
49
|
+
# Redis query. This class will be included (prepended) with the
|
50
|
+
# AppSignal Redis integration.
|
51
|
+
stub_const("RedisClient::RubyConnection", Class.new do
|
52
|
+
def initialize(config)
|
53
|
+
@config = config
|
54
|
+
end
|
55
|
+
|
56
|
+
def write(_commands)
|
57
|
+
"stub_write"
|
58
|
+
end
|
59
|
+
end)
|
60
|
+
# Load the integration again for the stubbed RedisClient::RubyConnection class.
|
61
|
+
# Call it directly because {Appsignal::Hooks.load_hooks} keeps
|
62
|
+
# track if it was installed already or not.
|
63
|
+
Appsignal::Hooks::RedisClientHook.new.install
|
64
|
+
end
|
65
|
+
let!(:transaction) do
|
66
|
+
Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
|
67
|
+
end
|
68
|
+
let!(:client_config) { RedisClient::Config.new(:id => "stub_id") }
|
69
|
+
around { |example| keep_transactions { example.run } }
|
70
|
+
|
71
|
+
it "instrument a redis call" do
|
72
|
+
connection = RedisClient::RubyConnection.new client_config
|
73
|
+
expect(connection.write([:get, "key"])).to eql("stub_write")
|
74
|
+
|
75
|
+
transaction_hash = transaction.to_h
|
76
|
+
expect(transaction_hash["events"]).to include(
|
77
|
+
hash_including(
|
78
|
+
"name" => "query.redis",
|
79
|
+
"body" => "get ?",
|
80
|
+
"title" => "stub_id"
|
81
|
+
)
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "instrument a redis script call" do
|
86
|
+
connection = ::RedisClient::RubyConnection.new client_config
|
87
|
+
script = "return redis.call('set',KEYS[1],ARGV[1])"
|
88
|
+
keys = ["foo"]
|
89
|
+
argv = ["bar"]
|
90
|
+
expect(connection.write([:eval, script, keys.size, keys,
|
91
|
+
argv])).to eql("stub_write")
|
92
|
+
|
93
|
+
transaction_hash = transaction.to_h
|
94
|
+
expect(transaction_hash["events"]).to include(
|
95
|
+
hash_including(
|
96
|
+
"name" => "query.redis",
|
97
|
+
"body" => "#{script} ? ?",
|
98
|
+
"title" => "stub_id"
|
99
|
+
)
|
100
|
+
)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
if DependencyHelper.hiredis_client_present?
|
107
|
+
context "with hiredis driver" do
|
108
|
+
describe "integration" do
|
109
|
+
before do
|
110
|
+
Appsignal.config.config_hash[:instrument_redis] = true
|
111
|
+
end
|
112
|
+
|
113
|
+
context "install" do
|
114
|
+
before do
|
115
|
+
Appsignal::Hooks.load_hooks
|
116
|
+
end
|
117
|
+
|
118
|
+
it "includes the integration in the HiredisConnection class" do
|
119
|
+
# Test if the last included module (prepended module) was our
|
120
|
+
# integration. That's not certain with the assertions below
|
121
|
+
# because we have to overwrite the `process` method for the test.
|
122
|
+
expect(RedisClient::HiredisConnection.included_modules.first)
|
123
|
+
.to eql(Appsignal::Integrations::RedisClientIntegration)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "requirements" do
|
128
|
+
it "driver should have the write method" do
|
129
|
+
# Since we stub the driver class below, to make sure that we don't
|
130
|
+
# create a real connection, the test won't fail if the method definition
|
131
|
+
# is changed.
|
132
|
+
method = RedisClient::HiredisConnection.instance_method(:write)
|
133
|
+
expect(method.arity).to eql(1)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "instrumentation" do
|
138
|
+
before do
|
139
|
+
start_agent
|
140
|
+
# Stub RedisClient::HiredisConnection class so that it doesn't perform an actual
|
141
|
+
# Redis query. This class will be included (prepended) with the
|
142
|
+
# AppSignal Redis integration.
|
143
|
+
stub_const("RedisClient::HiredisConnection", Class.new do
|
144
|
+
def initialize(config)
|
145
|
+
@config = config
|
146
|
+
end
|
147
|
+
|
148
|
+
def write(_commands)
|
149
|
+
"stub_write"
|
150
|
+
end
|
151
|
+
end)
|
152
|
+
# Load the integration again for the stubbed RedisClient::HiredisConnection class.
|
153
|
+
# Call it directly because {Appsignal::Hooks.load_hooks} keeps
|
154
|
+
# track if it was installed already or not.
|
155
|
+
Appsignal::Hooks::RedisClientHook.new.install
|
156
|
+
end
|
157
|
+
let!(:transaction) do
|
158
|
+
Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST,
|
159
|
+
"test")
|
160
|
+
end
|
161
|
+
let!(:client_config) { RedisClient::Config.new(:id => "stub_id") }
|
162
|
+
around { |example| keep_transactions { example.run } }
|
163
|
+
|
164
|
+
it "instrument a redis call" do
|
165
|
+
connection = RedisClient::HiredisConnection.new client_config
|
166
|
+
expect(connection.write([:get, "key"])).to eql("stub_write")
|
167
|
+
|
168
|
+
transaction_hash = transaction.to_h
|
169
|
+
expect(transaction_hash["events"]).to include(
|
170
|
+
hash_including(
|
171
|
+
"name" => "query.redis",
|
172
|
+
"body" => "get ?",
|
173
|
+
"title" => "stub_id"
|
174
|
+
)
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
178
|
+
it "instrument a redis script call" do
|
179
|
+
connection = ::RedisClient::HiredisConnection.new client_config
|
180
|
+
script = "return redis.call('set',KEYS[1],ARGV[1])"
|
181
|
+
keys = ["foo"]
|
182
|
+
argv = ["bar"]
|
183
|
+
expect(connection.write([:eval, script, keys.size, keys,
|
184
|
+
argv])).to eql("stub_write")
|
185
|
+
|
186
|
+
transaction_hash = transaction.to_h
|
187
|
+
expect(transaction_hash["events"]).to include(
|
188
|
+
hash_including(
|
189
|
+
"name" => "query.redis",
|
190
|
+
"body" => "#{script} ? ?",
|
191
|
+
"title" => "stub_id"
|
192
|
+
)
|
193
|
+
)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context "with instrumentation disabled" do
|
202
|
+
before do
|
203
|
+
Appsignal.config.config_hash[:instrument_redis] = false
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "#dependencies_present?" do
|
207
|
+
subject { described_class.new.dependencies_present? }
|
208
|
+
|
209
|
+
it { is_expected.to be_falsy }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
else
|
214
|
+
context "without redis" do
|
215
|
+
describe "#dependencies_present?" do
|
216
|
+
subject { described_class.new.dependencies_present? }
|
217
|
+
|
218
|
+
it { is_expected.to be_falsy }
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
@@ -5,100 +5,122 @@ describe Appsignal::Hooks::RedisHook do
|
|
5
5
|
|
6
6
|
if DependencyHelper.redis_present?
|
7
7
|
context "with redis" do
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
if DependencyHelper.redis_client_present?
|
9
|
+
context "with redis-client" do
|
10
|
+
context "with instrumentation enabled" do
|
11
|
+
describe "#dependencies_present?" do
|
12
|
+
subject { described_class.new.dependencies_present? }
|
11
13
|
|
12
|
-
|
14
|
+
it { is_expected.to be_falsey }
|
15
|
+
end
|
16
|
+
end
|
13
17
|
end
|
18
|
+
else
|
19
|
+
context "with instrumentation enabled" do
|
20
|
+
describe "#dependencies_present?" do
|
21
|
+
subject { described_class.new.dependencies_present? }
|
14
22
|
|
15
|
-
|
16
|
-
before do
|
17
|
-
Appsignal.config.config_hash[:instrument_redis] = true
|
23
|
+
it { is_expected.to be_truthy }
|
18
24
|
end
|
19
25
|
|
20
|
-
|
26
|
+
describe "integration" do
|
21
27
|
before do
|
22
|
-
Appsignal
|
28
|
+
Appsignal.config.config_hash[:instrument_redis] = true
|
23
29
|
end
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
expect(Redis::Client.included_modules.first)
|
30
|
-
.to eql(Appsignal::Integrations::RedisIntegration)
|
31
|
-
end
|
32
|
-
end
|
31
|
+
context "install" do
|
32
|
+
before do
|
33
|
+
Appsignal::Hooks.load_hooks
|
34
|
+
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
def id
|
42
|
-
"stub_id"
|
43
|
-
end
|
44
|
-
|
45
|
-
def write(_commands)
|
46
|
-
"stub_write"
|
47
|
-
end
|
48
|
-
end)
|
49
|
-
# Load the integration again for the stubbed Redis::Client class.
|
50
|
-
# Call it directly because {Appsignal::Hooks.load_hooks} keeps
|
51
|
-
# track if it was installed already or not.
|
52
|
-
Appsignal::Hooks::RedisHook.new.install
|
53
|
-
end
|
54
|
-
let!(:transaction) do
|
55
|
-
Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
|
36
|
+
it "prepends instrumentation module" do
|
37
|
+
# Test if the last included module (prepended module) was our
|
38
|
+
# integration. That's not certain with the assertions below
|
39
|
+
# because we have to overwrite the `process` method for the test.
|
40
|
+
expect(Redis::Client.included_modules.first)
|
41
|
+
.to eql(Appsignal::Integrations::RedisIntegration)
|
42
|
+
end
|
56
43
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
"name" => "query.redis",
|
67
|
-
"body" => "get ?",
|
68
|
-
"title" => "stub_id"
|
69
|
-
)
|
70
|
-
)
|
44
|
+
|
45
|
+
context "requirements" do
|
46
|
+
it "driver should have the write method" do
|
47
|
+
# Since we stub the client class below, to make sure that we don't
|
48
|
+
# create a real connection, the test won't fail if the method definition
|
49
|
+
# is changed.
|
50
|
+
method = Redis::Client.instance_method(:call)
|
51
|
+
expect(method.arity).to eql(1)
|
52
|
+
end
|
71
53
|
end
|
72
54
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
55
|
+
context "instrumentation" do
|
56
|
+
before do
|
57
|
+
start_agent
|
58
|
+
# Stub Redis::Client class so that it doesn't perform an actual
|
59
|
+
# Redis query. This class will be included (prepended) with the
|
60
|
+
# AppSignal Redis integration.
|
61
|
+
stub_const("Redis::Client", Class.new do
|
62
|
+
def id
|
63
|
+
"stub_id"
|
64
|
+
end
|
65
|
+
|
66
|
+
def write(_commands)
|
67
|
+
"stub_write"
|
68
|
+
end
|
69
|
+
end)
|
70
|
+
# Load the integration again for the stubbed Redis::Client class.
|
71
|
+
# Call it directly because {Appsignal::Hooks.load_hooks} keeps
|
72
|
+
# track if it was installed already or not.
|
73
|
+
Appsignal::Hooks::RedisHook.new.install
|
74
|
+
end
|
75
|
+
let!(:transaction) do
|
76
|
+
Appsignal::Transaction.create("uuid", Appsignal::Transaction::HTTP_REQUEST, "test")
|
77
|
+
end
|
78
|
+
around { |example| keep_transactions { example.run } }
|
79
|
+
|
80
|
+
it "instrument a redis call" do
|
81
|
+
client = Redis::Client.new
|
82
|
+
expect(client.write([:get, "key"])).to eql("stub_write")
|
83
|
+
|
84
|
+
transaction_hash = transaction.to_h
|
85
|
+
expect(transaction_hash["events"]).to include(
|
86
|
+
hash_including(
|
87
|
+
"name" => "query.redis",
|
88
|
+
"body" => "get ?",
|
89
|
+
"title" => "stub_id"
|
90
|
+
)
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "instrument a redis script call" do
|
95
|
+
client = Redis::Client.new
|
96
|
+
script = "return redis.call('set',KEYS[1],ARGV[1])"
|
97
|
+
keys = ["foo"]
|
98
|
+
argv = ["bar"]
|
99
|
+
expect(client.write([:eval, script, keys.size, keys, argv])).to eql("stub_write")
|
100
|
+
|
101
|
+
transaction_hash = transaction.to_h
|
102
|
+
expect(transaction_hash["events"]).to include(
|
103
|
+
hash_including(
|
104
|
+
"name" => "query.redis",
|
105
|
+
"body" => "#{script} ? ?",
|
106
|
+
"title" => "stub_id"
|
107
|
+
)
|
108
|
+
)
|
109
|
+
end
|
88
110
|
end
|
89
111
|
end
|
90
112
|
end
|
91
|
-
end
|
92
113
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
114
|
+
context "with instrumentation disabled" do
|
115
|
+
before do
|
116
|
+
Appsignal.config.config_hash[:instrument_redis] = false
|
117
|
+
end
|
97
118
|
|
98
|
-
|
99
|
-
|
119
|
+
describe "#dependencies_present?" do
|
120
|
+
subject { described_class.new.dependencies_present? }
|
100
121
|
|
101
|
-
|
122
|
+
it { is_expected.to be_falsy }
|
123
|
+
end
|
102
124
|
end
|
103
125
|
end
|
104
126
|
end
|
@@ -67,12 +67,12 @@ describe Appsignal::Hooks do
|
|
67
67
|
expect(Appsignal::Hooks.hooks[:mock_error_hook]).to be_instance_of(MockErrorHook)
|
68
68
|
expect(Appsignal::Hooks.hooks[:mock_error_hook].installed?).to be_falsy
|
69
69
|
|
70
|
-
expect(Appsignal.
|
70
|
+
expect(Appsignal.internal_logger).to receive(:error)
|
71
71
|
.with("Error while installing mock_error_hook hook: error").once
|
72
|
-
expect(Appsignal.
|
72
|
+
expect(Appsignal.internal_logger).to receive(:debug).ordered do |message|
|
73
73
|
expect(message).to eq("Installing mock_error_hook hook")
|
74
74
|
end
|
75
|
-
expect(Appsignal.
|
75
|
+
expect(Appsignal.internal_logger).to receive(:debug).ordered do |message|
|
76
76
|
# Start of the error backtrace as debug log
|
77
77
|
expect(message).to start_with(File.expand_path("../../..", __dir__))
|
78
78
|
end
|
@@ -89,7 +89,7 @@ describe Appsignal::Hooks do
|
|
89
89
|
let(:log_stream) { std_stream }
|
90
90
|
let(:log) { log_contents(log_stream) }
|
91
91
|
before do
|
92
|
-
Appsignal.
|
92
|
+
Appsignal.internal_logger = test_logger(log_stream)
|
93
93
|
end
|
94
94
|
|
95
95
|
def call_constant(&block)
|
@@ -18,9 +18,9 @@ if DependencyHelper.rails_present?
|
|
18
18
|
describe "#initialize_appsignal" do
|
19
19
|
let(:app) { MyApp::Application.new }
|
20
20
|
|
21
|
-
describe ".
|
21
|
+
describe ".internal_logger" do
|
22
22
|
before { Appsignal::Integrations::Railtie.initialize_appsignal(app) }
|
23
|
-
subject { Appsignal.
|
23
|
+
subject { Appsignal.internal_logger }
|
24
24
|
|
25
25
|
it { is_expected.to be_a Logger }
|
26
26
|
end
|
@@ -4,7 +4,7 @@ describe Appsignal::Integrations::SidekiqErrorHandler do
|
|
4
4
|
let(:log) { StringIO.new }
|
5
5
|
before do
|
6
6
|
start_agent
|
7
|
-
Appsignal.
|
7
|
+
Appsignal.internal_logger = test_logger(log)
|
8
8
|
end
|
9
9
|
around { |example| keep_transactions { example.run } }
|
10
10
|
|
@@ -86,7 +86,7 @@ describe Appsignal::Integrations::SidekiqMiddleware, :with_yaml_parse_error => f
|
|
86
86
|
let(:log) { StringIO.new }
|
87
87
|
before do
|
88
88
|
start_agent
|
89
|
-
Appsignal.
|
89
|
+
Appsignal.internal_logger = test_logger(log)
|
90
90
|
end
|
91
91
|
around { |example| keep_transactions { example.run } }
|
92
92
|
after :with_yaml_parse_error => false do
|
@@ -423,7 +423,7 @@ if DependencyHelper.active_job_present?
|
|
423
423
|
end
|
424
424
|
around do |example|
|
425
425
|
start_agent
|
426
|
-
Appsignal.
|
426
|
+
Appsignal.internal_logger = test_logger(log)
|
427
427
|
ActiveJob::Base.queue_adapter = :sidekiq
|
428
428
|
|
429
429
|
class ActiveJobSidekiqTestJob < ActiveJob::Base
|
@@ -16,8 +16,8 @@ if DependencyHelper.sinatra_present?
|
|
16
16
|
before { allow(Appsignal).to receive(:active?).and_return(true) }
|
17
17
|
after { uninstall_sinatra_integration }
|
18
18
|
|
19
|
-
context "Appsignal.
|
20
|
-
subject { Appsignal.
|
19
|
+
context "Appsignal.internal_logger" do
|
20
|
+
subject { Appsignal.internal_logger }
|
21
21
|
|
22
22
|
it "sets a logger" do
|
23
23
|
install_sinatra_integration
|
@@ -42,7 +42,7 @@ describe Appsignal::Minutely do
|
|
42
42
|
let(:log_stream) { StringIO.new }
|
43
43
|
let(:log) { log_contents(log_stream) }
|
44
44
|
before do
|
45
|
-
Appsignal.
|
45
|
+
Appsignal.internal_logger = test_logger(log_stream)
|
46
46
|
# Speed up test time
|
47
47
|
allow(Appsignal::Minutely).to receive(:initial_wait_time).and_return(0.001)
|
48
48
|
allow(Appsignal::Minutely).to receive(:wait_time).and_return(0.001)
|
@@ -287,7 +287,7 @@ describe Appsignal::Minutely do
|
|
287
287
|
describe "#register" do
|
288
288
|
let(:log_stream) { std_stream }
|
289
289
|
let(:log) { log_contents(log_stream) }
|
290
|
-
before { Appsignal.
|
290
|
+
before { Appsignal.internal_logger = test_logger(log_stream) }
|
291
291
|
|
292
292
|
it "adds the by key probe" do
|
293
293
|
probe = lambda {}
|
@@ -73,6 +73,20 @@ describe Appsignal::Probes::SidekiqProbe do
|
|
73
73
|
module Sidekiq7Mock
|
74
74
|
VERSION = "7.0.0".freeze
|
75
75
|
|
76
|
+
def self.redis_info_data=(info)
|
77
|
+
@redis_info_data = info
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.redis_info_data
|
81
|
+
return @redis_info_data if defined?(@redis_info_data)
|
82
|
+
|
83
|
+
{
|
84
|
+
"connected_clients" => 2,
|
85
|
+
"used_memory" => 1024,
|
86
|
+
"used_memory_rss" => 512
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
76
90
|
def self.redis
|
77
91
|
yield Client.new
|
78
92
|
end
|
@@ -83,11 +97,7 @@ describe Appsignal::Probes::SidekiqProbe do
|
|
83
97
|
end
|
84
98
|
|
85
99
|
def info
|
86
|
-
|
87
|
-
"connected_clients" => 2,
|
88
|
-
"used_memory" => 1024,
|
89
|
-
"used_memory_rss" => 512
|
90
|
-
}
|
100
|
+
Sidekiq7Mock.redis_info_data
|
91
101
|
end
|
92
102
|
end
|
93
103
|
|
@@ -227,6 +237,19 @@ describe Appsignal::Probes::SidekiqProbe do
|
|
227
237
|
probe.call
|
228
238
|
probe.call
|
229
239
|
end
|
240
|
+
|
241
|
+
context "when redis info doesn't contain requested keys" do
|
242
|
+
before { Sidekiq7Mock.redis_info_data = {} }
|
243
|
+
|
244
|
+
it "doesn't create metrics for nil values" do
|
245
|
+
expect_gauge("connection_count").never
|
246
|
+
expect_gauge("memory_usage").never
|
247
|
+
expect_gauge("memory_usage_rss").never
|
248
|
+
# Call probe twice so we can calculate the delta for some gauge values
|
249
|
+
probe.call
|
250
|
+
probe.call
|
251
|
+
end
|
252
|
+
end
|
230
253
|
end
|
231
254
|
|
232
255
|
context "with Sidekiq 6" do
|
@@ -301,7 +324,7 @@ describe Appsignal::Probes::SidekiqProbe do
|
|
301
324
|
end
|
302
325
|
end
|
303
326
|
|
304
|
-
def expect_gauge(key, value, tags = {})
|
327
|
+
def expect_gauge(key, value = anything, tags = {})
|
305
328
|
expect(Appsignal).to receive(:set_gauge)
|
306
329
|
.with("sidekiq_#{key}", value, expected_default_tags.merge(tags))
|
307
330
|
.and_call_original
|