gitlab-exporter 6.0.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1378d48a7af04eee678edaa21da6d5795baa5828d0b06853b816e8c6b8e8d489
4
- data.tar.gz: e221a2070050abee80662777a94afee1d4369ae8f108583f28f640cc2fc2517b
3
+ metadata.gz: 61203f2c5d53c61f05151255076c5004c65a254c2445d632ae8c7262ae0e1f82
4
+ data.tar.gz: 66b13da650dd0e66b3a4d639bf1738de51474e047e0df878893a5b675d158827
5
5
  SHA512:
6
- metadata.gz: d7c222835cd8bc99f412f95fb17457310857634b4c9c9b9b2ffb3a1f5b7002b05445f6331f4e0cdd74a4319d4bf0730e68070acd043168b65d8bfacf52da1e88
7
- data.tar.gz: e4d5aababedf60ee0865f5b9c455011f0941acb2d8ad0bb21bb6c4a2021aeba23ac3d2123238d8cc7932e70bc508dca43f3e396031b57b199c6aff752d86d457
6
+ metadata.gz: 7ab02d67cc6e2bf4e443e73f49138eb7549961d535a1c7425e7f9a7872ec7095f6ad77522105eee8111c674cbdebbfec304296953c884dd006832d452079414c
7
+ data.tar.gz: 81bf3b39c8cb1462dabbf51be56057efb9fddfbe0db6da4d6f1f7827f71f4a8cebf04e5890caf07ccaa588b873897dfef32e91d7276361a6fe629349eb2691b0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-exporter (6.0.0)
4
+ gitlab-exporter (6.1.0)
5
5
  connection_pool (~> 2.2.1)
6
6
  pg (~> 1.1)
7
7
  quantile (~> 0.2.0)
@@ -23,7 +23,7 @@ GEM
23
23
  pg (1.2.2)
24
24
  powerpack (0.1.1)
25
25
  quantile (0.2.1)
26
- rack (2.1.2)
26
+ rack (2.2.2)
27
27
  rack-protection (2.0.8.1)
28
28
  rack
29
29
  rainbow (2.1.0)
@@ -60,6 +60,9 @@ probes:
60
60
  - soft_deleted_projects
61
61
  - orphaned_projects
62
62
  - uploads
63
+ - users
64
+ - projects
65
+ - groups
63
66
  remote_mirrors:
64
67
  class_name: Database::RemoteMirrorsProber
65
68
  <<: *db_common
@@ -79,7 +79,40 @@ module GitLab
79
79
  joins: "LEFT JOIN namespaces ON projects.namespace_id = namespaces.id",
80
80
  where: "namespaces.id IS NULL"
81
81
  },
82
- uploads: { select: :uploads }
82
+ uploads: { select: :uploads },
83
+ users: {
84
+ select: :users,
85
+ joins: "LEFT JOIN
86
+ (
87
+ SELECT
88
+ members.user_id,
89
+ MAX(access_level) as access_level
90
+ FROM members
91
+ GROUP BY members.user_id
92
+ ) AS u
93
+ ON users.id = u.user_id",
94
+ where: "ghost IS NULL AND bot_type IS NULL",
95
+ fields: {
96
+ admin: {},
97
+ external: {},
98
+ state: {},
99
+ access_level: { definition: "COALESCE(u.access_level, 0)" }
100
+ }
101
+ },
102
+ projects: {
103
+ select: :projects,
104
+ fields: {
105
+ visibility_level: {},
106
+ archived: {}
107
+ }
108
+ },
109
+ groups: {
110
+ select: :namespaces,
111
+ fields: {
112
+ visibility_level: {},
113
+ root: { definition: "(parent_id IS NULL)" }
114
+ }
115
+ }
83
116
  }.freeze
84
117
 
85
118
  def initialize(args)
@@ -105,21 +138,37 @@ module GitLab
105
138
 
106
139
  def count_from_query_hash(query_hash)
107
140
  result = execute(construct_query(query_hash))
108
- return 0 unless result
141
+ return [{ "count": 0, "labels": {} }] unless result
109
142
 
110
- result[0]["count"]
143
+ result.map do |row|
144
+ labels = {}
145
+ (query_hash[:fields] || []).each do |key, _| labels[key] = row[key.to_s] end
146
+ { "count": row["count"], "labels": labels }
147
+ end
111
148
  end
112
149
 
113
150
  def successful_check?(query)
114
151
  result = execute("SELECT EXISTS (#{query})")
115
152
  return unless result
116
153
 
117
- result[0]["exists"] == "t"
154
+ result[0]["exists"]
118
155
  end
119
156
 
120
157
  def execute(query)
121
158
  with_connection_pool do |conn|
122
- conn.exec(query)
159
+ tm = PG::BasicTypeMapForResults.new(conn)
160
+
161
+ # Remove warning message:
162
+ # Warning: no type cast defined for type "name" with oid 19.
163
+ # Please cast this type explicitly to TEXT to be safe for future changes.
164
+ # Warning: no type cast defined for type "regproc" with oid 24.
165
+ # Please cast this type explicitly to TEXT to be safe for future changes.
166
+ [{ "type": "text", "oid": 19 }, { "type": "int4", "oid": 24 }].each do |value|
167
+ old_coder = tm.coders.find { |c| c.name == value[:type] }
168
+ tm.add_coder(old_coder.dup.tap { |c| c.oid = value[:oid] })
169
+ end
170
+
171
+ conn.exec(query).map_types!(tm)
123
172
  end
124
173
  rescue PG::UndefinedTable, PG::UndefinedColumn
125
174
  nil
@@ -127,9 +176,16 @@ module GitLab
127
176
 
128
177
  # Not private so I can test it without meta programming tricks
129
178
  def construct_query(query)
130
- query_string = "SELECT COUNT(*) FROM #{query[:select]} "
131
- query_string << "#{query[:joins]} " if query[:joins]
132
- query_string << "WHERE #{query[:where]}" if query[:where]
179
+ query_string = "SELECT COUNT(*)"
180
+ (query[:fields] || []).each do |key, value|
181
+ query_string << ", "
182
+ query_string << "(#{value[:definition]}) AS " if value[:definition]
183
+ query_string << key.to_s
184
+ end
185
+ query_string << " FROM #{query[:select]}"
186
+ query_string << " #{query[:joins]}" if query[:joins]
187
+ query_string << " WHERE #{query[:where]}" if query[:where]
188
+ query_string << " GROUP BY " + query[:fields].keys.join(", ") if query[:fields]
133
189
  query_string << ";"
134
190
  end
135
191
  end
@@ -146,8 +202,11 @@ module GitLab
146
202
 
147
203
  def probe_db
148
204
  results = @collector.run
149
- results.each do |key, value|
150
- @metrics.add("gitlab_database_rows", value.to_f, query_name: key.to_s)
205
+ results.each do |query_name, result|
206
+ labels = { query_name: query_name.to_s }
207
+ result.each do |row|
208
+ @metrics.add("gitlab_database_rows", row[:count].to_f, **labels, **row[:labels])
209
+ end
151
210
  end
152
211
 
153
212
  self
@@ -1,5 +1,5 @@
1
1
  module GitLab
2
2
  module Exporter
3
- VERSION = "6.0.0".freeze
3
+ VERSION = "6.1.0".freeze
4
4
  end
5
5
  end
@@ -4,7 +4,8 @@ require "gitlab_exporter/database/row_count"
4
4
  describe GitLab::Exporter::Database::RowCountCollector do
5
5
  let(:query) {
6
6
  { project_1: { select: :projects, where: "id=1" },
7
- project_2: { select: :projects, where: "id=2" } }
7
+ project_2: { select: :projects, where: "id=2" },
8
+ project_3: { select: :projects, fields: { is_public: { definition: "visibility_level == 20" } } } }
8
9
  }
9
10
  let(:collector) { described_class.new(connection_string: "host=localhost") }
10
11
 
@@ -12,19 +13,31 @@ describe GitLab::Exporter::Database::RowCountCollector do
12
13
  before do
13
14
  stub_const("GitLab::Exporter::Database::RowCountCollector::QUERIES", query)
14
15
 
15
- allow(collector).to receive(:count_from_query_hash).with(query[:project_1]).and_return(3)
16
- allow(collector).to receive(:count_from_query_hash).with(query[:project_2]).and_return(6)
16
+ allow(collector).to receive(:execute).with("SELECT COUNT(*) FROM projects WHERE id=1;").and_return(false)
17
+ allow(collector).to receive(:execute).with("SELECT COUNT(*) FROM projects WHERE id=2;").and_return(
18
+ [{ "count" => 6 }]
19
+ )
20
+ allow(collector).to receive(:execute).with(
21
+ "SELECT COUNT(*), (visibility_level == 20) AS is_public FROM projects GROUP BY is_public;"
22
+ ).and_return(
23
+ [{ "count" => 3, "is_public" => true }, { "count" => 6, "is_public" => false }]
24
+ )
17
25
  end
18
26
 
19
27
  it "executes all the queries" do
20
- expect(collector.run).to eq(project_1: 3, project_2: 6)
28
+ expect(collector.run).to eq(
29
+ project_1: [{ count: 0, labels: {} }],
30
+ project_2: [{ count: 6, labels: {} }],
31
+ project_3: [{ count: 3, labels: { is_public: true } },
32
+ { count: 6, labels: { is_public: false } }]
33
+ )
21
34
  end
22
35
 
23
36
  context "when selected_queries is passed" do
24
37
  let(:collector) { described_class.new(connection_string: "host=localhost", selected_queries: ["project_2"]) }
25
38
 
26
39
  it "executes the selected queries" do
27
- expect(collector.run).to eq(project_2: 6)
40
+ expect(collector.run).to eq(project_2: [{ count: 6, labels: {} }])
28
41
  end
29
42
  end
30
43
  end
@@ -33,5 +46,10 @@ describe GitLab::Exporter::Database::RowCountCollector do
33
46
  it "accepts a table and where clause" do
34
47
  expect(collector.send(:construct_query, query[:project_1])).to eq "SELECT COUNT(*) FROM projects WHERE id=1;"
35
48
  end
49
+
50
+ it "accepts a table and group (field) clause" do
51
+ expect(collector.send(:construct_query, query[:project_3])).to eq \
52
+ "SELECT COUNT(*), (visibility_level == 20) AS is_public FROM projects GROUP BY is_public;"
53
+ end
36
54
  end
37
55
  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: 6.0.0
4
+ version: 6.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Carranza