appsignal 3.1.5 → 3.1.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9c72c3c1f23e52406ea915fe3dd35cf45648c7dd712cebc8cdf908e304be60e
4
- data.tar.gz: 90ddbe20ee5243338aefdfbefbb1989bbe1df5cc57a56a4f277bcfa789086b41
3
+ metadata.gz: 7a3a10bbc00539eeb5809a449c341151d7fdd87bdeb81c85e9a7778ef4b49857
4
+ data.tar.gz: a5e646a6124dd3a9173d3a30ec19463076a50b96e8b4320ef54c909fdc2aad22
5
5
  SHA512:
6
- metadata.gz: 3f7aaf99cae0ca17beab0064e259c8a2cbe1f95b1bcaabc9a074b3033ead5fc847d714d2e84b0140874ef1efc57c098ad3c46596be87f09ead2a5f2d148d77ea
7
- data.tar.gz: bfe585b6c6ce5f8cc5e470c9a164e6690fc1834e40bb4bd27491f719cbdaf6ebd4b92d1f1ba2bc3001e157f5c35786f12143b29d9908e9ce73d9ca9712c7c5ef
6
+ metadata.gz: f0038a47accbfd1d2f69bb7c9b1db650bb974d416674285afddf2570e9ea19bd9958dfeb3b24d8f950f058af0a9d63ba212920e632ea5dbb5a2ece55b237e1fe
7
+ data.tar.gz: 3761cf3f55137ac16e63a740d917e0f83a75d8d72ad93cbd52aa1de09a61bd3631dc8e6f537ada82d36c7e8a0395b1e05f5d76084508dd00169a2ef67c77a83d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # AppSignal for Ruby gem Changelog
2
2
 
3
+ ## 3.1.6
4
+
5
+ ### Fixed
6
+
7
+ - [a03b7246](https://github.com/appsignal/appsignal-ruby/commit/a03b72461f5f3b047ca81368cf2bdbeadf078e08) patch - Support Sidekiq 7 in the Sidekiq minutely probe. It will now report metrics to Sidekiq magic dashboard for Sidekiq version 7 and newer.
8
+
3
9
  ## 3.1.5
4
10
 
5
11
  ### Changed
@@ -3,17 +3,59 @@ module Appsignal
3
3
  class SidekiqProbe
4
4
  include Helpers
5
5
 
6
+ class Sidekiq7Adapter
7
+ def self.redis_info
8
+ redis_info = nil
9
+ ::Sidekiq.redis { |c| redis_info = c.info }
10
+ redis_info
11
+ end
12
+
13
+ def self.hostname
14
+ host = nil
15
+ ::Sidekiq.redis do |c|
16
+ host = c.config.host
17
+ end
18
+ host
19
+ end
20
+ end
21
+
22
+ class Sidekiq6Adapter
23
+ def self.redis_info
24
+ return unless ::Sidekiq.respond_to?(:redis_info)
25
+
26
+ ::Sidekiq.redis_info
27
+ end
28
+
29
+ def self.hostname
30
+ host = nil
31
+ ::Sidekiq.redis do |c|
32
+ host = c.connection[:host] if c.respond_to? :connection
33
+ end
34
+ host
35
+ end
36
+ end
37
+
6
38
  # @api private
7
39
  attr_reader :config
8
40
 
41
+ def self.sidekiq7_and_greater?
42
+ Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("7.0.0")
43
+ end
44
+
9
45
  # @api private
10
46
  def self.dependencies_present?
47
+ return true if sidekiq7_and_greater?
48
+ return unless defined?(::Redis::VERSION) # Sidekiq <= 6
49
+
11
50
  Gem::Version.new(::Redis::VERSION) >= Gem::Version.new("3.3.5")
12
51
  end
13
52
 
14
53
  def initialize(config = {})
15
54
  @config = config
16
55
  @cache = {}
56
+ is_sidekiq7 = self.class.sidekiq7_and_greater?
57
+ @adapter = is_sidekiq7 ? Sidekiq7Adapter : Sidekiq6Adapter
58
+
17
59
  config_string = " with config: #{config}" unless config.empty?
18
60
  Appsignal.logger.debug("Initializing Sidekiq probe#{config_string}")
19
61
  require "sidekiq/api"
@@ -28,11 +70,11 @@ module Appsignal
28
70
 
29
71
  private
30
72
 
31
- attr_reader :cache
73
+ attr_reader :adapter, :cache
32
74
 
33
75
  def track_redis_info
34
- return unless ::Sidekiq.respond_to?(:redis_info)
35
- redis_info = ::Sidekiq.redis_info
76
+ redis_info = adapter.redis_info
77
+ return unless redis_info
36
78
 
37
79
  gauge "connection_count", redis_info.fetch("connected_clients")
38
80
  gauge "memory_usage", redis_info.fetch("used_memory")
@@ -81,8 +123,7 @@ module Appsignal
81
123
  return @hostname
82
124
  end
83
125
 
84
- host = nil
85
- ::Sidekiq.redis { |c| host = c.connection[:host] }
126
+ host = adapter.hostname
86
127
  Appsignal.logger.debug "Sidekiq probe: Using Redis server hostname " \
87
128
  "#{host.inspect} as hostname"
88
129
  @hostname = host
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Appsignal
4
- VERSION = "3.1.5".freeze
4
+ VERSION = "3.1.6".freeze
5
5
  end
@@ -7,114 +7,177 @@ describe Appsignal::Probes::SidekiqProbe do
7
7
  let(:expected_default_tags) { { :hostname => "localhost" } }
8
8
  before do
9
9
  Appsignal.config = project_fixture_config
10
- module SidekiqMock
11
- def self.redis_info
12
- {
13
- "connected_clients" => 2,
14
- "used_memory" => 1024,
15
- "used_memory_rss" => 512
16
- }
10
+
11
+ class SidekiqStats
12
+ class << self
13
+ attr_reader :calls
14
+
15
+ def count_call
16
+ @calls ||= -1
17
+ @calls += 1
18
+ end
17
19
  end
18
20
 
19
- def self.redis
20
- yield Client.new
21
+ def workers_size
22
+ # First method called, so count it towards a call
23
+ self.class.count_call
24
+ 24
21
25
  end
22
26
 
23
- class Client
24
- def connection
25
- { :host => "localhost" }
26
- end
27
+ def processes_size
28
+ 25
27
29
  end
28
30
 
29
- class Stats
30
- class << self
31
- attr_reader :calls
31
+ # Return two different values for two separate calls.
32
+ # This allows us to test the delta of the value send as a gauge.
33
+ def processed
34
+ [10, 15][self.class.calls]
35
+ end
32
36
 
33
- def count_call
34
- @calls ||= -1
35
- @calls += 1
36
- end
37
- end
37
+ # Return two different values for two separate calls.
38
+ # This allows us to test the delta of the value send as a gauge.
39
+ def failed
40
+ [10, 13][self.class.calls]
41
+ end
38
42
 
39
- def workers_size
40
- # First method called, so count it towards a call
41
- self.class.count_call
42
- 24
43
- end
43
+ def retry_size
44
+ 12
45
+ end
44
46
 
45
- def processes_size
46
- 25
47
- end
47
+ # Return two different values for two separate calls.
48
+ # This allows us to test the delta of the value send as a gauge.
49
+ def dead_size
50
+ [10, 12][self.class.calls]
51
+ end
48
52
 
49
- # Return two different values for two separate calls.
50
- # This allows us to test the delta of the value send as a gauge.
51
- def processed
52
- [10, 15][self.class.calls]
53
- end
53
+ def scheduled_size
54
+ 14
55
+ end
54
56
 
55
- # Return two different values for two separate calls.
56
- # This allows us to test the delta of the value send as a gauge.
57
- def failed
58
- [10, 13][self.class.calls]
59
- end
57
+ def enqueued
58
+ 15
59
+ end
60
+ end
60
61
 
61
- def retry_size
62
- 12
63
- end
62
+ class SidekiqQueue
63
+ Queue = Struct.new(:name, :size, :latency)
64
+
65
+ def self.all
66
+ [
67
+ Queue.new("default", 10, 12),
68
+ Queue.new("critical", 1, 2)
69
+ ]
70
+ end
71
+ end
72
+
73
+ module Sidekiq7Mock
74
+ VERSION = "7.0.0".freeze
75
+
76
+ def self.redis
77
+ yield Client.new
78
+ end
64
79
 
65
- # Return two different values for two separate calls.
66
- # This allows us to test the delta of the value send as a gauge.
67
- def dead_size
68
- [10, 12][self.class.calls]
80
+ class Client
81
+ def config
82
+ Config.new
69
83
  end
70
84
 
71
- def scheduled_size
72
- 14
85
+ def info
86
+ {
87
+ "connected_clients" => 2,
88
+ "used_memory" => 1024,
89
+ "used_memory_rss" => 512
90
+ }
73
91
  end
92
+ end
74
93
 
75
- def enqueued
76
- 15
94
+ class Config
95
+ def host
96
+ "localhost"
77
97
  end
78
98
  end
79
99
 
80
- class Queue
81
- Queue = Struct.new(:name, :size, :latency)
100
+ Stats = ::SidekiqStats
101
+ Queue = ::SidekiqQueue
102
+ end
103
+
104
+ module Sidekiq6Mock
105
+ VERSION = "6.9.9".freeze
106
+
107
+ def self.redis_info
108
+ {
109
+ "connected_clients" => 2,
110
+ "used_memory" => 1024,
111
+ "used_memory_rss" => 512
112
+ }
113
+ end
114
+
115
+ def self.redis
116
+ yield Client.new
117
+ end
82
118
 
83
- def self.all
84
- [
85
- Queue.new("default", 10, 12),
86
- Queue.new("critical", 1, 2)
87
- ]
119
+ class Client
120
+ def connection
121
+ { :host => "localhost" }
88
122
  end
89
123
  end
124
+
125
+ Stats = ::SidekiqStats
126
+ Queue = ::SidekiqQueue
90
127
  end
91
- stub_const("Sidekiq", SidekiqMock)
92
128
  end
93
- after { Object.send(:remove_const, :SidekiqMock) }
129
+ after do
130
+ Object.send(:remove_const, :SidekiqStats)
131
+ Object.send(:remove_const, :SidekiqQueue)
132
+ Object.send(:remove_const, :Sidekiq6Mock)
133
+ Object.send(:remove_const, :Sidekiq7Mock)
134
+ end
135
+
136
+ def with_sidekiq7!
137
+ stub_const("Sidekiq", Sidekiq7Mock)
138
+ end
139
+ # Version not relevant, but requires any version for tests
140
+ alias_method :with_sidekiq!, :with_sidekiq7!
141
+
142
+ def with_sidekiq6!
143
+ stub_const("Sidekiq", Sidekiq6Mock)
144
+ end
94
145
 
95
146
  describe ".dependencies_present?" do
96
- before do
97
- stub_const("Redis::VERSION", version)
147
+ context "when Sidekiq 7" do
148
+ before { with_sidekiq7! }
149
+
150
+ it "starts the probe" do
151
+ expect(described_class.dependencies_present?).to be_truthy
152
+ end
98
153
  end
99
154
 
100
- context "when Redis version is < 3.3.5" do
101
- let(:version) { "3.3.4" }
155
+ context "when Sidekiq 6" do
156
+ before do
157
+ with_sidekiq6!
158
+ stub_const("Redis::VERSION", version)
159
+ end
160
+
161
+ context "when Redis version is < 3.3.5" do
162
+ let(:version) { "3.3.4" }
102
163
 
103
- it "does not start probe" do
104
- expect(described_class.dependencies_present?).to be_falsy
164
+ it "does not start probe" do
165
+ expect(described_class.dependencies_present?).to be_falsy
166
+ end
105
167
  end
106
- end
107
168
 
108
- context "when Redis version is >= 3.3.5" do
109
- let(:version) { "3.3.5" }
169
+ context "when Redis version is >= 3.3.5" do
170
+ let(:version) { "3.3.5" }
110
171
 
111
- it "does not start probe" do
112
- expect(described_class.dependencies_present?).to be_truthy
172
+ it "starts the probe" do
173
+ expect(described_class.dependencies_present?).to be_truthy
174
+ end
113
175
  end
114
176
  end
115
177
  end
116
178
 
117
179
  it "loads Sidekiq::API" do
180
+ with_sidekiq!
118
181
  # Hide the Sidekiq constant if it was already loaded. It will be
119
182
  # redefined by loading "sidekiq/api" in the probe.
120
183
  hide_const "Sidekiq::Stats"
@@ -125,53 +188,94 @@ describe Appsignal::Probes::SidekiqProbe do
125
188
  end
126
189
 
127
190
  it "logs config on initialize" do
191
+ with_sidekiq!
128
192
  log = capture_logs { probe }
129
193
  expect(log).to contains_log(:debug, "Initializing Sidekiq probe\n")
130
194
  end
131
195
 
132
- it "logs used hostname on call once" do
133
- log = capture_logs { probe.call }
134
- expect(log).to contains_log(
135
- :debug,
136
- %(Sidekiq probe: Using Redis server hostname "localhost" as hostname)
137
- )
138
- log = capture_logs { probe.call }
139
- # Match more logs with incompelete message
140
- expect(log).to_not contains_log(:debug, %(Sidekiq probe: ))
141
- end
196
+ context "with Sidekiq 7" do
197
+ before { with_sidekiq7! }
142
198
 
143
- it "collects custom metrics" do
144
- expect_gauge("worker_count", 24).twice
145
- expect_gauge("process_count", 25).twice
146
- expect_gauge("connection_count", 2).twice
147
- expect_gauge("memory_usage", 1024).twice
148
- expect_gauge("memory_usage_rss", 512).twice
149
- expect_gauge("job_count", 5, :status => :processed) # Gauge delta
150
- expect_gauge("job_count", 3, :status => :failed) # Gauge delta
151
- expect_gauge("job_count", 12, :status => :retry_queue).twice
152
- expect_gauge("job_count", 2, :status => :died) # Gauge delta
153
- expect_gauge("job_count", 14, :status => :scheduled).twice
154
- expect_gauge("job_count", 15, :status => :enqueued).twice
155
- expect_gauge("queue_length", 10, :queue => "default").twice
156
- expect_gauge("queue_latency", 12_000, :queue => "default").twice
157
- expect_gauge("queue_length", 1, :queue => "critical").twice
158
- expect_gauge("queue_latency", 2_000, :queue => "critical").twice
159
- # Call probe twice so we can calculate the delta for some gauge values
160
- probe.call
161
- probe.call
199
+ it "logs used hostname on call once" do
200
+ log = capture_logs { probe.call }
201
+ expect(log).to contains_log(
202
+ :debug,
203
+ %(Sidekiq probe: Using Redis server hostname "localhost" as hostname)
204
+ )
205
+ log = capture_logs { probe.call }
206
+ # Match more logs with incompelete message
207
+ expect(log).to_not contains_log(:debug, %(Sidekiq probe: ))
208
+ end
209
+
210
+ it "collects custom metrics" do
211
+ expect_gauge("worker_count", 24).twice
212
+ expect_gauge("process_count", 25).twice
213
+ expect_gauge("connection_count", 2).twice
214
+ expect_gauge("memory_usage", 1024).twice
215
+ expect_gauge("memory_usage_rss", 512).twice
216
+ expect_gauge("job_count", 5, :status => :processed) # Gauge delta
217
+ expect_gauge("job_count", 3, :status => :failed) # Gauge delta
218
+ expect_gauge("job_count", 12, :status => :retry_queue).twice
219
+ expect_gauge("job_count", 2, :status => :died) # Gauge delta
220
+ expect_gauge("job_count", 14, :status => :scheduled).twice
221
+ expect_gauge("job_count", 15, :status => :enqueued).twice
222
+ expect_gauge("queue_length", 10, :queue => "default").twice
223
+ expect_gauge("queue_latency", 12_000, :queue => "default").twice
224
+ expect_gauge("queue_length", 1, :queue => "critical").twice
225
+ expect_gauge("queue_latency", 2_000, :queue => "critical").twice
226
+ # Call probe twice so we can calculate the delta for some gauge values
227
+ probe.call
228
+ probe.call
229
+ end
162
230
  end
163
231
 
164
- context "when `redis_info` is not defined" do
165
- before do
166
- allow(Sidekiq).to receive(:respond_to?).with(:redis_info).and_return(false)
232
+ context "with Sidekiq 6" do
233
+ before { with_sidekiq6! }
234
+
235
+ it "logs used hostname on call once" do
236
+ log = capture_logs { probe.call }
237
+ expect(log).to contains_log(
238
+ :debug,
239
+ %(Sidekiq probe: Using Redis server hostname "localhost" as hostname)
240
+ )
241
+ log = capture_logs { probe.call }
242
+ # Match more logs with incompelete message
243
+ expect(log).to_not contains_log(:debug, %(Sidekiq probe: ))
167
244
  end
168
245
 
169
- it "does not collect redis metrics" do
170
- expect_gauge("connection_count", 2).never
171
- expect_gauge("memory_usage", 1024).never
172
- expect_gauge("memory_usage_rss", 512).never
246
+ it "collects custom metrics" do
247
+ expect_gauge("worker_count", 24).twice
248
+ expect_gauge("process_count", 25).twice
249
+ expect_gauge("connection_count", 2).twice
250
+ expect_gauge("memory_usage", 1024).twice
251
+ expect_gauge("memory_usage_rss", 512).twice
252
+ expect_gauge("job_count", 5, :status => :processed) # Gauge delta
253
+ expect_gauge("job_count", 3, :status => :failed) # Gauge delta
254
+ expect_gauge("job_count", 12, :status => :retry_queue).twice
255
+ expect_gauge("job_count", 2, :status => :died) # Gauge delta
256
+ expect_gauge("job_count", 14, :status => :scheduled).twice
257
+ expect_gauge("job_count", 15, :status => :enqueued).twice
258
+ expect_gauge("queue_length", 10, :queue => "default").twice
259
+ expect_gauge("queue_latency", 12_000, :queue => "default").twice
260
+ expect_gauge("queue_length", 1, :queue => "critical").twice
261
+ expect_gauge("queue_latency", 2_000, :queue => "critical").twice
262
+ # Call probe twice so we can calculate the delta for some gauge values
263
+ probe.call
173
264
  probe.call
174
265
  end
266
+
267
+ context "when Sidekiq `redis_info` is not defined" do
268
+ before do
269
+ allow(Sidekiq).to receive(:respond_to?).with(:redis_info).and_return(false)
270
+ end
271
+
272
+ it "does not collect redis metrics" do
273
+ expect_gauge("connection_count", 2).never
274
+ expect_gauge("memory_usage", 1024).never
275
+ expect_gauge("memory_usage_rss", 512).never
276
+ probe.call
277
+ end
278
+ end
175
279
  end
176
280
 
177
281
  context "when hostname is configured for probe" do
@@ -179,6 +283,8 @@ describe Appsignal::Probes::SidekiqProbe do
179
283
  let(:probe) { described_class.new(:hostname => redis_hostname) }
180
284
 
181
285
  it "uses the redis hostname for the hostname tag" do
286
+ with_sidekiq!
287
+
182
288
  allow(Appsignal).to receive(:set_gauge).and_call_original
183
289
  log = capture_logs { probe }
184
290
  expect(log).to contains_log(
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appsignal
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.5
4
+ version: 3.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Beekman
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-10-18 00:00:00.000000000 Z
13
+ date: 2022-11-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack