gitlab-exporter 7.1.0 → 9.0.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: 2590101193dd650767c1f39170beb0b54661c188b7c1222fa7d01d59ee1f442a
4
- data.tar.gz: 9237f257766fefe33cf0e398a86d44ecae609a393c046c7e5203b07a74adaca4
3
+ metadata.gz: b3fb1c9119047242e695cb956c7a68f7c19f564f7a274c8d503b7d4b984eed03
4
+ data.tar.gz: fb77e078e08dbc9f8f81a1a82dc070944fbf49af3944c90a8e30eac59ca1c39a
5
5
  SHA512:
6
- metadata.gz: 4109296df37f483e64b5c3f9c9da8ce6359a8b36cbb8b2bc7a40c3147ee0401fafee78829b6e67e43167b1a859d771669e6f94e85f7ebf8529a7bbea45be6431
7
- data.tar.gz: e4d05c4fad006d5a27f693887320b6f2a633f96b1109e97f7e89f5b990d695528b72ef2e7b876901d520df3f4be6c6b24850208228923c227443e06b70b81988
6
+ metadata.gz: 0c75097275454229a38f351618bc7eef530534726fa16d3d06b1c8fb95d5fdacc43a84d4d9781963bf27b8afc7700699bfe32d5f0f8516403edf7d5fa5a6555a
7
+ data.tar.gz: 1eb96b35d5a80166dc5f587dce7de896d7533cf5822d5a17b220c0d09d858b01e5d02cfc7bbd8710b6002591efd9181cfab063b8fa8bfee698beca672536e83a
@@ -1,17 +1,26 @@
1
+ include:
2
+ - template: Security/DAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
3
+ - template: Security/Container-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
4
+ - template: Security/Dependency-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
5
+ - template: Security/License-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
6
+ - template: Security/SAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
7
+ - template: Security/Secret-Detection.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
8
+
1
9
  default:
2
- image: "ruby:2.3"
3
- before_script:
4
- - git config --global user.email "bot@gitlab.com"
5
- - git config --global user.name "Bot User"
6
- - bundle install -j $(nproc) --path vendor
10
+ image: ruby:2.7
7
11
  cache:
8
12
  paths:
9
13
  - vendor
10
14
  tags:
11
15
  - gitlab-org
12
16
 
17
+ .before_scripts: &before_scripts
18
+ - git config --global user.email "bot@gitlab.com"
19
+ - git config --global user.name "Bot User"
20
+ - bundle install -j $(nproc) --path vendor
21
+
13
22
  workflow:
14
- rules:
23
+ rules: &workflow_rules
15
24
  # For merge requests, create a pipeline.
16
25
  - if: '$CI_MERGE_REQUEST_IID'
17
26
  # For `master` branch, create a pipeline (this includes on schedules, pushes, merges, etc.).
@@ -22,15 +31,18 @@ workflow:
22
31
  rspec:
23
32
  script:
24
33
  - bundle exec rspec spec -f d -c
34
+ before_script: *before_scripts
25
35
 
26
36
  rubocop:
27
37
  script:
28
38
  - bundle exec rubocop
39
+ before_script: *before_scripts
29
40
 
30
- include:
31
- - template: Security/DAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
32
- - template: Security/Container-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
33
- - template: Security/Dependency-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
34
- - template: Security/License-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
35
- - template: Security/SAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
41
+ license_scanning:
42
+ rules: *workflow_rules
43
+
44
+ gemnasium-dependency_scanning:
45
+ rules: *workflow_rules
36
46
 
47
+ secret_detection:
48
+ rules: *workflow_rules
@@ -1,5 +1,7 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  AllCops:
2
- TargetRubyVersion: 2.3
4
+ TargetRubyVersion: 2.7
3
5
  DisplayCopNames: true
4
6
 
5
7
  # Just use double quotes please
@@ -20,15 +22,15 @@ Style/RaiseArgs:
20
22
  Style/FrozenStringLiteralComment:
21
23
  Enabled: false
22
24
 
25
+ # Commonly used screens these days easily fit more than 80 characters.
26
+ Layout/LineLength:
27
+ Max: 120
28
+
23
29
  Metrics/MethodLength:
24
30
  Max: 15
25
31
 
26
32
  Metrics/AbcSize:
27
33
  Enabled: false
28
34
 
29
- # Commonly used screens these days easily fit more than 80 characters.
30
- Metrics/LineLength:
31
- Max: 120
32
-
33
35
  Metrics/ClassLength:
34
36
  Max: 150
@@ -0,0 +1,64 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2021-01-11 12:24:03 UTC using RuboCop version 0.93.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Configuration parameters: Include.
11
+ # Include: **/*.gemspec
12
+ Gemspec/RequiredRubyVersion:
13
+ Exclude:
14
+ - 'gitlab-exporter.gemspec'
15
+
16
+ # Offense count: 3
17
+ Lint/AmbiguousBlockAssociation:
18
+ Exclude:
19
+ - 'spec/git_spec.rb'
20
+ - 'spec/util_spec.rb'
21
+
22
+ # Offense count: 2
23
+ # Configuration parameters: MaximumRangeSize.
24
+ Lint/MissingCopEnableDirective:
25
+ Exclude:
26
+ - 'spec/database/ci_builds_spec.rb'
27
+ - 'spec/git_process_proper_spec.rb'
28
+
29
+ # Offense count: 1
30
+ # Cop supports --auto-correct.
31
+ Lint/NonDeterministicRequireOrder:
32
+ Exclude:
33
+ - 'spec/spec_helper.rb'
34
+
35
+ # Offense count: 16
36
+ # Configuration parameters: CountComments, CountAsOne, ExcludedMethods.
37
+ # ExcludedMethods: refine
38
+ Metrics/BlockLength:
39
+ Max: 349
40
+
41
+ # Offense count: 1
42
+ # Configuration parameters: IgnoredMethods.
43
+ Metrics/CyclomaticComplexity:
44
+ Max: 8
45
+
46
+ # Offense count: 1
47
+ # Configuration parameters: IgnoredMethods.
48
+ Metrics/PerceivedComplexity:
49
+ Max: 9
50
+
51
+ # Offense count: 1
52
+ # Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols.
53
+ # SupportedStyles: inline, group
54
+ Style/AccessModifierDeclarations:
55
+ Exclude:
56
+ - 'lib/gitlab_exporter/util.rb'
57
+
58
+ # Offense count: 2
59
+ # Cop supports --auto-correct.
60
+ # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods.
61
+ # AllowedMethods: present?, blank?, presence, try, try!
62
+ Style/SafeNavigation:
63
+ Exclude:
64
+ - 'lib/gitlab_exporter/database/base.rb'
@@ -0,0 +1 @@
1
+ 2.7.2
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-exporter (7.1.0)
4
+ gitlab-exporter (9.0.0)
5
5
  connection_pool (~> 2.2.1)
6
6
  pg (~> 1.1)
7
7
  quantile (~> 0.2.0)
@@ -13,23 +13,25 @@ PATH
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- ast (2.4.0)
16
+ ast (2.4.1)
17
17
  connection_pool (2.2.3)
18
18
  diff-lcs (1.3)
19
19
  mustermann (1.1.1)
20
20
  ruby2_keywords (~> 0.0.1)
21
- parser (2.5.1.0)
22
- ast (~> 2.4.0)
21
+ parallel (1.20.1)
22
+ parser (3.0.0.0)
23
+ ast (~> 2.4.1)
23
24
  pg (1.2.3)
24
- powerpack (0.1.1)
25
25
  quantile (0.2.1)
26
26
  rack (2.2.3)
27
27
  rack-protection (2.0.8.1)
28
28
  rack
29
- rainbow (2.1.0)
29
+ rainbow (3.0.0)
30
30
  redis (4.1.4)
31
31
  redis-namespace (1.6.0)
32
32
  redis (>= 3.0.4)
33
+ regexp_parser (2.0.3)
34
+ rexml (3.2.4)
33
35
  rspec (3.7.0)
34
36
  rspec-core (~> 3.7.0)
35
37
  rspec-expectations (~> 3.7.0)
@@ -43,13 +45,18 @@ GEM
43
45
  diff-lcs (>= 1.2.0, < 2.0)
44
46
  rspec-support (~> 3.7.0)
45
47
  rspec-support (3.7.1)
46
- rubocop (0.42.0)
47
- parser (>= 2.3.1.1, < 3.0)
48
- powerpack (~> 0.1)
49
- rainbow (>= 1.99.1, < 3.0)
48
+ rubocop (0.93.1)
49
+ parallel (~> 1.10)
50
+ parser (>= 2.7.1.5)
51
+ rainbow (>= 2.2.2, < 4.0)
52
+ regexp_parser (>= 1.8)
53
+ rexml
54
+ rubocop-ast (>= 0.6.0)
50
55
  ruby-progressbar (~> 1.7)
51
- unicode-display_width (~> 1.0, >= 1.0.1)
52
- ruby-progressbar (1.8.1)
56
+ unicode-display_width (>= 1.4.0, < 2.0)
57
+ rubocop-ast (1.4.0)
58
+ parser (>= 2.7.1.5)
59
+ ruby-progressbar (1.11.0)
53
60
  ruby2_keywords (0.0.2)
54
61
  sidekiq (5.2.9)
55
62
  connection_pool (~> 2.2, >= 2.2.2)
@@ -62,7 +69,7 @@ GEM
62
69
  rack-protection (= 2.0.8.1)
63
70
  tilt (~> 2.0)
64
71
  tilt (2.0.10)
65
- unicode-display_width (1.6.0)
72
+ unicode-display_width (1.7.0)
66
73
 
67
74
  PLATFORMS
68
75
  ruby
@@ -74,4 +81,4 @@ DEPENDENCIES
74
81
  rubocop (~> 0.42)
75
82
 
76
83
  BUNDLED WITH
77
- 1.17.3
84
+ 2.1.4
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
4
 
5
5
  require "optparse"
6
6
  require "gitlab_exporter"
@@ -6,6 +6,7 @@ db_common: &db_common
6
6
 
7
7
  # Web server config
8
8
  server:
9
+ name: puma # cf. https://github.com/sinatra/sinatra#available-settings
9
10
  listen_address: 0.0.0.0
10
11
  listen_port: 9168
11
12
  # Maximum amount of memory to use in megabytes, after which the process is killed
@@ -1,4 +1,4 @@
1
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path("lib", __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require "gitlab_exporter/version"
4
4
 
@@ -20,13 +20,13 @@ Gem::Specification.new do |s|
20
20
  s.homepage = "http://gitlab.com"
21
21
  s.license = "MIT"
22
22
 
23
+ s.add_runtime_dependency "connection_pool", "~> 2.2.1"
23
24
  s.add_runtime_dependency "pg", "~> 1.1"
24
- s.add_runtime_dependency "sinatra", "~> 2.0.4"
25
25
  s.add_runtime_dependency "quantile", "~> 0.2.0"
26
- s.add_runtime_dependency "sidekiq", "~> 5.2.1"
27
26
  s.add_runtime_dependency "redis", "~> 4.1.2"
28
27
  s.add_runtime_dependency "redis-namespace", "~> 1.6.0"
29
- s.add_runtime_dependency "connection_pool", "~> 2.2.1"
28
+ s.add_runtime_dependency "sidekiq", "~> 5.2.1"
29
+ s.add_runtime_dependency "sinatra", "~> 2.0.4"
30
30
 
31
31
  s.add_development_dependency "rspec", "~> 3.7.0"
32
32
  s.add_development_dependency "rspec-expectations", "~> 3.7.0"
@@ -19,8 +19,7 @@ module GitLab
19
19
  # Empty runner that will raise an InvalidCLICommand when executed to provide the usage
20
20
  # in the exception message
21
21
  class NullRunner
22
- def initialize(args)
23
- end
22
+ def initialize(args); end
24
23
 
25
24
  def run
26
25
  fail InvalidCLICommand.new("Usage: #{EXECUTABLE_NAME} <command> [options] [arguments...]\n\n"\
@@ -31,13 +31,11 @@ module GitLab
31
31
 
32
32
  def with_connection_pool
33
33
  connection_pool.with do |conn|
34
- begin
35
- yield conn
36
- rescue PG::UnableToSend => e
37
- @logger.warn "Error sending to the database: #{e}" if @logger
38
- conn.reset
39
- raise e
40
- end
34
+ yield conn
35
+ rescue PG::UnableToSend => e
36
+ @logger.warn "Error sending to the database: #{e}" if @logger
37
+ conn.reset
38
+ raise e
41
39
  end
42
40
  rescue PG::Error => e
43
41
  @logger.error "Error connecting to the database: #{e}" if @logger
@@ -3,6 +3,8 @@ module GitLab
3
3
  module Database
4
4
  # Helper to collect bloat metrics.
5
5
  class BloatCollector < Base
6
+ attr_writer :logger
7
+
6
8
  def run(type = :btree)
7
9
  execute(self.class.query_for(type)).each_with_object({}) do |row, h|
8
10
  h[row["object_name"]] = row
@@ -33,16 +35,18 @@ module GitLab
33
35
 
34
36
  # Prober class to gather bloat metrics
35
37
  class BloatProber
36
- METRIC_KEYS = %w(bloat_ratio bloat_size extra_size real_size).freeze
38
+ METRIC_KEYS = %w[bloat_ratio bloat_size extra_size real_size].freeze
37
39
 
38
40
  attr_reader :metrics, :collector, :bloat_types
39
41
 
40
42
  def initialize(opts,
41
43
  metrics: PrometheusMetrics.new,
42
- collector: BloatCollector.new(connection_string: opts[:connection_string]))
44
+ collector: BloatCollector.new(connection_string: opts[:connection_string]),
45
+ logger: nil)
43
46
  @metrics = metrics
44
47
  @collector = collector
45
- @bloat_types = opts[:bloat_types] || %i(btree table)
48
+ @collector.logger = logger
49
+ @bloat_types = opts[:bloat_types] || %i[btree table]
46
50
  end
47
51
 
48
52
  def probe_db
@@ -12,73 +12,90 @@ SELECT current_database(), nspname AS schemaname, tblname, idxname AS object_nam
12
12
  END AS bloat_size,
13
13
  100 * (relpages-est_pages_ff)::float / relpages AS bloat_ratio,
14
14
  is_na
15
- -- , 100-(sub.pst).avg_leaf_density, est_pages, index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, sub.reltuples, sub.relpages -- (DEBUG INFO)
15
+ -- , 100-(pst).avg_leaf_density AS pst_avg_bloat, est_pages, index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples, relpages -- (DEBUG INFO)
16
16
  FROM (
17
17
  SELECT coalesce(1 +
18
- ceil(reltuples/floor((bs-pageopqdata-pagehdr)/(4+nulldatahdrwidth)::float)), 0 -- ItemIdData size + computed avg size of a tuple (nulldatahdrwidth)
19
- ) AS est_pages,
20
- coalesce(1 +
21
- ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatahdrwidth)::float))), 0
22
- ) AS est_pages_ff,
23
- bs, nspname, table_oid, tblname, idxname, relpages, fillfactor, is_na
24
- -- , stattuple.pgstatindex(quote_ident(nspname)||'.'||quote_ident(idxname)) AS pst, index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples -- (DEBUG INFO)
18
+ ceil(reltuples/floor((bs-pageopqdata-pagehdr)/(4+nulldatahdrwidth)::float)), 0 -- ItemIdData size + computed avg size of a tuple (nulldatahdrwidth)
19
+ ) AS est_pages,
20
+ coalesce(1 +
21
+ ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatahdrwidth)::float))), 0
22
+ ) AS est_pages_ff,
23
+ bs, nspname, tblname, idxname, relpages, fillfactor, is_na
24
+ -- , pgstatindex(idxoid) AS pst, index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples -- (DEBUG INFO)
25
25
  FROM (
26
- SELECT maxalign, bs, nspname, tblname, idxname, reltuples, relpages, relam, table_oid, fillfactor,
27
- ( index_tuple_hdr_bm +
28
- maxalign - CASE -- Add padding to the index tuple header to align on MAXALIGN
29
- WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign
30
- ELSE index_tuple_hdr_bm%maxalign
31
- END
32
- + nulldatawidth + maxalign - CASE -- Add padding to the data to align on MAXALIGN
33
- WHEN nulldatawidth = 0 THEN 0
34
- WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
35
- ELSE nulldatawidth::integer%maxalign
36
- END
37
- )::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na
38
- -- , index_tuple_hdr_bm, nulldatawidth -- (DEBUG INFO)
39
- FROM (
40
- SELECT
41
- i.nspname, i.tblname, i.idxname, i.reltuples, i.relpages, i.relam, a.attrelid AS table_oid,
42
- current_setting('block_size')::numeric AS bs, fillfactor,
43
- CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?)
44
- WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8
45
- ELSE 4
46
- END AS maxalign,
47
- /* per page header, fixed size: 20 for 7.X, 24 for others */
48
- 24 AS pagehdr,
49
- /* per page btree opaque data */
50
- 16 AS pageopqdata,
51
- /* per tuple header: add IndexAttributeBitMapData if some cols are null-able */
52
- CASE WHEN max(coalesce(s.null_frac,0)) = 0
53
- THEN 2 -- IndexTupleData size
54
- ELSE 2 + (( 32 + 8 - 1 ) / 8) -- IndexTupleData size + IndexAttributeBitMapData size ( max num filed per index + 8 - 1 /8)
55
- END AS index_tuple_hdr_bm,
56
- /* data len: we remove null values save space using it fractionnal part from stats */
57
- sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) AS nulldatawidth,
58
- max( CASE WHEN a.atttypid = 'pg_catalog.name'::regtype THEN 1 ELSE 0 END ) > 0 AS is_na
59
- FROM pg_attribute AS a
60
- JOIN (
61
- SELECT nspname, tbl.relname AS tblname, idx.relname AS idxname, idx.reltuples, idx.relpages, idx.relam,
62
- indrelid, indexrelid, indkey::smallint[] AS attnum,
63
- coalesce(substring(
64
- array_to_string(idx.reloptions, ' ')
65
- from 'fillfactor=([0-9]+)')::smallint, 90) AS fillfactor
66
- FROM pg_index
67
- JOIN pg_class idx ON idx.oid=pg_index.indexrelid
68
- JOIN pg_class tbl ON tbl.oid=pg_index.indrelid
69
- JOIN pg_namespace ON pg_namespace.oid = idx.relnamespace
70
- WHERE pg_index.indisvalid AND tbl.relkind = 'r' AND idx.relpages > 0
71
- ) AS i ON a.attrelid = i.indexrelid
72
- JOIN pg_stats AS s ON s.schemaname = i.nspname
73
- AND ((s.tablename = i.tblname AND s.attname = pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE)) -- stats from tbl
74
- OR (s.tablename = i.idxname AND s.attname = a.attname))-- stats from functionnal cols
75
- JOIN pg_type AS t ON a.atttypid = t.oid
76
- WHERE a.attnum > 0
77
- GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9
78
- ) AS s1
79
- ) AS s2
80
- JOIN pg_am am ON s2.relam = am.oid WHERE am.amname = 'btree'
81
- ) AS sub
82
- WHERE NOT is_na
83
- AND nspname = 'public'
84
- ORDER BY 2,3,4;
26
+ SELECT maxalign, bs, nspname, tblname, idxname, reltuples, relpages, idxoid, fillfactor,
27
+ ( index_tuple_hdr_bm +
28
+ maxalign - CASE -- Add padding to the index tuple header to align on MAXALIGN
29
+ WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign
30
+ ELSE index_tuple_hdr_bm%maxalign
31
+ END
32
+ + nulldatawidth + maxalign - CASE -- Add padding to the data to align on MAXALIGN
33
+ WHEN nulldatawidth = 0 THEN 0
34
+ WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
35
+ ELSE nulldatawidth::integer%maxalign
36
+ END
37
+ )::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na
38
+ -- , index_tuple_hdr_bm, nulldatawidth -- (DEBUG INFO)
39
+ FROM (
40
+ SELECT n.nspname, i.tblname, i.idxname, i.reltuples, i.relpages,
41
+ i.idxoid, i.fillfactor, current_setting('block_size')::numeric AS bs,
42
+ CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?)
43
+ WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8
44
+ ELSE 4
45
+ END AS maxalign,
46
+ /* per page header, fixed size: 20 for 7.X, 24 for others */
47
+ 24 AS pagehdr,
48
+ /* per page btree opaque data */
49
+ 16 AS pageopqdata,
50
+ /* per tuple header: add IndexAttributeBitMapData if some cols are null-able */
51
+ CASE WHEN max(coalesce(s.null_frac,0)) = 0
52
+ THEN 2 -- IndexTupleData size
53
+ ELSE 2 + (( 32 + 8 - 1 ) / 8) -- IndexTupleData size + IndexAttributeBitMapData size ( max num filed per index + 8 - 1 /8)
54
+ END AS index_tuple_hdr_bm,
55
+ /* data len: we remove null values save space using it fractionnal part from stats */
56
+ sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) AS nulldatawidth,
57
+ max( CASE WHEN i.atttypid = 'pg_catalog.name'::regtype THEN 1 ELSE 0 END ) > 0 AS is_na
58
+ FROM (
59
+ SELECT ct.relname AS tblname, ct.relnamespace, ic.idxname, ic.attpos, ic.indkey, ic.indkey[ic.attpos], ic.reltuples, ic.relpages, ic.tbloid, ic.idxoid, ic.fillfactor,
60
+ coalesce(a1.attnum, a2.attnum) AS attnum, coalesce(a1.attname, a2.attname) AS attname, coalesce(a1.atttypid, a2.atttypid) AS atttypid,
61
+ CASE WHEN a1.attnum IS NULL
62
+ THEN ic.idxname
63
+ ELSE ct.relname
64
+ END AS attrelname
65
+ FROM (
66
+ SELECT idxname, reltuples, relpages, tbloid, idxoid, fillfactor, indkey,
67
+ pg_catalog.generate_series(1,indnatts) AS attpos
68
+ FROM (
69
+ SELECT ci.relname AS idxname, ci.reltuples, ci.relpages, i.indrelid AS tbloid,
70
+ i.indexrelid AS idxoid,
71
+ coalesce(substring(
72
+ array_to_string(ci.reloptions, ' ')
73
+ from 'fillfactor=([0-9]+)')::smallint, 90) AS fillfactor,
74
+ i.indnatts,
75
+ pg_catalog.string_to_array(pg_catalog.textin(
76
+ pg_catalog.int2vectorout(i.indkey)),' ')::int[] AS indkey
77
+ FROM pg_catalog.pg_index i
78
+ JOIN pg_catalog.pg_class ci ON ci.oid = i.indexrelid
79
+ WHERE ci.relam=(SELECT oid FROM pg_am WHERE amname = 'btree')
80
+ AND ci.relpages > 0
81
+ ) AS idx_data
82
+ ) AS ic
83
+ JOIN pg_catalog.pg_class ct ON ct.oid = ic.tbloid
84
+ LEFT JOIN pg_catalog.pg_attribute a1 ON
85
+ ic.indkey[ic.attpos] <> 0
86
+ AND a1.attrelid = ic.tbloid
87
+ AND a1.attnum = ic.indkey[ic.attpos]
88
+ LEFT JOIN pg_catalog.pg_attribute a2 ON
89
+ ic.indkey[ic.attpos] = 0
90
+ AND a2.attrelid = ic.idxoid
91
+ AND a2.attnum = ic.attpos
92
+ ) i
93
+ JOIN pg_catalog.pg_namespace n ON n.oid = i.relnamespace
94
+ JOIN pg_catalog.pg_stats s ON s.schemaname = n.nspname
95
+ AND s.tablename = i.attrelname
96
+ AND s.attname = i.attname
97
+ GROUP BY 1,2,3,4,5,6,7,8,9,10,11
98
+ ) AS rows_data_stats
99
+ ) AS rows_hdr_pdg_stats
100
+ ) AS relation_stats
101
+ ORDER BY nspname, tblname, idxname;
@@ -1,5 +1,5 @@
1
1
  -- Originally from: https://github.com/ioguix/pgsql-bloat-estimation/blob/master/table/table_bloat.sql
2
- /* WARNING: executed with a non-superuser role, the query inspect only tables you are granted to read.
2
+ /* WARNING: executed with a non-superuser role, the query inspect only tables and materialized view (9.3+) you are granted to read.
3
3
  * This query is compatible with PostgreSQL 9.0 and more
4
4
  */
5
5
  SELECT current_database(), schemaname, tblname AS object_name, bs*tblpages AS real_size,
@@ -16,12 +16,12 @@ SELECT current_database(), schemaname, tblname AS object_name, bs*tblpages AS re
16
16
  THEN 100 * (tblpages - est_tblpages_ff)/tblpages::float
17
17
  ELSE 0
18
18
  END AS bloat_ratio, is_na
19
- -- , (pst).free_percent + (pst).dead_tuple_percent AS real_frag
19
+ -- , tpl_hdr_size, tpl_data_size, (pst).free_percent + (pst).dead_tuple_percent AS real_frag -- (DEBUG INFO)
20
20
  FROM (
21
21
  SELECT ceil( reltuples / ( (bs-page_hdr)/tpl_size ) ) + ceil( toasttuples / 4 ) AS est_tblpages,
22
22
  ceil( reltuples / ( (bs-page_hdr)*fillfactor/(tpl_size*100) ) ) + ceil( toasttuples / 4 ) AS est_tblpages_ff,
23
23
  tblpages, fillfactor, bs, tblid, schemaname, tblname, heappages, toastpages, is_na
24
- -- , stattuple.pgstattuple(tblid) AS pst
24
+ -- , tpl_hdr_size, tpl_data_size, pgstattuple(tblid) AS pst -- (DEBUG INFO)
25
25
  FROM (
26
26
  SELECT
27
27
  ( 4 + tpl_hdr_size + tpl_data_size + (2*ma)
@@ -29,6 +29,7 @@ FROM (
29
29
  - CASE WHEN ceil(tpl_data_size)::int%ma = 0 THEN ma ELSE ceil(tpl_data_size)::int%ma END
30
30
  ) AS tpl_size, bs - page_hdr AS size_per_block, (heappages + toastpages) AS tblpages, heappages,
31
31
  toastpages, reltuples, toasttuples, bs, page_hdr, tblid, schemaname, tblname, fillfactor, is_na
32
+ -- , tpl_hdr_size, tpl_data_size
32
33
  FROM (
33
34
  SELECT
34
35
  tbl.oid AS tblid, ns.nspname AS schemaname, tbl.relname AS tblname, tbl.reltuples,
@@ -40,24 +41,24 @@ FROM (
40
41
  current_setting('block_size')::numeric AS bs,
41
42
  CASE WHEN version()~'mingw32' OR version()~'64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END AS ma,
42
43
  24 AS page_hdr,
43
- 23 + CASE WHEN MAX(coalesce(null_frac,0)) > 0 THEN ( 7 + count(*) ) / 8 ELSE 0::int END
44
- + CASE WHEN tbl.relhasoids THEN 4 ELSE 0 END AS tpl_hdr_size,
45
- sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024) ) AS tpl_data_size,
44
+ 23 + CASE WHEN MAX(coalesce(s.null_frac,0)) > 0 THEN ( 7 + count(s.attname) ) / 8 ELSE 0::int END
45
+ + CASE WHEN bool_or(att.attname = 'oid' and att.attnum < 0) THEN 4 ELSE 0 END AS tpl_hdr_size,
46
+ sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 0) ) AS tpl_data_size,
46
47
  bool_or(att.atttypid = 'pg_catalog.name'::regtype)
47
- OR count(att.attname) <> count(s.attname) AS is_na
48
+ OR sum(CASE WHEN att.attnum > 0 THEN 1 ELSE 0 END) <> count(s.attname) AS is_na
48
49
  FROM pg_attribute AS att
49
50
  JOIN pg_class AS tbl ON att.attrelid = tbl.oid
50
51
  JOIN pg_namespace AS ns ON ns.oid = tbl.relnamespace
51
52
  LEFT JOIN pg_stats AS s ON s.schemaname=ns.nspname
52
53
  AND s.tablename = tbl.relname AND s.inherited=false AND s.attname=att.attname
53
54
  LEFT JOIN pg_class AS toast ON tbl.reltoastrelid = toast.oid
54
- WHERE att.attnum > 0 AND NOT att.attisdropped
55
- AND tbl.relkind = 'r'
56
- GROUP BY 1,2,3,4,5,6,7,8,9,10, tbl.relhasoids
55
+ WHERE NOT att.attisdropped
56
+ AND tbl.relkind in ('r','m')
57
+ GROUP BY 1,2,3,4,5,6,7,8,9,10
57
58
  ORDER BY 2,3
58
59
  ) AS s
59
60
  ) AS s2
60
61
  ) AS s3
61
- WHERE NOT is_na
62
+ -- WHERE NOT is_na
62
63
  -- AND tblpages*((pst).free_percent + (pst).dead_tuple_percent)::float4/100 >= 1
63
- AND schemaname= 'public';
64
+ ORDER BY schemaname, tblname;
@@ -391,6 +391,7 @@ module GitLab
391
391
 
392
392
  def include_bool_if_row_defined(row, field)
393
393
  return {} unless row[field.to_s]
394
+
394
395
  { field => row[field.to_s] == "t" ? "yes" : "no" }
395
396
  end
396
397
 
@@ -470,7 +471,7 @@ module GitLab
470
471
 
471
472
  def add_ci_created_pending_builds(metric_name, value, labels)
472
473
  add_metric_with_namespace_label(metric_name,
473
- [:namespace, :shared_runners, :has_minutes],
474
+ %i[namespace shared_runners has_minutes],
474
475
  value,
475
476
  labels)
476
477
  end
@@ -505,8 +506,8 @@ module GitLab
505
506
  def add_ci_running_builds(value, labels)
506
507
  add_metric_with_namespace_label(
507
508
  "ci_running_builds",
508
- [:runner, :namespace, :runner_type, :scheduled,
509
- :triggered, :mirror, :mirror_trigger_builds, :has_minutes],
509
+ %i[runner namespace runner_type scheduled
510
+ triggered mirror mirror_trigger_builds has_minutes],
510
511
  value,
511
512
  labels
512
513
  )
@@ -29,7 +29,7 @@ module GitLab
29
29
 
30
30
  MIRROR_QUERY = {
31
31
  select: :projects,
32
- joins: <<~SQL,
32
+ joins: <<~SQL,
33
33
  INNER JOIN project_mirror_data ON project_mirror_data.project_id = projects.id
34
34
  INNER JOIN namespaces AS root_namespaces ON root_namespaces.id = (
35
35
  WITH RECURSIVE "base_and_ancestors" AS (
@@ -112,9 +112,9 @@ module GitLab
112
112
  ON users.id = u.user_id",
113
113
  where: "user_type IS NULL",
114
114
  fields: {
115
- admin: {},
116
- external: {},
117
- state: {},
115
+ admin: {},
116
+ external: {},
117
+ state: {},
118
118
  access_level: { definition: "COALESCE(u.access_level, 0)" }
119
119
  }
120
120
  },
@@ -122,14 +122,14 @@ module GitLab
122
122
  select: :projects,
123
123
  fields: {
124
124
  visibility_level: {},
125
- archived: {}
125
+ archived: {}
126
126
  }
127
127
  },
128
128
  groups: {
129
129
  select: :namespaces,
130
130
  fields: {
131
131
  visibility_level: {},
132
- root: { definition: "(parent_id IS NULL)" }
132
+ root: { definition: "(parent_id IS NULL)" }
133
133
  }
134
134
  }
135
135
  }.freeze
@@ -175,6 +175,14 @@ module GitLab
175
175
 
176
176
  def execute(query)
177
177
  with_connection_pool do |conn|
178
+ conn.exec(query).map_types!(type_map_for_results(conn))
179
+ end
180
+ rescue PG::UndefinedTable, PG::UndefinedColumn
181
+ nil
182
+ end
183
+
184
+ def type_map_for_results(conn)
185
+ @type_map_for_results ||= begin
178
186
  tm = PG::BasicTypeMapForResults.new(conn)
179
187
 
180
188
  # Remove warning message:
@@ -187,10 +195,8 @@ module GitLab
187
195
  tm.add_coder(old_coder.dup.tap { |c| c.oid = value[:oid] })
188
196
  end
189
197
 
190
- conn.exec(query).map_types!(tm)
198
+ tm
191
199
  end
192
- rescue PG::UndefinedTable, PG::UndefinedColumn
193
- nil
194
200
  end
195
201
 
196
202
  # Not private so I can test it without meta programming tricks
@@ -5,7 +5,7 @@ module GitLab
5
5
  #
6
6
  # It takes a connection string (e.g. "dbname=test port=5432")
7
7
  class TupleStatsCollector < Base
8
- COLUMNS = %w(relname seq_tup_read idx_tup_fetch n_tup_ins n_tup_upd n_tup_del n_tup_hot_upd n_dead_tup seq_scan)
8
+ COLUMNS = %w[relname seq_tup_read idx_tup_fetch n_tup_ins n_tup_upd n_tup_del n_tup_hot_upd n_dead_tup seq_scan]
9
9
  .join(",")
10
10
  QUERY = <<-SQL.freeze
11
11
  SELECT #{COLUMNS}
@@ -35,9 +35,11 @@ module GitLab
35
35
 
36
36
  result.each do |table_name, tuple_stats|
37
37
  tuple_stats.each do |column_name, value|
38
+ next if value.is_a?(Numeric)
39
+
38
40
  @metrics.add("gitlab_database_stat_table_#{column_name}",
39
41
  value.to_f,
40
- table_name: table_name) unless value.is_a?(Numeric)
42
+ table_name: table_name)
41
43
  end
42
44
  end
43
45
 
@@ -13,6 +13,7 @@ module GitLab
13
13
  class Git
14
14
  def initialize(repo)
15
15
  fail "Repository #{repo} does not exists" unless Dir.exist? repo
16
+
16
17
  @repo = repo
17
18
  @tracker = TimeTracker.new
18
19
  end
@@ -35,6 +36,7 @@ module GitLab
35
36
  def execute(command)
36
37
  result = CommandResult.new(*Open3.capture2e(command, chdir: @repo))
37
38
  fail "Command #{command} failed with status #{result.status}\n#{result.stdout}" if result.failed?
39
+
38
40
  result
39
41
  end
40
42
  end
@@ -96,7 +98,7 @@ module GitLab
96
98
  Utils.pgrep("^git ").each do |pid|
97
99
  process_cmd = begin
98
100
  File.read("/proc/#{pid}/cmdline")
99
- rescue
101
+ rescue StandardError
100
102
  "" # Process file is gone (race condition)
101
103
  end
102
104
  subcommand = self.class.extract_subcommand(process_cmd)
@@ -131,6 +133,7 @@ module GitLab
131
133
 
132
134
  def self.extract_subcommand(cmd)
133
135
  return if cmd.empty?
136
+
134
137
  cmd_splitted = cmd.split("\u0000") # cmdline does not return it space-separated
135
138
 
136
139
  cmd_splitted.shift # Because it's "git"
@@ -87,7 +87,7 @@ module GitLab
87
87
  end
88
88
  end
89
89
  end
90
- rescue => e
90
+ rescue StandardError => e
91
91
  puts "Error: #{e}"
92
92
  @valid = false
93
93
  create_memstats_not_available(totals)
@@ -25,7 +25,7 @@ module GitLab
25
25
  # Locked: 0 kB
26
26
  # VmFlags: rd ex mr mw me dw sd
27
27
  class Mapping
28
- FIELDS = %w(size rss shared_clean shared_dirty private_clean private_dirty swap pss).freeze
28
+ FIELDS = %w[size rss shared_clean shared_dirty private_clean private_dirty swap pss].freeze
29
29
 
30
30
  attr_reader :address_start
31
31
  attr_reader :address_end
@@ -105,9 +105,7 @@ module GitLab
105
105
  ::GitLab::Exporter::MemStats::Mapping::FIELDS.each do |field|
106
106
  value = stats.totals[field]
107
107
 
108
- if value >= 0
109
- @metrics.add("process_smaps_#{field}_bytes", value * 1024, @use_quantiles, **labels)
110
- end
108
+ @metrics.add("process_smaps_#{field}_bytes", value * 1024, @use_quantiles, **labels) if value >= 0
111
109
  end
112
110
  end
113
111
 
@@ -53,21 +53,19 @@ module GitLab
53
53
  self
54
54
  end
55
55
 
56
- def probe_jobs # rubocop:disable Metrics/MethodLength
56
+ def probe_jobs
57
57
  return self unless connected?
58
58
 
59
59
  job_stats = {}
60
60
 
61
61
  Sidekiq::Queue.all.each do |queue|
62
- begin
63
- Sidekiq.redis do |conn|
64
- stats = conn.evalsha(QUEUE_JOB_STATS_SHA, ["queue:#{queue.name}"])
65
- job_stats.merge!(stats.to_h)
66
- end
67
- rescue Redis::CommandError # Could happen if the script exceeded the maximum run time (5 seconds by default)
68
- # FIXME: Should we call SCRIPT KILL?
69
- return self
62
+ Sidekiq.redis do |conn|
63
+ stats = conn.evalsha(QUEUE_JOB_STATS_SHA, ["queue:#{queue.name}"])
64
+ job_stats.merge!(stats.to_h)
70
65
  end
66
+ rescue Redis::CommandError # Could happen if the script exceeded the maximum run time (5 seconds by default)
67
+ # FIXME: Should we call SCRIPT KILL?
68
+ return self
71
69
  end
72
70
 
73
71
  job_stats.each do |class_name, count|
@@ -153,7 +151,7 @@ module GitLab
153
151
  end
154
152
  true
155
153
  end
156
- rescue Redis::CannotConnectError, Redis::TimeoutError # rubocop:disable Lint/HandleExceptions
154
+ rescue Redis::CannotConnectError, Redis::TimeoutError
157
155
  # Maybe we're trying connecting to a slave
158
156
  end
159
157
 
@@ -164,6 +162,7 @@ module GitLab
164
162
  # Using administrative commands on conn directly (which is a Redis::Namespace)
165
163
  # will be removed in redis-namespace 2.0.
166
164
  next if conn.redis.script(:exists, QUEUE_JOB_STATS_SHA)
165
+
167
166
  conn.redis.script(:load, QUEUE_JOB_STATS_SCRIPT)
168
167
  end
169
168
  end
@@ -24,7 +24,7 @@ module GitLab
24
24
  # Helper methods, some stuff was copied from ActiveSupport
25
25
  module Utils
26
26
  def camel_case_string(str)
27
- str.gsub(/(?:_|^)([a-z\d]*)/i) { $1.capitalize } # rubocop:disable PerlBackrefs
27
+ str.gsub(/(?:_|^)([a-z\d]*)/i) { $1.capitalize } # rubocop:disable Style/PerlBackrefs
28
28
  end
29
29
  module_function :camel_case_string
30
30
 
@@ -1,5 +1,5 @@
1
1
  module GitLab
2
2
  module Exporter
3
- VERSION = "7.1.0".freeze
3
+ VERSION = "9.0.0".freeze
4
4
  end
5
5
  end
@@ -24,7 +24,7 @@ module GitLab
24
24
  private
25
25
 
26
26
  def memory_usage
27
- io = IO.popen(%W(ps -o rss= -p #{$PID}))
27
+ io = IO.popen(%W[ps -o rss= -p #{$PID}])
28
28
 
29
29
  mem = io.read
30
30
  io.close
@@ -36,6 +36,8 @@ module GitLab
36
36
  end
37
37
 
38
38
  class << self
39
+ DEFAULT_WEB_SERVER = "webrick".freeze
40
+
39
41
  def setup(config)
40
42
  setup_server(config[:server])
41
43
  setup_probes(config[:probes])
@@ -52,6 +54,7 @@ module GitLab
52
54
  def setup_server(config)
53
55
  config ||= {}
54
56
 
57
+ set(:server, config.fetch(:name, DEFAULT_WEB_SERVER))
55
58
  set(:bind, config.fetch(:listen_address, "0.0.0.0"))
56
59
  set(:port, config.fetch(:listen_port, 9168))
57
60
  end
@@ -26,7 +26,7 @@ describe GitLab::Exporter::Database::BloatCollector do
26
26
  end
27
27
 
28
28
  describe GitLab::Exporter::Database::BloatProber do
29
- let(:opts) { { bloat_types: %i(btree table) } }
29
+ let(:opts) { { bloat_types: %i[btree table] } }
30
30
  let(:metrics) { double("PrometheusMetrics", add: nil) }
31
31
  let(:collector) { double("BloatCollector", run: data) }
32
32
 
@@ -43,7 +43,11 @@ describe GitLab::Exporter::Database::BloatProber do
43
43
  end
44
44
 
45
45
  describe "#probe_db" do
46
- subject { described_class.new(opts, metrics: metrics, collector: collector).probe_db }
46
+ subject { described_class.new(opts, metrics: metrics, collector: collector, logger: STDOUT).probe_db }
47
+
48
+ before do
49
+ expect(collector).to receive(:logger=).with(STDOUT)
50
+ end
47
51
 
48
52
  it "invokes the collector for each bloat type" do
49
53
  expect(collector).to receive(:run).with(:btree)
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
  require "gitlab_exporter/database/ci_builds"
3
3
 
4
- # rubocop:disable Metrics/LineLength
4
+ # rubocop:disable Layout/LineLength
5
5
  describe GitLab::Exporter::Database do
6
6
  let(:set_random_page_cost_query) { "SET random_page_cost" }
7
7
  let(:builds_query_ee) { "SELECT BUILDS EE" }
@@ -100,35 +100,35 @@ describe GitLab::Exporter::Database do
100
100
  allow(Time).to receive(:now).and_return(time_now)
101
101
 
102
102
  allow(connection).to receive(:exec).with(builds_query_ee)
103
- .and_return([builds_query_row_ee("f", "created", "1", "f", 10),
104
- builds_query_row_ee("t", "pending", "1", "t", 30),
105
- builds_query_row_ee("f", "created", "2", "f", 20),
106
- builds_query_row_ee("t", "pending", "2", "t", 50),
107
- builds_query_row_ee("t", "pending", "3", "f", 1),
108
- builds_query_row_ee("t", "pending", "4", "t", 2),
109
- builds_query_row_ee("f", "pending", "5", "f", 2)])
103
+ .and_return([builds_query_row_ee("f", "created", "1", "f", 10),
104
+ builds_query_row_ee("t", "pending", "1", "t", 30),
105
+ builds_query_row_ee("f", "created", "2", "f", 20),
106
+ builds_query_row_ee("t", "pending", "2", "t", 50),
107
+ builds_query_row_ee("t", "pending", "3", "f", 1),
108
+ builds_query_row_ee("t", "pending", "4", "t", 2),
109
+ builds_query_row_ee("f", "pending", "5", "f", 2)])
110
110
  allow(connection).to receive(:exec).with(builds_query_ce)
111
- .and_return([builds_query_row_ce("f", "created", "1", 10),
112
- builds_query_row_ce("t", "pending", "1", 30),
113
- builds_query_row_ce("f", "created", "2", 20),
114
- builds_query_row_ce("t", "pending", "2", 50),
115
- builds_query_row_ce("t", "pending", "3", 1),
116
- builds_query_row_ce("t", "pending", "4", 2),
117
- builds_query_row_ce("f", "pending", "5", 2)])
111
+ .and_return([builds_query_row_ce("f", "created", "1", 10),
112
+ builds_query_row_ce("t", "pending", "1", 30),
113
+ builds_query_row_ce("f", "created", "2", 20),
114
+ builds_query_row_ce("t", "pending", "2", 50),
115
+ builds_query_row_ce("t", "pending", "3", 1),
116
+ builds_query_row_ce("t", "pending", "4", 2),
117
+ builds_query_row_ce("f", "pending", "5", 2)])
118
118
 
119
119
  allow(connection).to receive(:exec).with(stale_builds_query).and_return([{ "count" => 2 }])
120
120
 
121
121
  allow(connection).to receive(:exec).with(per_runner_query_ee)
122
- .and_return([per_runner_query_row_ee(1, "instance_type", 1, "f", "f", 1, nil, "t", 15),
123
- per_runner_query_row_ee(2, "project_type", 2, "t", "t", nil, 3, "f", 5),
124
- per_runner_query_row_ee(2, "project_type", 3, "t", "t", nil, 3, "t", 5),
125
- per_runner_query_row_ee(3, "project_type", 4, "t", "t", nil, 3, "f", 5)])
122
+ .and_return([per_runner_query_row_ee(1, "instance_type", 1, "f", "f", 1, nil, "t", 15),
123
+ per_runner_query_row_ee(2, "project_type", 2, "t", "t", nil, 3, "f", 5),
124
+ per_runner_query_row_ee(2, "project_type", 3, "t", "t", nil, 3, "t", 5),
125
+ per_runner_query_row_ee(3, "project_type", 4, "t", "t", nil, 3, "f", 5)])
126
126
 
127
127
  allow(connection).to receive(:exec).with(per_runner_query_ce)
128
- .and_return([per_runner_query_row_ce(1, "instance_type", 1, 1, nil, 15),
129
- per_runner_query_row_ce(2, "project_type", 2, nil, 3, 5),
130
- per_runner_query_row_ce(2, "project_type", 3, nil, 3, 5),
131
- per_runner_query_row_ce(3, "project_type", 4, nil, 3, 5)])
128
+ .and_return([per_runner_query_row_ce(1, "instance_type", 1, 1, nil, 15),
129
+ per_runner_query_row_ce(2, "project_type", 2, nil, 3, 5),
130
+ per_runner_query_row_ce(2, "project_type", 3, nil, 3, 5),
131
+ per_runner_query_row_ce(3, "project_type", 4, nil, 3, 5)])
132
132
 
133
133
  # rubocop:disable Style/FormatString
134
134
  repeated_commands_query_ee_with_limit = repeated_commands_query_ee % [allowed_repeated_commands_count]
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
  require "gitlab_exporter"
3
3
 
4
- # rubocop:disable Metrics/LineLength
4
+ # rubocop:disable Layout/LineLength
5
5
  describe GitLab::Exporter::GitProcessProber do
6
6
  describe ".extract_subcommand" do
7
7
  it "extract git subcommand" do
@@ -14,11 +14,11 @@ describe GitLab::Exporter::MemStats do
14
14
  it "parses the data properly" do
15
15
  expect(subject.valid?).to be_truthy
16
16
 
17
- nonzero_fields = %w(size rss shared_clean shared_dirty private_dirty pss)
18
- zero_fields = %w(private_clean swap)
17
+ nonzero_fields = %w[size rss shared_clean shared_dirty private_dirty pss]
18
+ zero_fields = %w[private_clean swap]
19
19
 
20
20
  nonzero_fields.each do |field|
21
- expect(subject.totals[field]).to be > 0 # rubocop:disable Style/NumericPredicate
21
+ expect(subject.totals[field]).to be > 0
22
22
  end
23
23
 
24
24
  zero_fields.each do |field|
@@ -51,11 +51,9 @@ class CLIArgs
51
51
  yield self
52
52
  end
53
53
 
54
- def on(*args)
55
- end
54
+ def on(*args); end
56
55
 
57
- def banner=(banner)
58
- end
56
+ def banner=(banner); end
59
57
 
60
58
  def parse!
61
59
  @arguments
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: 7.1.0
4
+ version: 9.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Carranza
@@ -11,33 +11,33 @@ cert_chain: []
11
11
  date: 2016-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: pg
14
+ name: connection_pool
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.1'
19
+ version: 2.2.1
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: '1.1'
26
+ version: 2.2.1
27
27
  - !ruby/object:Gem::Dependency
28
- name: sinatra
28
+ name: pg
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.0.4
33
+ version: '1.1'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.0.4
40
+ version: '1.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: quantile
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,61 +53,61 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.2.0
55
55
  - !ruby/object:Gem::Dependency
56
- name: sidekiq
56
+ name: redis
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 5.2.1
61
+ version: 4.1.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: 5.2.1
68
+ version: 4.1.2
69
69
  - !ruby/object:Gem::Dependency
70
- name: redis
70
+ name: redis-namespace
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 4.1.2
75
+ version: 1.6.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 4.1.2
82
+ version: 1.6.0
83
83
  - !ruby/object:Gem::Dependency
84
- name: redis-namespace
84
+ name: sidekiq
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 1.6.0
89
+ version: 5.2.1
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 1.6.0
96
+ version: 5.2.1
97
97
  - !ruby/object:Gem::Dependency
98
- name: connection_pool
98
+ name: sinatra
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 2.2.1
103
+ version: 2.0.4
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 2.2.1
110
+ version: 2.0.4
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -146,6 +146,8 @@ files:
146
146
  - ".gitignore"
147
147
  - ".gitlab-ci.yml"
148
148
  - ".rubocop.yml"
149
+ - ".rubocop_todo.yml"
150
+ - ".ruby-version"
149
151
  - CONTRIBUTING.md
150
152
  - Gemfile
151
153
  - Gemfile.lock
@@ -206,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
206
208
  - !ruby/object:Gem::Version
207
209
  version: '0'
208
210
  requirements: []
209
- rubygems_version: 3.0.3
211
+ rubygems_version: 3.1.4
210
212
  signing_key:
211
213
  specification_version: 4
212
214
  summary: GitLab metrics exporter