gitlab-exporter 16.1.0 → 16.3.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: f8f9e18ad6f1758709b718bb67c3491f654a01078aa7835462a0e346731adff9
4
- data.tar.gz: affa763080262ed9621f7d51f8342aaebb2ca8cd5f6296b730a02a042d62b816
3
+ metadata.gz: f525375bfd6495a98af906badecaa459b07d6464327b47abd754e9a54b002522
4
+ data.tar.gz: 13388a0735f269ed0ad9c43a324e8e77a4c008ac2f8d9ec9a10a48a623886141
5
5
  SHA512:
6
- metadata.gz: 7148d67304d3605314d65ce4c33a4450f33853a086da26150ee19532353db76d05d43326de068894f5d88ee879496ead866917ca2753e37623affab5e9b02292
7
- data.tar.gz: 8d677307d6a128a01c695ce1cec716f31673032ad744bb600a89e713e9ae32ffa39e93ab22790d4e09fca6f485c1664e000ddf627d1bab31ad49e18d5e6f3891
6
+ metadata.gz: 0e754a5a16e88b93604313e719ae13441ffad1c4062d531c375aa11d7747a2aa4235037a42665d318b7534c3d6568ccc1f0c4fd8321cbed5fde3333e4a81bbbb
7
+ data.tar.gz: 230d9ac1d8925987027961bde296501e3dd665082f7f8140c29582997249f0342a721b58b5ad351e2c204c16afac46bdc1ee8ceed9095533a8614c7ad0f250b2
data/.gitlab-ci.yml CHANGED
@@ -62,7 +62,7 @@ rspec_integration:
62
62
  services:
63
63
  - name: redis:${REDIS_VERSION}
64
64
  alias: redis-master
65
- - name: bitnami/redis-sentinel:${REDIS_SENTINEL_VERSION}
65
+ - name: bitnamilegacy/redis-sentinel:${REDIS_SENTINEL_VERSION}
66
66
  alias: redis-sentinel
67
67
  command:
68
68
  - /bin/sh
data/Gemfile.lock CHANGED
@@ -1,11 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-exporter (16.1.0)
5
- connection_pool (= 2.5.3)
4
+ gitlab-exporter (16.3.0)
5
+ connection_pool (= 2.5.4)
6
6
  deep_merge (~> 1.2.2)
7
- faraday (= 2.13.4)
8
- pg (= 1.6.1)
7
+ faraday (= 2.14.0)
8
+ pg (= 1.6.2)
9
9
  puma (= 6.6.1)
10
10
  quantile (= 0.2.1)
11
11
  redis (= 4.8.1)
@@ -19,10 +19,10 @@ GEM
19
19
  specs:
20
20
  ast (2.4.3)
21
21
  base64 (0.2.0)
22
- connection_pool (2.5.3)
22
+ connection_pool (2.5.4)
23
23
  deep_merge (1.2.2)
24
24
  diff-lcs (1.5.0)
25
- faraday (2.13.4)
25
+ faraday (2.14.0)
26
26
  faraday-net_http (>= 2.0, < 3.5)
27
27
  json
28
28
  logger
@@ -38,7 +38,7 @@ GEM
38
38
  parser (3.3.9.0)
39
39
  ast (~> 2.4.1)
40
40
  racc
41
- pg (1.6.1)
41
+ pg (1.6.2)
42
42
  prism (1.4.0)
43
43
  puma (6.6.1)
44
44
  nio4r (~> 2.0)
@@ -66,7 +66,7 @@ GEM
66
66
  diff-lcs (>= 1.2.0, < 2.0)
67
67
  rspec-support (~> 3.12.0)
68
68
  rspec-support (3.12.0)
69
- rubocop (1.79.1)
69
+ rubocop (1.81.6)
70
70
  json (~> 2.3)
71
71
  language_server-protocol (~> 3.17.0.2)
72
72
  lint_roller (~> 1.1.0)
@@ -74,10 +74,10 @@ GEM
74
74
  parser (>= 3.3.0.2)
75
75
  rainbow (>= 2.2.2, < 4.0)
76
76
  regexp_parser (>= 2.9.3, < 3.0)
77
- rubocop-ast (>= 1.46.0, < 2.0)
77
+ rubocop-ast (>= 1.47.1, < 2.0)
78
78
  ruby-progressbar (~> 1.7)
79
79
  unicode-display_width (>= 2.4.0, < 4.0)
80
- rubocop-ast (1.46.0)
80
+ rubocop-ast (1.47.1)
81
81
  parser (>= 3.3.7.2)
82
82
  prism (~> 1.4)
83
83
  ruby-progressbar (1.13.0)
@@ -22,10 +22,10 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.required_ruby_version = Gem::Requirement.new(">= 3.0")
24
24
 
25
- s.add_runtime_dependency "connection_pool", "2.5.3"
25
+ s.add_runtime_dependency "connection_pool", "2.5.4"
26
26
  s.add_runtime_dependency "deep_merge", "~> 1.2.2"
27
- s.add_runtime_dependency "faraday", "2.13.4"
28
- s.add_runtime_dependency "pg", "1.6.1"
27
+ s.add_runtime_dependency "faraday", "2.14.0"
28
+ s.add_runtime_dependency "pg", "1.6.2"
29
29
  s.add_runtime_dependency "puma", "6.6.1"
30
30
  s.add_runtime_dependency "quantile", "0.2.1"
31
31
  s.add_runtime_dependency "redis", "4.8.1"
@@ -3,7 +3,8 @@ module GitLab
3
3
  module Database
4
4
  # A helper class to collect zoekt metrics.
5
5
  class ZoektCollector < Base
6
- QUERY = <<~SQL.freeze
6
+ # Query to get processing zoekt_tasks distribution by zoekt_node_id
7
+ ZOEKT_TASKS_PROCESSING_QUERY = <<~SQL.freeze
7
8
  WITH task_counts AS (
8
9
  SELECT
9
10
  zoekt_node_id,
@@ -26,6 +27,34 @@ module GitLab
26
27
  task_counts tc ON n.id = tc.zoekt_node_id
27
28
  SQL
28
29
 
30
+ ZOEKT_NODES_QUERY = <<~SQL.freeze
31
+ SELECT schema_version, id FROM zoekt_nodes
32
+ SQL
33
+
34
+ ZOEKT_NODES_STATUS_QUERY = <<~SQL.freeze
35
+ SELECT
36
+ id,
37
+ CASE
38
+ WHEN last_seen_at < NOW() - INTERVAL '2 minute' THEN 0
39
+ ELSE 1
40
+ END AS status
41
+ FROM zoekt_nodes;
42
+ SQL
43
+
44
+ ZOEKT_REPOSITORY_SCHEMA_VERSION_QUERY = <<~SQL.freeze
45
+ SELECT
46
+ COUNT(*)
47
+ FROM
48
+ zoekt_repositories
49
+ INNER JOIN
50
+ zoekt_indices
51
+ ON zoekt_repositories.zoekt_index_id = zoekt_indices.id
52
+ WHERE
53
+ zoekt_indices.zoekt_node_id = $1
54
+ AND zoekt_repositories.schema_version < $2
55
+ AND zoekt_repositories.state = 10;
56
+ SQL
57
+
29
58
  ZOEKT_ENABLED_QUERY = <<~SQL.freeze
30
59
  SELECT
31
60
  zoekt_settings ->> 'zoekt_indexing_enabled' AS zoekt_indexing_enabled
@@ -35,13 +64,50 @@ module GitLab
35
64
  SQL
36
65
 
37
66
  def run
38
- return unless zoekt_indexing_enabled?
67
+ return {} unless zoekt_indexing_enabled?
39
68
 
40
- execute(QUERY, [Time.now.utc])
69
+ {
70
+ task_processing_query_result: execute(ZOEKT_TASKS_PROCESSING_QUERY, [Time.now.utc]),
71
+ repositories_schema_version_query_result: repositories_schema_version_query_result,
72
+ zoekt_nodes_status_query_result: execute(ZOEKT_NODES_STATUS_QUERY)
73
+ }.compact
41
74
  end
42
75
 
43
76
  private
44
77
 
78
+ def repositories_schema_version_query_result
79
+ hash = zoekt_node_schema_version_hash
80
+ return if hash.nil?
81
+
82
+ zoekt_repository_schema_version_result(hash)
83
+ end
84
+
85
+ def zoekt_node_schema_version_hash
86
+ zoekt_nodes = execute(ZOEKT_NODES_QUERY)
87
+ return if zoekt_nodes.nil?
88
+
89
+ hash = {}
90
+ zoekt_nodes.each do |row|
91
+ hash[row["id"]] = row["schema_version"]
92
+ end
93
+ hash
94
+ end
95
+
96
+ def zoekt_repository_schema_version_result(hash)
97
+ result = Set.new
98
+ hash.each do |id, schema_version|
99
+ query_result = execute(ZOEKT_REPOSITORY_SCHEMA_VERSION_QUERY, [id, schema_version])
100
+ if query_result.nil?
101
+ result = nil
102
+ break
103
+ end
104
+
105
+ count = query_result[0]["count"].to_i
106
+ result.add({ target_schema_version: schema_version, zoekt_node_id: id, unfinished_repository_count: count })
107
+ end
108
+ result
109
+ end
110
+
45
111
  def zoekt_indexing_enabled?
46
112
  @zoekt_indexing_enabled ||=
47
113
  begin
@@ -53,7 +119,7 @@ module GitLab
53
119
  end
54
120
  end
55
121
 
56
- def execute(query, params)
122
+ def execute(query, params = [])
57
123
  with_connection_pool do |conn|
58
124
  conn.exec_params(query, params)
59
125
  end
@@ -64,9 +130,23 @@ module GitLab
64
130
 
65
131
  # The prober which is called when gathering metrics
66
132
  class ZoektProber
67
- PrometheusMetrics.describe("search_zoekt_task_processing_queue_size",
68
- "Number of tasks waiting to be processed by Zoekt",
69
- "gauge")
133
+ PrometheusMetrics.describe(
134
+ "search_zoekt_task_processing_queue_size",
135
+ "Number of tasks waiting to be processed by Zoekt",
136
+ "gauge"
137
+ )
138
+
139
+ PrometheusMetrics.describe(
140
+ "search_zoekt_repositories_schema_version_count",
141
+ "Number of zoekt_repositories which do not have the latest schema version",
142
+ "gauge"
143
+ )
144
+
145
+ PrometheusMetrics.describe(
146
+ "search_zoekt_nodes_status",
147
+ "Status of each zoekt_node. 0 is offline (last seen more than 2 minutes ago), 1 is online",
148
+ "gauge"
149
+ )
70
150
 
71
151
  def initialize(metrics: PrometheusMetrics.new, **opts)
72
152
  @metrics = metrics
@@ -75,13 +155,14 @@ module GitLab
75
155
 
76
156
  def probe_db
77
157
  results = @collector.run
78
- results.to_a.each do |row|
79
- @metrics.add(
80
- "search_zoekt_task_processing_queue_size",
81
- row["task_count"].to_i,
82
- node_name: row["node_name"],
83
- node_id: row["node_id"]
84
- )
158
+ results[:task_processing_query_result].to_a.each do |row|
159
+ add_processing_zoekt_tasks_to_metric(row)
160
+ end
161
+ results[:repositories_schema_version_query_result]&.each do |row|
162
+ add_zoekt_repositories_by_schema_version_to_metric(row)
163
+ end
164
+ results[:zoekt_nodes_status_query_result]&.each do |row|
165
+ add_zoekt_nodes_status_to_metric(row)
85
166
  end
86
167
 
87
168
  self
@@ -89,6 +170,32 @@ module GitLab
89
170
  self
90
171
  end
91
172
 
173
+ def add_processing_zoekt_tasks_to_metric(row)
174
+ @metrics.add(
175
+ "search_zoekt_task_processing_queue_size",
176
+ row["task_count"].to_i,
177
+ node_name: row["node_name"],
178
+ node_id: row["node_id"]
179
+ )
180
+ end
181
+
182
+ def add_zoekt_repositories_by_schema_version_to_metric(row)
183
+ @metrics.add(
184
+ "search_zoekt_repositories_schema_version_count",
185
+ row[:unfinished_repository_count].to_i,
186
+ target_schema_version: row[:target_schema_version],
187
+ zoekt_node_id: row[:zoekt_node_id]
188
+ )
189
+ end
190
+
191
+ def add_zoekt_nodes_status_to_metric(row)
192
+ @metrics.add(
193
+ "search_zoekt_nodes_status",
194
+ row["status"].to_i,
195
+ zoekt_node_id: row["id"]
196
+ )
197
+ end
198
+
92
199
  def write_to(target)
93
200
  target.write(@metrics.to_s)
94
201
  end
@@ -1,5 +1,5 @@
1
1
  module GitLab
2
2
  module Exporter
3
- VERSION = "16.1.0".freeze
3
+ VERSION = "16.3.0".freeze
4
4
  end
5
5
  end
@@ -4,8 +4,15 @@ require "gitlab_exporter/database/zoekt"
4
4
  describe GitLab::Exporter::Database::ZoektCollector do
5
5
  let(:connection_pool) { double("connection pool") }
6
6
  let(:connection) { double("connection") }
7
- let(:query) { described_class::QUERY }
7
+ let(:zoekt_tasks_processing_query) { described_class::ZOEKT_TASKS_PROCESSING_QUERY }
8
+ let(:zoekt_nodes_query) { described_class::ZOEKT_NODES_QUERY }
9
+ let(:zoekt_nodes_query_results) { [{ "id" => "1", "schema_version" => "2302" }] }
8
10
  let(:zoekt_enabled_query) { described_class::ZOEKT_ENABLED_QUERY }
11
+ let(:zoekt_repository_schema_version_query) { described_class::ZOEKT_REPOSITORY_SCHEMA_VERSION_QUERY }
12
+ let(:zoekt_nodes_status_query) { described_class::ZOEKT_NODES_STATUS_QUERY }
13
+ let(:zoekt_nodes_status_query_results) { [{ "id" => "1", "status" => "1" }] }
14
+
15
+ let(:zoekt_repository_schema_version_query_results) { [{ "count" => "1" }] }
9
16
 
10
17
  subject(:collector) { described_class.new(connection_string: "host=localhost") }
11
18
 
@@ -26,13 +33,25 @@ describe GitLab::Exporter::Database::ZoektCollector do
26
33
  describe "#run" do
27
34
  let(:zoekt_enabled_results) {}
28
35
  let(:frozen_time) { Time.new(2023, 1, 1, 0, 0, 0, 0) }
29
- let(:query_results) do
36
+ let(:zoekt_tasks_processing_query_results) do
30
37
  [
31
38
  { "node_id" => "1", "node_name" => "zoekt-1", "task_count" => "5" },
32
39
  { "node_id" => "2", "node_name" => "zoekt-2", "task_count" => "10" }
33
40
  ]
34
41
  end
35
42
 
43
+ let(:zoekt_repositories_schema_version_query_results) do
44
+ Set.new([{ target_schema_version: "2302", zoekt_node_id: "1", unfinished_repository_count: 1 }])
45
+ end
46
+
47
+ let(:result) do
48
+ {
49
+ repositories_schema_version_query_result: zoekt_repositories_schema_version_query_results,
50
+ task_processing_query_result: zoekt_tasks_processing_query_results,
51
+ zoekt_nodes_status_query_result: zoekt_nodes_status_query_results
52
+ }
53
+ end
54
+
36
55
  before do
37
56
  allow(Time).to receive(:now).and_return(frozen_time)
38
57
  end
@@ -42,10 +61,8 @@ describe GitLab::Exporter::Database::ZoektCollector do
42
61
  stub_zoekt_not_enabled
43
62
  end
44
63
 
45
- it "returns nil" do
46
- allow(connection).to receive(:exec_params).with(query, frozen_time).and_raise(PG::UndefinedTable)
47
-
48
- expect(collector.run).to be_nil
64
+ it "returns {}" do
65
+ expect(collector.run).to eq({})
49
66
  end
50
67
  end
51
68
 
@@ -54,25 +71,43 @@ describe GitLab::Exporter::Database::ZoektCollector do
54
71
  stub_zoekt_enabled
55
72
  end
56
73
 
57
- it "executes the query with the current time" do
58
- expect(connection).to receive(:exec_params).with(query, [frozen_time]).and_return(query_results)
59
-
60
- expect(collector.run).to eq(query_results)
74
+ it "executes the query with correct params" do
75
+ expect(connection).to receive(:exec_params).with(zoekt_tasks_processing_query, [frozen_time])
76
+ .and_return(zoekt_tasks_processing_query_results)
77
+ expect(connection).to receive(:exec_params).with(zoekt_nodes_query, [])
78
+ .and_return(zoekt_nodes_query_results)
79
+ expect(connection).to receive(:exec_params).with(zoekt_repository_schema_version_query, %w[1 2302])
80
+ .and_return(zoekt_repository_schema_version_query_results)
81
+ expect(connection).to receive(:exec_params).with(zoekt_nodes_status_query, [])
82
+ .and_return(zoekt_nodes_status_query_results)
83
+
84
+ expect(collector.run).to eq(result)
61
85
  end
62
86
 
63
87
  context "when PG::UndefinedTable is raised" do
64
- it "returns nil" do
65
- allow(connection).to receive(:exec_params).with(query, [frozen_time]).and_raise(PG::UndefinedTable)
66
-
67
- expect(collector.run).to be_nil
88
+ it "does not includes the key which got the exception" do
89
+ allow(connection).to receive(:exec_params).with(zoekt_tasks_processing_query, [frozen_time])
90
+ .and_raise(PG::UndefinedTable)
91
+ allow(connection).to receive(:exec_params).with(zoekt_nodes_query, [])
92
+ .and_raise(PG::UndefinedTable)
93
+ allow(connection).to receive(:exec_params).with(zoekt_nodes_status_query, [])
94
+ .and_raise(PG::UndefinedTable)
95
+
96
+ expect(collector.run).to eq({})
68
97
  end
69
98
  end
70
99
 
71
100
  context "when PG::UndefinedColumn is raised" do
72
- it "returns nil" do
73
- allow(connection).to receive(:exec_params).with(query, [frozen_time]).and_raise(PG::UndefinedColumn)
74
-
75
- expect(collector.run).to be_nil
101
+ it "does not includes the key which got the exception" do
102
+ allow(connection).to receive(:exec_params).with(zoekt_tasks_processing_query, [frozen_time])
103
+ .and_return(zoekt_tasks_processing_query_results)
104
+ expect(connection).to receive(:exec_params).with(zoekt_nodes_query, [])
105
+ .and_return(zoekt_nodes_query_results)
106
+ expect(connection).to receive(:exec_params).with(zoekt_repository_schema_version_query, %w[1 2302])
107
+ .and_raise(PG::UndefinedTable)
108
+ expect(connection).to receive(:exec_params).with(zoekt_nodes_status_query, []).and_raise(PG::UndefinedTable)
109
+
110
+ expect(collector.run).to eq({ task_processing_query_result: zoekt_tasks_processing_query_results })
76
111
  end
77
112
  end
78
113
  end
@@ -99,10 +134,15 @@ describe GitLab::Exporter::Database::ZoektProber do
99
134
  let(:metrics) { double("PrometheusMetrics", add: nil) }
100
135
  let(:collector) { double(GitLab::Exporter::Database::ZoektCollector, run: data) }
101
136
  let(:data) do
102
- [
103
- { "node_id" => "1", "node_name" => "zoekt-1", "task_count" => "5" },
104
- { "node_id" => "2", "node_name" => "zoekt-2", "task_count" => "10" }
105
- ]
137
+ {
138
+ repositories_schema_version_query_result: Set.new(
139
+ [{ target_schema_version: "2302", zoekt_node_id: "1", unfinished_repository_count: 1 }]
140
+ ),
141
+ task_processing_query_result: [
142
+ { "node_id" => "1", "node_name" => "zoekt-1", "task_count" => "5" },
143
+ { "node_id" => "2", "node_name" => "zoekt-2", "task_count" => "10" }
144
+ ]
145
+ }
106
146
  end
107
147
 
108
148
  describe "#probe_db" do
@@ -123,7 +163,7 @@ describe GitLab::Exporter::Database::ZoektProber do
123
163
  it "adds metrics for each node" do
124
164
  expect(collector).to receive(:run).and_return(data)
125
165
 
126
- data.each do |node_data|
166
+ data[:task_processing_query_result].each do |node_data|
127
167
  expect(metrics).to receive(:add)
128
168
  .with("search_zoekt_task_processing_queue_size",
129
169
  node_data["task_count"].to_i,
@@ -131,6 +171,16 @@ describe GitLab::Exporter::Database::ZoektProber do
131
171
  node_id: node_data["node_id"])
132
172
  end
133
173
 
174
+ data[:repositories_schema_version_query_result].each do |node_data|
175
+ expect(metrics).to receive(:add)
176
+ .with(
177
+ "search_zoekt_repositories_schema_version_count",
178
+ node_data[:unfinished_repository_count].to_i,
179
+ target_schema_version: node_data[:target_schema_version],
180
+ zoekt_node_id: node_data[:zoekt_node_id]
181
+ )
182
+ end
183
+
134
184
  probe_db
135
185
  end
136
186
  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: 16.1.0
4
+ version: 16.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Carranza
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.5.3
19
+ version: 2.5.4
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 2.5.3
26
+ version: 2.5.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: deep_merge
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,28 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 2.13.4
47
+ version: 2.14.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 2.13.4
54
+ version: 2.14.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: pg
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.6.1
61
+ version: 1.6.2
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 1.6.1
68
+ version: 1.6.2
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: puma
71
71
  requirement: !ruby/object:Gem::Requirement