gitlab-exporter 14.4.0 → 15.0.0

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: e925093b6d87edda1419b3b92a1166f599084a24768cc0082cb3f2d2e662fc37
4
- data.tar.gz: 89a3598b636def73036a3ae4e1f9982a420fb4c04376039ac769b0e38ff6bc68
3
+ metadata.gz: aa3c6ff71709207bbbe1c85dea19eab223c678c721baf437eed2275ad73816b9
4
+ data.tar.gz: f263b55d0e45ece0a7d3124511c684eacbe78532eae81e2f4c11f3ec4279af9b
5
5
  SHA512:
6
- metadata.gz: cfd9e51c7dd85bba95f79e618fdb33a5e5f81cb8626352fb335861aeacfecb80f896e76d124f73ffdf46d9552ef37fb757d6f2a3ddc78fb49b402faf8caecb52
7
- data.tar.gz: a0d0f3d11bb8f09ae1a7a0d5a9f8f4a038a400a616850c5e12d8f48ad05ac74eea5cf4db0c3770905e8e2d1fbab3ab85f43dbc7da8e728b2ff2065077f733ee0
6
+ metadata.gz: 8db3f5dd5db87f02d7a85fb58c13e8a48df40726c5718fd82d5b7ae792675948bd43664da3f94075527e5242c0dcf8bc5e150f8606611097677a812981d73354
7
+ data.tar.gz: 9411698d4c809eba8997bd8fc0f9cc4295dac625daa35a8faf37604909a20fde621afb161534bd82fa912087cf50de45e5e192186627cb95f5c8b5643de1742e
data/.gitlab-ci.yml CHANGED
@@ -50,9 +50,32 @@ rspec_integration:
50
50
  - bundle exec rspec spec -t integration -f d -c
51
51
  before_script: *before_scripts
52
52
  services:
53
- - redis:latest
53
+ - name: redis:${REDIS_VERSION}
54
+ alias: redis-master
55
+ - name: bitnami/redis-sentinel:${REDIS_SENTINEL_VERSION}
56
+ alias: redis-sentinel
57
+ command:
58
+ - /bin/sh
59
+ - -c
60
+ - |
61
+ echo "Starting Redis Sentinel..."
62
+ cat <<EOF > /opt/bitnami/redis-sentinel/etc/sentinel.conf
63
+ user default off
64
+ user ${REDIS_SENTINEL_USERNAME} on >${REDIS_SENTINEL_PASSWORD} +@all
65
+ sentinel monitor mymaster redis-master 6379 2
66
+ sentinel resolve-hostnames yes
67
+ sentinel down-after-milliseconds mymaster 5000
68
+ EOF
69
+ redis-sentinel /opt/bitnami/redis-sentinel/etc/sentinel.conf
70
+
54
71
  variables:
55
72
  REDIS_URL: "redis://redis"
73
+ REDIS_SENTINEL_URL: "redis://mymaster"
74
+ REDIS_SENTINELS: "redis-sentinel:26379"
75
+ REDIS_VERSION: latest
76
+ REDIS_SENTINEL_VERSION: latest
77
+ REDIS_SENTINEL_USERNAME: "my-sentinel-username"
78
+ REDIS_SENTINEL_PASSWORD: "my-sentinel-password"
56
79
  parallel:
57
80
  matrix:
58
81
  - RUBY_VERSION: ["2.7", "3.0", "3.1", "3.2"]
data/Gemfile.lock CHANGED
@@ -1,16 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-exporter (14.4.0)
4
+ gitlab-exporter (15.0.0)
5
5
  connection_pool (= 2.2.5)
6
6
  deep_merge (~> 1.2.2)
7
7
  faraday (>= 1.8.0, <= 2.8.1)
8
8
  pg (= 1.5.3)
9
9
  puma (= 5.6.8)
10
10
  quantile (= 0.2.1)
11
- redis (= 4.4.0)
11
+ redis (= 4.5.0)
12
12
  redis-namespace (= 1.9.0)
13
- sidekiq (= 6.4.0)
13
+ sidekiq (= 6.5.12)
14
14
  sinatra (~> 2.2.0)
15
15
  webrick (~> 1.7)
16
16
 
@@ -41,7 +41,7 @@ GEM
41
41
  rack-protection (2.2.4)
42
42
  rack
43
43
  rainbow (3.0.0)
44
- redis (4.4.0)
44
+ redis (4.5.0)
45
45
  redis-namespace (1.9.0)
46
46
  redis (>= 4)
47
47
  regexp_parser (2.0.3)
@@ -72,10 +72,10 @@ GEM
72
72
  parser (>= 2.7.1.5)
73
73
  ruby-progressbar (1.11.0)
74
74
  ruby2_keywords (0.0.5)
75
- sidekiq (6.4.0)
76
- connection_pool (>= 2.2.2)
75
+ sidekiq (6.5.12)
76
+ connection_pool (>= 2.2.5, < 3)
77
77
  rack (~> 2.0)
78
- redis (>= 4.2.0)
78
+ redis (>= 4.5.0, < 5)
79
79
  sinatra (2.2.4)
80
80
  mustermann (~> 2.0)
81
81
  rack (~> 2.2)
@@ -98,6 +98,14 @@ probes:
98
98
  # redis_username: 'redis-username'
99
99
  # redis_password: 'redis-password'
100
100
  redis_enable_client: true
101
+ # Uncomment if Redis Sentinels are needed
102
+ # redis_sentinels:
103
+ # - host: 'localhost'
104
+ # port: 26380
105
+ # - host: 'localhost'
106
+ # port: 26381
107
+ # redis_sentinel_username: 'redis-sentinel-username'
108
+ # redis_sentinel_password: 'redis-sentinel-password'
101
109
 
102
110
  ruby: &ruby
103
111
  class_name: RubyProber
@@ -28,9 +28,9 @@ Gem::Specification.new do |s|
28
28
  s.add_runtime_dependency "pg", "1.5.3"
29
29
  s.add_runtime_dependency "puma", "5.6.8"
30
30
  s.add_runtime_dependency "quantile", "0.2.1"
31
- s.add_runtime_dependency "redis", "4.4.0"
31
+ s.add_runtime_dependency "redis", "4.5.0"
32
32
  s.add_runtime_dependency "redis-namespace", "1.9.0"
33
- s.add_runtime_dependency "sidekiq", "6.4.0"
33
+ s.add_runtime_dependency "sidekiq", "6.5.12"
34
34
  s.add_runtime_dependency "sinatra", "~> 2.2.0"
35
35
  s.add_runtime_dependency "webrick", "~> 1.7"
36
36
 
@@ -297,12 +297,24 @@ module GitLab
297
297
  @target = File.open(@target, "a") if @target.is_a?(String)
298
298
  end
299
299
 
300
- def options(args)
300
+ def options(args) # rubocop:disable Metrics/MethodLength
301
301
  args.options do |opts|
302
302
  opts.banner = "Usage: #{EXECUTABLE_NAME} #{COMMAND_NAME} [options]"
303
303
  opts.on("--redis-url=\"redis://localhost:6379\"", "Redis URL") do |val|
304
304
  @redis_url = val
305
305
  end
306
+ opts.on("--redis-sentinel-username=\"my-sentinel-username\"", "Redis Sentinel username") do |val|
307
+ @redis_sentinel_username = val
308
+ end
309
+ opts.on("--redis-sentinel-password=\"my-sentinel-password\"", "Redis Sentinel password") do |val|
310
+ @redis_sentinel_password = val
311
+ end
312
+ opts.on("--redis-sentinels=HOST1:PORT1,HOST2:PORT2", Array, "List of Redis Sentinels") do |val|
313
+ @redis_sentinels = val.map { |item|
314
+ host, port = item.split(":")
315
+ { host: host, port: port.to_i }
316
+ }
317
+ end
306
318
  end
307
319
  end
308
320
 
@@ -313,13 +325,19 @@ module GitLab
313
325
  def run
314
326
  validate!
315
327
 
316
- ::GitLab::Exporter::SidekiqProber.new(redis_url: @redis_url)
317
- .probe_stats
318
- .probe_queues
319
- .probe_jobs_limit
320
- .probe_workers
321
- .probe_retries
322
- .write_to(@target)
328
+ prober = ::GitLab::Exporter::SidekiqProber.new(redis_url: @redis_url,
329
+ redis_sentinels: @redis_sentinels,
330
+ redis_sentinel_username: @redis_sentinel_username,
331
+ redis_sentinel_password: @redis_sentinel_password,
332
+ logger: Logger.new(STDERR))
333
+
334
+ prober
335
+ .probe_stats
336
+ .probe_queues
337
+ .probe_jobs_limit
338
+ .probe_workers
339
+ .probe_retries
340
+ .write_to(@target)
323
341
  end
324
342
 
325
343
  private
@@ -62,6 +62,10 @@ module GitLab
62
62
  conn.reset
63
63
  raise e
64
64
  end
65
+ rescue PG::ConnectionBad => e
66
+ @logger.error "Bad connection to the database, resetting pool: #{e}" if @logger
67
+ connection_pool.reload(&:close)
68
+ raise e
65
69
  rescue PG::Error => e
66
70
  @logger.error "Error connecting to the database: #{e}" if @logger
67
71
  raise e
@@ -7,7 +7,7 @@ module GitLab
7
7
  # A prober for Sidekiq queues
8
8
  #
9
9
  # It takes the Redis URL Sidekiq is connected to
10
- class SidekiqProber
10
+ class SidekiqProber # rubocop:disable Metrics/ClassLength
11
11
  # The maximum depth (from the head) of each queue to probe. Probing the
12
12
  # entirety of a very large queue will take longer and run the risk of
13
13
  # timing out. But when we have a very large queue, we are most in need of
@@ -195,6 +195,7 @@ module GitLab
195
195
  def redis_options
196
196
  options = {
197
197
  url: @opts[:redis_url],
198
+ sentinels: redis_sentinel_options,
198
199
  connect_timeout: 1,
199
200
  reconnect_attempts: 0
200
201
  }
@@ -207,6 +208,19 @@ module GitLab
207
208
  options
208
209
  end
209
210
 
211
+ def redis_sentinel_options
212
+ sentinels = @opts[:redis_sentinels]
213
+
214
+ return sentinels unless sentinels.is_a?(Array)
215
+
216
+ sentinels.each do |sentinel_config|
217
+ sentinel_config[:username] = @opts[:redis_sentinel_username] if @opts.key?(:redis_sentinel_username)
218
+ sentinel_config[:password] = @opts[:redis_sentinel_password] if @opts.key?(:redis_sentinel_password)
219
+ end
220
+
221
+ sentinels
222
+ end
223
+
210
224
  def redis_enable_client?
211
225
  return true if @opts[:redis_enable_client].nil?
212
226
 
@@ -221,6 +235,8 @@ module GitLab
221
235
  end
222
236
  rescue Redis::BaseConnectionError => e
223
237
  @logger&.error "Error connecting to the Redis: #{e}"
238
+ pool = self.class.connection_pool[redis_options]
239
+ pool.reload(&:close)
224
240
  @connected = false
225
241
  end
226
242
  end
@@ -1,5 +1,5 @@
1
1
  module GitLab
2
2
  module Exporter
3
- VERSION = "14.4.0".freeze
3
+ VERSION = "15.0.0".freeze
4
4
  end
5
5
  end
@@ -290,6 +290,22 @@ describe GitLab::Exporter::Database do
290
290
  expect(output).to match(/^ci_stale_builds 0.0$/m)
291
291
  end
292
292
  end
293
+
294
+ context "when PG connection shuts down" do
295
+ before do
296
+ allow(connection).to receive(:exec).and_raise(PG::ConnectionBad)
297
+ end
298
+
299
+ it "responds with Prometheus metrics" do
300
+ expect(connection_pool).to receive(:reload)
301
+
302
+ prober.probe_db
303
+ prober.write_to(writer)
304
+ output = writer.string
305
+
306
+ expect(output).to be_empty
307
+ end
308
+ end
293
309
  end
294
310
 
295
311
  context "when executed on EE" do
@@ -6,6 +6,13 @@ module GitLab
6
6
  module CLI
7
7
  describe SidekiqRunner, :integration do
8
8
  let(:redis_url) { ENV.fetch("REDIS_URL", "redis://localhost:6379") }
9
+ let(:redis_sentinel_url) { ENV.fetch("REDIS_SENTINEL_URL", "redis://mymaster:6379") }
10
+ let(:redis_sentinel_username) { ENV.fetch("REDIS_SENTINEL_USERNAME", "my-sentinel-user") }
11
+ let(:redis_sentinel_password) { ENV.fetch("REDIS_SENTINEL_PASSWORD", "my-sentinel-password") }
12
+ let(:redis_sentinels) do
13
+ sentinels = ENV.fetch("REDIS_SENTINELS", "localhost:26379")
14
+ sentinels.split(" ")
15
+ end
9
16
  let(:io) { StringIO.new }
10
17
 
11
18
  it "can properly reach out to redis" do
@@ -14,6 +21,16 @@ module GitLab
14
21
 
15
22
  expect { runner.run }.not_to raise_error
16
23
  end
24
+
25
+ it "can properly reach out to redis-sentinel" do
26
+ args = CLIArgs.new([io], options: { /^--redis-url/ => redis_sentinel_url,
27
+ /^--redis-sentinel-username/ => redis_sentinel_username,
28
+ /^--redis-sentinel-password/ => redis_sentinel_password,
29
+ /^--redis-sentinels/ => redis_sentinels })
30
+ runner = SidekiqRunner.new(args)
31
+
32
+ expect { runner.run }.not_to raise_error
33
+ end
17
34
  end
18
35
  end
19
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-exporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 14.4.0
4
+ version: 15.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Carranza
@@ -106,14 +106,14 @@ dependencies:
106
106
  requirements:
107
107
  - - '='
108
108
  - !ruby/object:Gem::Version
109
- version: 4.4.0
109
+ version: 4.5.0
110
110
  type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - '='
115
115
  - !ruby/object:Gem::Version
116
- version: 4.4.0
116
+ version: 4.5.0
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: redis-namespace
119
119
  requirement: !ruby/object:Gem::Requirement
@@ -134,14 +134,14 @@ dependencies:
134
134
  requirements:
135
135
  - - '='
136
136
  - !ruby/object:Gem::Version
137
- version: 6.4.0
137
+ version: 6.5.12
138
138
  type: :runtime
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - '='
143
143
  - !ruby/object:Gem::Version
144
- version: 6.4.0
144
+ version: 6.5.12
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: sinatra
147
147
  requirement: !ruby/object:Gem::Requirement
@@ -278,7 +278,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
278
278
  - !ruby/object:Gem::Version
279
279
  version: '0'
280
280
  requirements: []
281
- rubygems_version: 3.3.26
281
+ rubygems_version: 3.3.27
282
282
  signing_key:
283
283
  specification_version: 4
284
284
  summary: GitLab metrics exporter