gitlab-exporter 14.4.0 → 15.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +24 -1
- data/Gemfile.lock +7 -7
- data/config/gitlab-exporter.yml.example +8 -0
- data/gitlab-exporter.gemspec +2 -2
- data/lib/gitlab_exporter/cli.rb +26 -8
- data/lib/gitlab_exporter/database/base.rb +4 -0
- data/lib/gitlab_exporter/sidekiq.rb +17 -1
- data/lib/gitlab_exporter/version.rb +1 -1
- data/spec/database/ci_builds_spec.rb +16 -0
- data/spec/integration/cli_spec.rb +17 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa3c6ff71709207bbbe1c85dea19eab223c678c721baf437eed2275ad73816b9
|
4
|
+
data.tar.gz: f263b55d0e45ece0a7d3124511c684eacbe78532eae81e2f4c11f3ec4279af9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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 (
|
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.
|
11
|
+
redis (= 4.5.0)
|
12
12
|
redis-namespace (= 1.9.0)
|
13
|
-
sidekiq (= 6.
|
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.
|
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.
|
76
|
-
connection_pool (>= 2.2.
|
75
|
+
sidekiq (6.5.12)
|
76
|
+
connection_pool (>= 2.2.5, < 3)
|
77
77
|
rack (~> 2.0)
|
78
|
-
redis (>= 4.
|
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
|
data/gitlab-exporter.gemspec
CHANGED
@@ -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.
|
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.
|
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
|
|
data/lib/gitlab_exporter/cli.rb
CHANGED
@@ -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
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
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
|
@@ -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:
|
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.
|
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.
|
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.
|
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.
|
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.
|
281
|
+
rubygems_version: 3.3.27
|
282
282
|
signing_key:
|
283
283
|
specification_version: 4
|
284
284
|
summary: GitLab metrics exporter
|