gitlab-exporter 7.0.5 → 7.2.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: de89f0131cde7415ce666ec09c4da388b53f4cbf57b8e7872f3e5538be257e30
4
- data.tar.gz: 4b84a64c0d3b26306628ec04dc2ce7b56b36eda349385a43855b1a968c2a8560
3
+ metadata.gz: 86ad2e8d49582c70ba5faa5e7a8744a0e812f5682447cc1e1f000e050a3b9451
4
+ data.tar.gz: 2a0f878e42abef28992284e0e372db960831025b7ff3cf71c676369210d05fea
5
5
  SHA512:
6
- metadata.gz: a292b9c5c4f24fab3014e6bc9ae5f3b86c86ff47d5034fce9280d1fa75372cbcd18e5d75a6e130c9de77fc662b1ef2fa6d1dd9f390a004236c727e311a9e02a3
7
- data.tar.gz: 6f1309c2abeeeca930d0485d66b9b714006f1d97814141fba7f6a2b4db063ee41f0181857de0044435d8e3b14d10e844d2ed595a5ce2505fe63a02ef6abce466
6
+ metadata.gz: 28d6f61e6df16ac17ba9e25ddea5d6a39c65940796898a2a6bad66c352ad47a1341593e3bb8dd7edaefd5281a787612beda9ff6f3f3700c6c458ad345fef055d
7
+ data.tar.gz: f7b2ff3ddd97529571e0517f4b8f9c7d42fe512f5d786a9c60dfae6337cafc56f5ae8eecaf98e3d85d0cb987e66363102bfec40a6ff4411524359cdf888f9d3e
@@ -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
10
  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
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,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-exporter (7.0.5)
4
+ gitlab-exporter (7.2.0)
5
5
  connection_pool (~> 2.2.1)
6
6
  pg (~> 1.1)
7
7
  quantile (~> 0.2.0)
@@ -14,19 +14,20 @@ GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
16
  ast (2.4.0)
17
- connection_pool (2.2.2)
17
+ connection_pool (2.2.3)
18
18
  diff-lcs (1.3)
19
- mustermann (1.0.3)
19
+ mustermann (1.1.1)
20
+ ruby2_keywords (~> 0.0.1)
20
21
  parser (2.5.1.0)
21
22
  ast (~> 2.4.0)
22
- pg (1.2.2)
23
+ pg (1.2.3)
23
24
  powerpack (0.1.1)
24
25
  quantile (0.2.1)
25
- rack (2.0.7)
26
- rack-protection (2.0.7)
26
+ rack (2.2.3)
27
+ rack-protection (2.0.8.1)
27
28
  rack
28
29
  rainbow (2.1.0)
29
- redis (4.1.3)
30
+ redis (4.1.4)
30
31
  redis-namespace (1.6.0)
31
32
  redis (>= 3.0.4)
32
33
  rspec (3.7.0)
@@ -49,17 +50,18 @@ GEM
49
50
  ruby-progressbar (~> 1.7)
50
51
  unicode-display_width (~> 1.0, >= 1.0.1)
51
52
  ruby-progressbar (1.8.1)
52
- sidekiq (5.2.7)
53
+ ruby2_keywords (0.0.2)
54
+ sidekiq (5.2.9)
53
55
  connection_pool (~> 2.2, >= 2.2.2)
54
- rack (>= 1.5.0)
56
+ rack (~> 2.0)
55
57
  rack-protection (>= 1.5.0)
56
- redis (>= 3.3.5, < 5)
57
- sinatra (2.0.7)
58
+ redis (>= 3.3.5, < 4.2)
59
+ sinatra (2.0.8.1)
58
60
  mustermann (~> 1.0)
59
61
  rack (~> 2.0)
60
- rack-protection (= 2.0.7)
62
+ rack-protection (= 2.0.8.1)
61
63
  tilt (~> 2.0)
62
- tilt (2.0.9)
64
+ tilt (2.0.10)
63
65
  unicode-display_width (1.6.0)
64
66
 
65
67
  PLATFORMS
@@ -16,8 +16,9 @@ module GitLab
16
16
  end
17
17
  end
18
18
 
19
- def initialize(args)
19
+ def initialize(args, logger: nil)
20
20
  @connection_string = args[:connection_string]
21
+ @logger = logger
21
22
  end
22
23
 
23
24
  def run
@@ -33,10 +34,14 @@ module GitLab
33
34
  begin
34
35
  yield conn
35
36
  rescue PG::UnableToSend => e
37
+ @logger.warn "Error sending to the database: #{e}" if @logger
36
38
  conn.reset
37
39
  raise e
38
40
  end
39
41
  end
42
+ rescue PG::Error => e
43
+ @logger.error "Error connecting to the database: #{e}" if @logger
44
+ raise e
40
45
  end
41
46
  end
42
47
  end
@@ -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
@@ -39,9 +41,11 @@ module GitLab
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
48
+ @collector.logger = logger
45
49
  @bloat_types = opts[:bloat_types] || %i(btree table)
46
50
  end
47
51
 
@@ -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;
@@ -21,8 +21,7 @@ module GitLab
21
21
  ON namespaces.id = projects.namespace_id
22
22
  LEFT JOIN namespace_statistics
23
23
  ON namespace_statistics.namespace_id = namespaces.id
24
- JOIN application_settings
25
- ON application_settings.id = 1
24
+ JOIN application_settings ON (TRUE)
26
25
  WHERE ci_builds.type = 'Ci::Build'
27
26
  AND ci_builds.status = '%s'
28
27
  -- The created_at filter has been introduced for performance reasons only
@@ -95,8 +94,7 @@ module GitLab
95
94
  ON namespaces.id = projects.namespace_id
96
95
  LEFT JOIN namespace_statistics
97
96
  ON namespace_statistics.namespace_id = namespaces.id
98
- JOIN application_settings
99
- ON application_settings.id = 1
97
+ JOIN application_settings ON (TRUE)
100
98
  WHERE ci_builds.type = 'Ci::Build'
101
99
  AND ci_builds.status = 'running'
102
100
  -- The created_at filter has been introduced for performance reasons only
@@ -175,8 +173,7 @@ module GitLab
175
173
  ON namespaces.id = projects.namespace_id
176
174
  LEFT JOIN namespace_statistics
177
175
  ON namespace_statistics.namespace_id = namespaces.id
178
- JOIN application_settings
179
- ON application_settings.id = 1
176
+ JOIN application_settings ON (TRUE)
180
177
  WHERE ci_builds.type = 'Ci::Build'
181
178
  AND ci_builds.status IN ('running', 'pending')
182
179
  -- The created_at filter has been introduced for performance reasons only
@@ -265,8 +262,8 @@ module GitLab
265
262
 
266
263
  DEFAULT_UNARCHIVED_TRACES_OFFSET_MINUTES = 1440
267
264
 
268
- def initialize(opts)
269
- super(opts)
265
+ def initialize(opts, logger: nil)
266
+ super(opts, logger: logger)
270
267
 
271
268
  @allowed_repeated_commands_count = opts[:allowed_repeated_commands_count]
272
269
  @created_builds_counting_disabled = opts[:created_builds_counting_disabled]
@@ -420,14 +417,14 @@ module GitLab
420
417
 
421
418
  # The prober which is called when gathering metrics
422
419
  class CiBuildsProber
423
- def initialize(opts, metrics: PrometheusMetrics.new)
420
+ def initialize(opts, metrics: PrometheusMetrics.new, logger: nil)
424
421
  @metrics = metrics
425
422
 
426
423
  collector_opts = { connection_string: opts[:connection_string],
427
424
  allowed_repeated_commands_count: opts[:allowed_repeated_commands_count],
428
425
  created_builds_counting_disabled: opts[:created_builds_counting_disabled],
429
426
  unarchived_traces_offset_minutes: opts[:unarchived_traces_offset_minutes] }
430
- @collector = CiBuildsCollector.new(collector_opts)
427
+ @collector = CiBuildsCollector.new(collector_opts, logger: logger)
431
428
  end
432
429
 
433
430
  def probe_db
@@ -35,7 +35,7 @@ module GitLab
35
35
 
36
36
  # The prober which is called when gathering metrics
37
37
  class RemoteMirrorsProber
38
- def initialize(opts, metrics: PrometheusMetrics.new)
38
+ def initialize(opts, metrics: PrometheusMetrics.new, logger: nil) # rubocop:disable Lint/UnusedMethodArgument
39
39
  @metrics = metrics
40
40
  @collector = RemoteMirrorsCollector.new(
41
41
  connection_string: opts[:connection_string],
@@ -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
@@ -212,7 +218,7 @@ module GitLab
212
218
 
213
219
  # The prober which is called when gathering metrics
214
220
  class RowCountProber
215
- def initialize(opts, metrics: PrometheusMetrics.new)
221
+ def initialize(opts, metrics: PrometheusMetrics.new, logger: nil) # rubocop:disable Lint/UnusedMethodArgument
216
222
  @metrics = metrics
217
223
  @collector = RowCountCollector.new(
218
224
  connection_string: opts[:connection_string],
@@ -25,9 +25,9 @@ module GitLab
25
25
 
26
26
  # Probes the DB specified by opts[:connection_string] for tuple stats, then converts them to metrics
27
27
  class TuplesProber
28
- def initialize(opts, metrics: PrometheusMetrics.new)
28
+ def initialize(opts, metrics: PrometheusMetrics.new, logger: nil)
29
29
  @metrics = metrics
30
- @collector = TupleStatsCollector.new(connection_string: opts[:connection_string])
30
+ @collector = TupleStatsCollector.new(connection_string: opts[:connection_string], logger: logger)
31
31
  end
32
32
 
33
33
  def probe_db
@@ -62,7 +62,7 @@ module GitLab
62
62
  # Optionally takes a metrics object which by default is a PrometheusMetrics, useful to change the
63
63
  # metrics writer to something else.
64
64
  class GitProber
65
- def initialize(opts, metrics: PrometheusMetrics.new)
65
+ def initialize(opts, metrics: PrometheusMetrics.new, logger: nil) # rubocop:disable Lint/UnusedMethodArgument
66
66
  @metrics = metrics
67
67
  @labels = opts[:labels] || {}
68
68
  @git = Git.new(opts[:source])
@@ -85,7 +85,7 @@ module GitLab
85
85
 
86
86
  # A special prober for git processes
87
87
  class GitProcessProber
88
- def initialize(opts, metrics: PrometheusMetrics.new)
88
+ def initialize(opts, metrics: PrometheusMetrics.new, logger: nil) # rubocop:disable Lint/UnusedMethodArgument
89
89
  @opts = opts
90
90
  @metrics = metrics
91
91
  end
@@ -2,9 +2,10 @@ module GitLab
2
2
  module Exporter
3
3
  # A class to combine multiple probers into one
4
4
  class Prober
5
- def initialize(prober_opts, metrics: PrometheusMetrics.new)
5
+ def initialize(prober_opts, metrics: PrometheusMetrics.new, logger: nil)
6
6
  @prober_opts = prober_opts
7
7
  @metrics = metrics
8
+ @logger = logger
8
9
 
9
10
  resolve_prober_classes
10
11
  end
@@ -12,7 +13,7 @@ module GitLab
12
13
  def probe_all
13
14
  @prober_opts.each do |_probe_name, params|
14
15
  Utils.wrap_in_array(params[:opts]).each do |opts|
15
- prober = params[:class].new(opts, metrics: @metrics)
16
+ prober = params[:class].new(opts, metrics: @metrics, logger: @logger)
16
17
  params[:methods].each do |meth|
17
18
  prober.send(meth)
18
19
  end
@@ -59,7 +59,7 @@ module GitLab
59
59
 
60
60
  # Probes a process for info then writes metrics to a target
61
61
  class ProcessProber
62
- def initialize(options, metrics: PrometheusMetrics.new)
62
+ def initialize(options, metrics: PrometheusMetrics.new, logger: nil) # rubocop:disable Lint/UnusedMethodArgument
63
63
  @metrics = metrics
64
64
  @name = options[:name]
65
65
  @pids = if options[:pid_or_pattern] =~ /^\d+$/
@@ -10,9 +10,10 @@ module GitLab
10
10
  QUEUE_JOB_STATS_SCRIPT = File.read(File.expand_path("#{__FILE__}/../sidekiq_queue_job_stats.lua")).freeze
11
11
  QUEUE_JOB_STATS_SHA = Digest::SHA1.hexdigest(QUEUE_JOB_STATS_SCRIPT).freeze
12
12
 
13
- def initialize(opts, metrics: PrometheusMetrics.new)
13
+ def initialize(opts, metrics: PrometheusMetrics.new, logger: nil)
14
14
  @opts = opts
15
15
  @metrics = metrics
16
+ @logger = logger
16
17
 
17
18
  Sidekiq.configure_client do |config|
18
19
  config.redis = redis_options
@@ -1,5 +1,5 @@
1
1
  module GitLab
2
2
  module Exporter
3
- VERSION = "7.0.5".freeze
3
+ VERSION = "7.2.0".freeze
4
4
  end
5
5
  end
@@ -42,6 +42,11 @@ module GitLab
42
42
 
43
43
  memory_threshold = (config[:server] && config[:server][:memory_threshold]) || 1024
44
44
  use MemoryKillerMiddleware, memory_threshold
45
+ use Rack::Logger
46
+ end
47
+
48
+ def logger
49
+ request.logger
45
50
  end
46
51
 
47
52
  def setup_server(config)
@@ -62,7 +67,7 @@ module GitLab
62
67
 
63
68
  get "/#{probe_name}" do
64
69
  content_type "text/plain; version=0.0.4"
65
- prober = Prober.new(opts, metrics: PrometheusMetrics.new(include_timestamp: false))
70
+ prober = Prober.new(opts, metrics: PrometheusMetrics.new(include_timestamp: false), logger: logger)
66
71
 
67
72
  prober.probe_all
68
73
  prober.write_to(response)
@@ -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)
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-exporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.5
4
+ version: 7.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Carranza
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2016-07-27 00:00:00.000000000 Z
@@ -191,7 +191,7 @@ homepage: http://gitlab.com
191
191
  licenses:
192
192
  - MIT
193
193
  metadata: {}
194
- post_install_message:
194
+ post_install_message:
195
195
  rdoc_options: []
196
196
  require_paths:
197
197
  - lib
@@ -207,7 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
207
207
  version: '0'
208
208
  requirements: []
209
209
  rubygems_version: 3.0.3
210
- signing_key:
210
+ signing_key:
211
211
  specification_version: 4
212
212
  summary: GitLab metrics exporter
213
213
  test_files: