appsignal 2.11.0.alpha.1-java → 2.11.0.alpha.2-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,147 +48,225 @@ describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
48
48
  expect(log_contents(log)).to_not contains_log(:warn, "Unable to load YAML")
49
49
  end
50
50
 
51
- shared_examples "sidekiq metadata" do
52
- describe "internal Sidekiq job values" do
53
- it "does not save internal Sidekiq values as metadata on transaction" do
54
- perform_job
51
+ shared_examples "unknown job action name" do
52
+ it "sets the action name to unknown" do
53
+ transaction_hash = transaction.to_h
54
+ expect(transaction_hash).to include("action" => "unknown")
55
+ end
55
56
 
56
- transaction_hash = transaction.to_h
57
- expect(transaction_hash["metadata"].keys)
58
- .to_not include(*Appsignal::Hooks::SidekiqPlugin::JOB_KEYS)
59
- end
57
+ it "stores no sample data" do
58
+ transaction_hash = transaction.to_h
59
+ expect(transaction_hash).to include(
60
+ "sample_data" => {
61
+ "environment" => {},
62
+ "params" => [],
63
+ "tags" => {}
64
+ }
65
+ )
60
66
  end
61
67
 
62
- context "with parameter filtering" do
63
- before do
64
- Appsignal.config = project_fixture_config("production")
65
- Appsignal.config[:filter_parameters] = ["foo"]
66
- end
68
+ it "logs a debug message" do
69
+ expect(log_contents(log)).to contains_log(
70
+ :debug, "Unable to determine an action name from Sidekiq payload: #{item}"
71
+ )
72
+ end
73
+ end
67
74
 
68
- it "filters selected arguments" do
69
- perform_job
75
+ describe "internal Sidekiq job values" do
76
+ it "does not save internal Sidekiq values as metadata on transaction" do
77
+ perform_job
70
78
 
71
- transaction_hash = transaction.to_h
72
- expect(transaction_hash["sample_data"]).to include(
73
- "params" => [
74
- "foo",
75
- {
76
- "foo" => "[FILTERED]",
77
- "bar" => "Bar",
78
- "baz" => { "1" => "foo" }
79
- }
80
- ]
81
- )
82
- end
79
+ transaction_hash = transaction.to_h
80
+ expect(transaction_hash["metadata"].keys)
81
+ .to_not include(*Appsignal::Hooks::SidekiqPlugin::JOB_KEYS)
83
82
  end
83
+ end
84
84
 
85
- context "with encrypted arguments" do
86
- before do
87
- item["encrypt"] = true
88
- item["args"] << "super secret value" # Last argument will be replaced
89
- end
85
+ context "with parameter filtering" do
86
+ before do
87
+ Appsignal.config = project_fixture_config("production")
88
+ Appsignal.config[:filter_parameters] = ["foo"]
89
+ end
90
90
 
91
- it "replaces the last argument (the secret bag) with an [encrypted data] string" do
92
- perform_job
91
+ it "filters selected arguments" do
92
+ perform_job
93
93
 
94
- transaction_hash = transaction.to_h
95
- expect(transaction_hash["sample_data"]).to include(
96
- "params" => expected_args << "[encrypted data]"
97
- )
98
- end
94
+ transaction_hash = transaction.to_h
95
+ expect(transaction_hash["sample_data"]).to include(
96
+ "params" => [
97
+ "foo",
98
+ {
99
+ "foo" => "[FILTERED]",
100
+ "bar" => "Bar",
101
+ "baz" => { "1" => "foo" }
102
+ }
103
+ ]
104
+ )
99
105
  end
106
+ end
100
107
 
101
- context "when using the Sidekiq delayed extension" do
102
- let(:item) do
103
- {
104
- "jid" => "efb140489485999d32b5504c",
105
- "class" => "Sidekiq::Extensions::DelayedClass",
106
- "queue" => "default",
107
- "args" => [
108
- "---\n- !ruby/class 'DelayedTestClass'\n- :foo_method\n- - :bar: baz\n"
109
- ],
110
- "retry" => true,
111
- "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
112
- "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
113
- "extra" => "data"
114
- }
115
- end
108
+ context "with encrypted arguments" do
109
+ before do
110
+ item["encrypt"] = true
111
+ item["args"] << "super secret value" # Last argument will be replaced
112
+ end
116
113
 
117
- it "uses the delayed class and method name for the action" do
114
+ it "replaces the last argument (the secret bag) with an [encrypted data] string" do
115
+ perform_job
116
+
117
+ transaction_hash = transaction.to_h
118
+ expect(transaction_hash["sample_data"]).to include(
119
+ "params" => expected_args << "[encrypted data]"
120
+ )
121
+ end
122
+ end
123
+
124
+ context "when using the Sidekiq delayed extension" do
125
+ let(:item) do
126
+ {
127
+ "jid" => "efb140489485999d32b5504c",
128
+ "class" => "Sidekiq::Extensions::DelayedClass",
129
+ "queue" => "default",
130
+ "args" => [
131
+ "---\n- !ruby/class 'DelayedTestClass'\n- :foo_method\n- - :bar: baz\n"
132
+ ],
133
+ "retry" => true,
134
+ "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
135
+ "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
136
+ "extra" => "data"
137
+ }
138
+ end
139
+
140
+ it "uses the delayed class and method name for the action" do
141
+ perform_job
142
+
143
+ transaction_hash = transaction.to_h
144
+ expect(transaction_hash["action"]).to eq("DelayedTestClass.foo_method")
145
+ expect(transaction_hash["sample_data"]).to include(
146
+ "params" => ["bar" => "baz"]
147
+ )
148
+ end
149
+
150
+ context "when job arguments is a malformed YAML object", :with_yaml_parse_error => true do
151
+ before { item["args"] = [] }
152
+
153
+ it "logs a warning and uses the default argument" do
118
154
  perform_job
119
155
 
120
156
  transaction_hash = transaction.to_h
121
- expect(transaction_hash["action"]).to eq("DelayedTestClass.foo_method")
122
- expect(transaction_hash["sample_data"]).to include(
123
- "params" => ["bar" => "baz"]
124
- )
157
+ expect(transaction_hash["action"]).to eq("Sidekiq::Extensions::DelayedClass#perform")
158
+ expect(transaction_hash["sample_data"]).to include("params" => [])
159
+ expect(log_contents(log)).to contains_log(:warn, "Unable to load YAML")
125
160
  end
161
+ end
162
+ end
126
163
 
127
- context "when job arguments is a malformed YAML object", :with_yaml_parse_error => true do
128
- before { item["args"] = [] }
164
+ context "when using the Sidekiq ActiveRecord instance delayed extension" do
165
+ let(:item) do
166
+ {
167
+ "jid" => "efb140489485999d32b5504c",
168
+ "class" => "Sidekiq::Extensions::DelayedModel",
169
+ "queue" => "default",
170
+ "args" => [
171
+ "---\n- !ruby/object:DelayedTestClass {}\n- :foo_method\n- - :bar: :baz\n"
172
+ ],
173
+ "retry" => true,
174
+ "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
175
+ "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
176
+ "extra" => "data"
177
+ }
178
+ end
129
179
 
130
- it "logs a warning and uses the default argument" do
131
- perform_job
180
+ it "uses the delayed class and method name for the action" do
181
+ perform_job
132
182
 
133
- transaction_hash = transaction.to_h
134
- expect(transaction_hash["action"]).to eq("Sidekiq::Extensions::DelayedClass#perform")
135
- expect(transaction_hash["sample_data"]).to include("params" => [])
136
- expect(log_contents(log)).to contains_log(:warn, "Unable to load YAML")
137
- end
138
- end
183
+ transaction_hash = transaction.to_h
184
+ expect(transaction_hash["action"]).to eq("DelayedTestClass#foo_method")
185
+ expect(transaction_hash["sample_data"]).to include(
186
+ "params" => ["bar" => "baz"]
187
+ )
139
188
  end
140
189
 
141
- context "when using the Sidekiq ActiveRecord instance delayed extension" do
142
- let(:item) do
143
- {
144
- "jid" => "efb140489485999d32b5504c",
145
- "class" => "Sidekiq::Extensions::DelayedModel",
146
- "queue" => "default",
147
- "args" => [
148
- "---\n- !ruby/object:DelayedTestClass {}\n- :foo_method\n- - :bar: :baz\n"
149
- ],
150
- "retry" => true,
151
- "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
152
- "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
153
- "extra" => "data"
154
- }
155
- end
190
+ context "when job arguments is a malformed YAML object", :with_yaml_parse_error => true do
191
+ before { item["args"] = [] }
156
192
 
157
- it "uses the delayed class and method name for the action" do
193
+ it "logs a warning and uses the default argument" do
158
194
  perform_job
159
195
 
160
196
  transaction_hash = transaction.to_h
161
- expect(transaction_hash["action"]).to eq("DelayedTestClass#foo_method")
162
- expect(transaction_hash["sample_data"]).to include(
163
- "params" => ["bar" => "baz"]
164
- )
197
+ expect(transaction_hash["action"]).to eq("Sidekiq::Extensions::DelayedModel#perform")
198
+ expect(transaction_hash["sample_data"]).to include("params" => [])
199
+ expect(log_contents(log)).to contains_log(:warn, "Unable to load YAML")
165
200
  end
201
+ end
202
+ end
166
203
 
167
- context "when job arguments is a malformed YAML object", :with_yaml_parse_error => true do
168
- before { item["args"] = [] }
204
+ context "when using ActiveJob" do
205
+ let(:item) do
206
+ {
207
+ "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
208
+ "wrapped" => "ActiveJobTestClass",
209
+ "queue" => "default",
210
+ "args" => [{
211
+ "job_class" => "ActiveJobTestJob",
212
+ "job_id" => "23e79d48-6966-40d0-b2d4-f7938463a263",
213
+ "queue_name" => "default",
214
+ "arguments" => [
215
+ "foo", { "foo" => "Foo", "bar" => "Bar", "baz" => { 1 => :bar } }
216
+ ]
217
+ }],
218
+ "retry" => true,
219
+ "jid" => "efb140489485999d32b5504c",
220
+ "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
221
+ "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f
222
+ }
223
+ end
169
224
 
170
- it "logs a warning and uses the default argument" do
171
- perform_job
225
+ it "creates a transaction with events" do
226
+ perform_job
172
227
 
173
- transaction_hash = transaction.to_h
174
- expect(transaction_hash["action"]).to eq("Sidekiq::Extensions::DelayedModel#perform")
175
- expect(transaction_hash["sample_data"]).to include("params" => [])
176
- expect(log_contents(log)).to contains_log(:warn, "Unable to load YAML")
177
- end
178
- end
228
+ transaction_hash = transaction.to_h
229
+ expect(transaction_hash).to include(
230
+ "id" => kind_of(String),
231
+ "action" => "ActiveJobTestClass#perform",
232
+ "error" => nil,
233
+ "namespace" => namespace,
234
+ "metadata" => {
235
+ "queue" => "default"
236
+ },
237
+ "sample_data" => {
238
+ "environment" => {},
239
+ "params" => [
240
+ "foo",
241
+ {
242
+ "foo" => "Foo",
243
+ "bar" => "Bar",
244
+ "baz" => { "1" => "bar" }
245
+ }
246
+ ],
247
+ "tags" => {}
248
+ }
249
+ )
250
+ # TODO: Not available in transaction.to_h yet.
251
+ # https://github.com/appsignal/appsignal-agent/issues/293
252
+ expect(transaction.request.env).to eq(
253
+ :queue_start => Time.parse("2001-01-01 10:00:00UTC").to_f
254
+ )
255
+ expect_transaction_to_have_sidekiq_event(transaction_hash)
179
256
  end
180
257
 
181
- context "when using ActiveJob" do
258
+ context "with ActionMailer job" do
182
259
  let(:item) do
183
260
  {
184
261
  "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
185
- "wrapped" => "ActiveJobTestClass",
262
+ "wrapped" => "ActionMailer::DeliveryJob",
186
263
  "queue" => "default",
187
264
  "args" => [{
188
- "job_class" => "ActiveJobTestJob",
265
+ "job_class" => "ActiveMailerTestJob",
189
266
  "job_id" => "23e79d48-6966-40d0-b2d4-f7938463a263",
190
267
  "queue_name" => "default",
191
268
  "arguments" => [
269
+ "MailerClass", "mailer_method", "deliver_now",
192
270
  "foo", { "foo" => "Foo", "bar" => "Bar", "baz" => { 1 => :bar } }
193
271
  ]
194
272
  }],
@@ -199,13 +277,13 @@ describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
199
277
  }
200
278
  end
201
279
 
202
- it "creates a transaction with events" do
280
+ it "creates a transaction for the ActionMailer class" do
203
281
  perform_job
204
282
 
205
283
  transaction_hash = transaction.to_h
206
284
  expect(transaction_hash).to include(
207
285
  "id" => kind_of(String),
208
- "action" => "ActiveJobTestClass#perform",
286
+ "action" => "MailerClass#mailer_method",
209
287
  "error" => nil,
210
288
  "namespace" => namespace,
211
289
  "metadata" => {
@@ -224,43 +302,87 @@ describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
224
302
  "tags" => {}
225
303
  }
226
304
  )
227
- # TODO: Not available in transaction.to_h yet.
228
- # https://github.com/appsignal/appsignal-agent/issues/293
229
- expect(transaction.request.env).to eq(
230
- :queue_start => Time.parse("2001-01-01 10:00:00UTC").to_f
305
+ end
306
+ end
307
+
308
+ context "with parameter filtering" do
309
+ before do
310
+ Appsignal.config = project_fixture_config("production")
311
+ Appsignal.config[:filter_parameters] = ["foo"]
312
+ end
313
+
314
+ it "filters selected arguments" do
315
+ perform_job
316
+
317
+ transaction_hash = transaction.to_h
318
+ expect(transaction_hash["sample_data"]).to include(
319
+ "params" => [
320
+ "foo",
321
+ {
322
+ "foo" => "[FILTERED]",
323
+ "bar" => "Bar",
324
+ "baz" => { "1" => "bar" }
325
+ }
326
+ ]
231
327
  )
232
- expect_transaction_to_have_sidekiq_event(transaction_hash)
233
328
  end
329
+ end
234
330
 
235
- context "with ActionMailer job" do
236
- let(:item) do
331
+ context "when Sidekiq job payload is missing the 'wrapped' value" do
332
+ let(:item) do
333
+ {
334
+ "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
335
+ "queue" => "default",
336
+ "args" => [first_argument],
337
+ "retry" => true,
338
+ "jid" => "efb140489485999d32b5504c",
339
+ "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
340
+ "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f
341
+ }
342
+ end
343
+ before { perform_job }
344
+
345
+ context "when the first argument is not a Hash object" do
346
+ let(:first_argument) { "foo" }
347
+
348
+ include_examples "unknown job action name"
349
+ end
350
+
351
+ context "when the first argument is a Hash object not containing a job payload" do
352
+ let(:first_argument) { { "foo" => "bar" } }
353
+
354
+ include_examples "unknown job action name"
355
+
356
+ context "when the argument contains an invalid job_class value" do
357
+ let(:first_argument) { { "job_class" => :foo } }
358
+
359
+ include_examples "unknown job action name"
360
+ end
361
+ end
362
+
363
+ context "when the first argument is a Hash object containing a job payload" do
364
+ let(:first_argument) do
237
365
  {
238
- "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
239
- "wrapped" => "ActionMailer::DeliveryJob",
240
- "queue" => "default",
241
- "args" => [{
242
- "job_class" => "ActiveMailerTestJob",
243
- "job_id" => "23e79d48-6966-40d0-b2d4-f7938463a263",
244
- "queue_name" => "default",
245
- "arguments" => [
246
- "MailerClass", "mailer_method", "deliver_now",
247
- "foo", { "foo" => "Foo", "bar" => "Bar", "baz" => { 1 => :bar } }
248
- ]
249
- }],
250
- "retry" => true,
251
- "jid" => "efb140489485999d32b5504c",
252
- "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
253
- "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f
366
+ "job_class" => "ActiveMailerTestJob",
367
+ "job_id" => "23e79d48-6966-40d0-b2d4-f7938463a263",
368
+ "queue_name" => "default",
369
+ "arguments" => [
370
+ "foo", { "foo" => "Foo", "bar" => "Bar", "baz" => { 1 => :bar } }
371
+ ]
254
372
  }
255
373
  end
256
374
 
257
- it "creates a transaction for the ActionMailer class" do
258
- perform_job
375
+ it "sets the action name to the job class in the first argument" do
376
+ transaction_hash = transaction.to_h
377
+ expect(transaction_hash).to include(
378
+ "action" => "ActiveMailerTestJob#perform"
379
+ )
380
+ end
259
381
 
382
+ it "stores the job metadata on the transaction" do
260
383
  transaction_hash = transaction.to_h
261
384
  expect(transaction_hash).to include(
262
385
  "id" => kind_of(String),
263
- "action" => "MailerClass#mailer_method",
264
386
  "error" => nil,
265
387
  "namespace" => namespace,
266
388
  "metadata" => {
@@ -280,137 +402,13 @@ describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
280
402
  }
281
403
  )
282
404
  end
283
- end
284
-
285
- context "with parameter filtering" do
286
- before do
287
- Appsignal.config = project_fixture_config("production")
288
- Appsignal.config[:filter_parameters] = ["foo"]
289
- end
290
-
291
- it "filters selected arguments" do
292
- perform_job
293
405
 
294
- transaction_hash = transaction.to_h
295
- expect(transaction_hash["sample_data"]).to include(
296
- "params" => [
297
- "foo",
298
- {
299
- "foo" => "[FILTERED]",
300
- "bar" => "Bar",
301
- "baz" => { "1" => "bar" }
302
- }
303
- ]
406
+ it "does not log a debug message" do
407
+ expect(log_contents(log)).to_not contains_log(
408
+ :debug, "Unable to determine an action name from Sidekiq payload"
304
409
  )
305
410
  end
306
411
  end
307
-
308
- context "when Sidekiq job payload is missing the 'wrapped' value" do
309
- let(:item) do
310
- {
311
- "class" => "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper",
312
- "queue" => "default",
313
- "args" => [first_argument],
314
- "retry" => true,
315
- "jid" => "efb140489485999d32b5504c",
316
- "created_at" => Time.parse("2001-01-01 10:00:00UTC").to_f,
317
- "enqueued_at" => Time.parse("2001-01-01 10:00:00UTC").to_f
318
- }
319
- end
320
- before { perform_job }
321
-
322
- context "when the first argument is not a Hash object" do
323
- let(:first_argument) { "foo" }
324
-
325
- include_examples "unknown job action name"
326
- end
327
-
328
- context "when the first argument is a Hash object not containing a job payload" do
329
- let(:first_argument) { { "foo" => "bar" } }
330
-
331
- include_examples "unknown job action name"
332
-
333
- context "when the argument contains an invalid job_class value" do
334
- let(:first_argument) { { "job_class" => :foo } }
335
-
336
- include_examples "unknown job action name"
337
- end
338
- end
339
-
340
- context "when the first argument is a Hash object containing a job payload" do
341
- let(:first_argument) do
342
- {
343
- "job_class" => "ActiveMailerTestJob",
344
- "job_id" => "23e79d48-6966-40d0-b2d4-f7938463a263",
345
- "queue_name" => "default",
346
- "arguments" => [
347
- "foo", { "foo" => "Foo", "bar" => "Bar", "baz" => { 1 => :bar } }
348
- ]
349
- }
350
- end
351
-
352
- it "sets the action name to the job class in the first argument" do
353
- transaction_hash = transaction.to_h
354
- expect(transaction_hash).to include(
355
- "action" => "ActiveMailerTestJob#perform"
356
- )
357
- end
358
-
359
- it "stores the job metadata on the transaction" do
360
- transaction_hash = transaction.to_h
361
- expect(transaction_hash).to include(
362
- "id" => kind_of(String),
363
- "error" => nil,
364
- "namespace" => namespace,
365
- "metadata" => {
366
- "queue" => "default"
367
- },
368
- "sample_data" => {
369
- "environment" => {},
370
- "params" => [
371
- "foo",
372
- {
373
- "foo" => "Foo",
374
- "bar" => "Bar",
375
- "baz" => { "1" => "bar" }
376
- }
377
- ],
378
- "tags" => {}
379
- }
380
- )
381
- end
382
-
383
- it "does not log a debug message" do
384
- expect(log_contents(log)).to_not contains_log(
385
- :debug, "Unable to determine an action name from Sidekiq payload"
386
- )
387
- end
388
- end
389
- end
390
- end
391
- end
392
-
393
- shared_examples "unknown job action name" do
394
- it "sets the action name to unknown" do
395
- transaction_hash = transaction.to_h
396
- expect(transaction_hash).to include("action" => "unknown")
397
- end
398
-
399
- it "stores no sample data" do
400
- transaction_hash = transaction.to_h
401
- expect(transaction_hash).to include(
402
- "sample_data" => {
403
- "environment" => {},
404
- "params" => [],
405
- "tags" => {}
406
- }
407
- )
408
- end
409
-
410
- it "logs a debug message" do
411
- expect(log_contents(log)).to contains_log(
412
- :debug, "Unable to determine an action name from Sidekiq payload: #{item}"
413
- )
414
412
  end
415
413
  end
416
414
 
@@ -452,8 +450,6 @@ describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
452
450
  )
453
451
  expect_transaction_to_have_sidekiq_event(transaction_hash)
454
452
  end
455
-
456
- include_examples "sidekiq metadata"
457
453
  end
458
454
 
459
455
  context "without an error" do
@@ -487,8 +483,6 @@ describe Appsignal::Hooks::SidekiqPlugin, :with_yaml_parse_error => false do
487
483
  )
488
484
  expect_transaction_to_have_sidekiq_event(transaction_hash)
489
485
  end
490
-
491
- include_examples "sidekiq metadata"
492
486
  end
493
487
 
494
488
  def perform_job
@@ -537,7 +531,7 @@ describe Appsignal::Hooks::SidekiqHook do
537
531
  describe "#install" do
538
532
  before do
539
533
  Appsignal.config = project_fixture_config
540
- class Sidekiq
534
+ module Sidekiq
541
535
  def self.middlewares
542
536
  @middlewares ||= Set.new
543
537
  end
@@ -560,203 +554,3 @@ describe Appsignal::Hooks::SidekiqHook do
560
554
  end
561
555
  end
562
556
  end
563
-
564
- describe Appsignal::Hooks::SidekiqProbe do
565
- describe "#call" do
566
- let(:probe) { described_class.new }
567
- let(:redis_hostname) { "localhost" }
568
- let(:expected_default_tags) { { :hostname => "localhost" } }
569
- before do
570
- Appsignal.config = project_fixture_config
571
- class Sidekiq
572
- def self.redis_info
573
- {
574
- "connected_clients" => 2,
575
- "used_memory" => 1024,
576
- "used_memory_rss" => 512
577
- }
578
- end
579
-
580
- def self.redis
581
- yield Client.new
582
- end
583
-
584
- class Client
585
- def connection
586
- { :host => "localhost" }
587
- end
588
- end
589
-
590
- class Stats
591
- class << self
592
- attr_reader :calls
593
-
594
- def count_call
595
- @calls ||= -1
596
- @calls += 1
597
- end
598
- end
599
-
600
- def workers_size
601
- # First method called, so count it towards a call
602
- self.class.count_call
603
- 24
604
- end
605
-
606
- def processes_size
607
- 25
608
- end
609
-
610
- # Return two different values for two separate calls.
611
- # This allows us to test the delta of the value send as a gauge.
612
- def processed
613
- [10, 15][self.class.calls]
614
- end
615
-
616
- # Return two different values for two separate calls.
617
- # This allows us to test the delta of the value send as a gauge.
618
- def failed
619
- [10, 13][self.class.calls]
620
- end
621
-
622
- def retry_size
623
- 12
624
- end
625
-
626
- # Return two different values for two separate calls.
627
- # This allows us to test the delta of the value send as a gauge.
628
- def dead_size
629
- [10, 12][self.class.calls]
630
- end
631
-
632
- def scheduled_size
633
- 14
634
- end
635
-
636
- def enqueued
637
- 15
638
- end
639
- end
640
-
641
- class Queue
642
- Queue = Struct.new(:name, :size, :latency)
643
-
644
- def self.all
645
- [
646
- Queue.new("default", 10, 12),
647
- Queue.new("critical", 1, 2)
648
- ]
649
- end
650
- end
651
- end
652
- end
653
- after { Object.send(:remove_const, "Sidekiq") }
654
-
655
- describe ".dependencies_present?" do
656
- before do
657
- class Redis; end
658
- Redis.const_set(:VERSION, version)
659
- end
660
- after { Object.send(:remove_const, "Redis") }
661
-
662
- context "when Redis version is < 3.3.5" do
663
- let(:version) { "3.3.4" }
664
-
665
- it "does not start probe" do
666
- expect(described_class.dependencies_present?).to be_falsy
667
- end
668
- end
669
-
670
- context "when Redis version is >= 3.3.5" do
671
- let(:version) { "3.3.5" }
672
-
673
- it "does not start probe" do
674
- expect(described_class.dependencies_present?).to be_truthy
675
- end
676
- end
677
- end
678
-
679
- it "loads Sidekiq::API" do
680
- expect(defined?(Sidekiq::API)).to be_falsy
681
- probe
682
- expect(defined?(Sidekiq::API)).to be_truthy
683
- end
684
-
685
- it "logs config on initialize" do
686
- log = capture_logs { probe }
687
- expect(log).to contains_log(:debug, "Initializing Sidekiq probe\n")
688
- end
689
-
690
- it "logs used hostname on call once" do
691
- log = capture_logs { probe.call }
692
- expect(log).to contains_log(
693
- :debug,
694
- %(Sidekiq probe: Using Redis server hostname "localhost" as hostname)
695
- )
696
- log = capture_logs { probe.call }
697
- # Match more logs with incompelete message
698
- expect(log).to_not contains_log(:debug, %(Sidekiq probe: ))
699
- end
700
-
701
- it "collects custom metrics" do
702
- expect_gauge("worker_count", 24).twice
703
- expect_gauge("process_count", 25).twice
704
- expect_gauge("connection_count", 2).twice
705
- expect_gauge("memory_usage", 1024).twice
706
- expect_gauge("memory_usage_rss", 512).twice
707
- expect_gauge("job_count", 5, :status => :processed) # Gauge delta
708
- expect_gauge("job_count", 3, :status => :failed) # Gauge delta
709
- expect_gauge("job_count", 12, :status => :retry_queue).twice
710
- expect_gauge("job_count", 2, :status => :died) # Gauge delta
711
- expect_gauge("job_count", 14, :status => :scheduled).twice
712
- expect_gauge("job_count", 15, :status => :enqueued).twice
713
- expect_gauge("queue_length", 10, :queue => "default").twice
714
- expect_gauge("queue_latency", 12_000, :queue => "default").twice
715
- expect_gauge("queue_length", 1, :queue => "critical").twice
716
- expect_gauge("queue_latency", 2_000, :queue => "critical").twice
717
- # Call probe twice so we can calculate the delta for some gauge values
718
- probe.call
719
- probe.call
720
- end
721
-
722
- context "when `redis_info` is not defined" do
723
- before do
724
- allow(Sidekiq).to receive(:respond_to?).with(:redis_info).and_return(false)
725
- end
726
-
727
- it "does not collect redis metrics" do
728
- expect_gauge("connection_count", 2).never
729
- expect_gauge("memory_usage", 1024).never
730
- expect_gauge("memory_usage_rss", 512).never
731
- probe.call
732
- end
733
- end
734
-
735
- context "when hostname is configured for probe" do
736
- let(:redis_hostname) { "my_redis_server" }
737
- let(:probe) { described_class.new(:hostname => redis_hostname) }
738
-
739
- it "uses the redis hostname for the hostname tag" do
740
- allow(Appsignal).to receive(:set_gauge).and_call_original
741
- log = capture_logs { probe }
742
- expect(log).to contains_log(
743
- :debug,
744
- %(Initializing Sidekiq probe with config: {:hostname=>"#{redis_hostname}"})
745
- )
746
- log = capture_logs { probe.call }
747
- expect(log).to contains_log(
748
- :debug,
749
- "Sidekiq probe: Using hostname config option #{redis_hostname.inspect} as hostname"
750
- )
751
- expect(Appsignal).to have_received(:set_gauge)
752
- .with(anything, anything, :hostname => redis_hostname).at_least(:once)
753
- end
754
- end
755
-
756
- def expect_gauge(key, value, tags = {})
757
- expect(Appsignal).to receive(:set_gauge)
758
- .with("sidekiq_#{key}", value, expected_default_tags.merge(tags))
759
- .and_call_original
760
- end
761
- end
762
- end