gitlab-exporter 17.0.0 → 17.0.2
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 +4 -4
- data/.gitlab-ci.yml +3 -3
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/AGENTS.md +75 -0
- data/CLAUDE.md +1 -0
- data/Gemfile.lock +7 -7
- data/README.md +54 -2
- data/gitlab-exporter.gemspec +2 -2
- data/lib/gitlab_exporter/database/ci_builds.rb +41 -0
- data/lib/gitlab_exporter/database/tuple_stats.rb +0 -2
- data/lib/gitlab_exporter/version.rb +1 -1
- data/spec/database/ci_builds_spec.rb +52 -0
- data/spec/database/tuple_stats_spec.rb +40 -0
- data/spec/prometheus_metrics_spec.rb +20 -6
- metadata +8 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0f38401d83375e243787b0f692035d11cc9cc9e5a3bde34ca9d468261be12a41
|
|
4
|
+
data.tar.gz: 4f8f1dbed6854da6003209745214b6687f405145b79c5dc2a0ee06d0bbedec4f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7c88e061a15dcc9f640c29a910de6d81eedb345c113bce789b08a44a252ddc708bdb082e5aa7ee881eb383dcf51c72d34fd7ec8c00353fe210e0b97915e05ab4
|
|
7
|
+
data.tar.gz: 9a26c277997d178c65607aadbba2b82b931bc1375a1f732c35665639cfb1a404869409272f85b640df8a5f101cf25eddee985c1f20dbb8d75f6904aaffd1e7c6
|
data/.gitlab-ci.yml
CHANGED
|
@@ -32,7 +32,7 @@ default:
|
|
|
32
32
|
# to avoid https://github.com/rubygems/rubygems/issues/5380 use an
|
|
33
33
|
# older Bundler version.
|
|
34
34
|
case ${RUBY_VERSION} in
|
|
35
|
-
"3.
|
|
35
|
+
"3.1")
|
|
36
36
|
export BUNDLER_VERSION="2.4.20"
|
|
37
37
|
;;
|
|
38
38
|
esac
|
|
@@ -53,7 +53,7 @@ rspec:
|
|
|
53
53
|
before_script: *before_scripts
|
|
54
54
|
parallel:
|
|
55
55
|
matrix:
|
|
56
|
-
- RUBY_VERSION: ["3.
|
|
56
|
+
- RUBY_VERSION: ["3.1", "3.2", "3.3", "3.4", "4.0"]
|
|
57
57
|
|
|
58
58
|
rspec_integration:
|
|
59
59
|
script:
|
|
@@ -88,7 +88,7 @@ rspec_integration:
|
|
|
88
88
|
REDIS_SENTINEL_PASSWORD: "my-sentinel-password"
|
|
89
89
|
parallel:
|
|
90
90
|
matrix:
|
|
91
|
-
- RUBY_VERSION: ["3.
|
|
91
|
+
- RUBY_VERSION: ["3.1", "3.2", "3.3", "3.4", "4.0"]
|
|
92
92
|
|
|
93
93
|
rubocop:
|
|
94
94
|
script:
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.1.7
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# gitlab-exporter — AI agent guidelines
|
|
2
|
+
|
|
3
|
+
gitlab-exporter is a Prometheus web exporter (a Ruby gem) that collects GitLab
|
|
4
|
+
production metrics via custom probes and exposes them over HTTP for a Prometheus
|
|
5
|
+
scraper. See `README.md` for the probe catalog.
|
|
6
|
+
|
|
7
|
+
## Project layout
|
|
8
|
+
|
|
9
|
+
- `lib/gitlab_exporter/` — probes and the exporter runtime
|
|
10
|
+
- `lib/gitlab_exporter/version.rb` — the gem version; bumping this on `master`
|
|
11
|
+
triggers a release (see below)
|
|
12
|
+
- `bin/gitlab-exporter` — executable entry point
|
|
13
|
+
- `spec/` — RSpec tests (`-t integration` marks integration specs that need Redis/PG)
|
|
14
|
+
|
|
15
|
+
## Development commands
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
bundle install
|
|
19
|
+
bundle exec rspec spec # unit tests
|
|
20
|
+
bundle exec rspec spec -t integration # integration tests (needs Redis/Postgres)
|
|
21
|
+
bundle exec rubocop # lint
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Commit messages
|
|
25
|
+
|
|
26
|
+
Follow the [GitLab commit message guidelines](https://docs.gitlab.com/development/contributing/merge_request_workflow/#commit-messages-guidelines).
|
|
27
|
+
|
|
28
|
+
- Subject: imperative mood, capitalized, no trailing period, ≤ 72 chars
|
|
29
|
+
("Add Zoekt probe", not "Added Zoekt probe").
|
|
30
|
+
- Body: explain *why*, wrap at 72 chars. Reference issues/MRs with full URLs,
|
|
31
|
+
not short references (`#123`).
|
|
32
|
+
|
|
33
|
+
## Changelog trailer (required for user-facing changes)
|
|
34
|
+
|
|
35
|
+
Releases are cut by the `gem-release` CI component, which builds the release
|
|
36
|
+
notes from GitLab's changelog generator. That generator **only includes commits
|
|
37
|
+
that carry a `Changelog:` git trailer** — commits without one are dropped, which
|
|
38
|
+
is why a release can end up saying "No changes." and produce an empty changelog
|
|
39
|
+
in downstream projects (e.g. omnibus-gitlab's Renovate MRs).
|
|
40
|
+
|
|
41
|
+
Add the trailer as a **separate block at the end of the commit message**,
|
|
42
|
+
preceded by a blank line (the blank line is required for git to parse it as a
|
|
43
|
+
trailer; without it the changelog generator silently drops the commit):
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Changelog: <type>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Valid types: `added`, `fixed`, `changed`, `deprecated`, `removed`, `security`,
|
|
50
|
+
`performance`, `other`.
|
|
51
|
+
|
|
52
|
+
**Include a trailer for:** new or changed probes/metrics, behavior changes,
|
|
53
|
+
bug fixes, dependency bumps that affect users, security fixes.
|
|
54
|
+
|
|
55
|
+
**Skip the trailer for:** test-only changes, documentation-only changes, CI/
|
|
56
|
+
tooling-only changes, and pure internal refactors with no user-visible effect.
|
|
57
|
+
|
|
58
|
+
Example:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Add remote mirror staleness metric
|
|
62
|
+
|
|
63
|
+
Exposes project_remote_mirror_last_successful_update_time_seconds so
|
|
64
|
+
operators can alert on mirrors that have stopped syncing.
|
|
65
|
+
|
|
66
|
+
Changelog: added
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Releasing
|
|
70
|
+
|
|
71
|
+
A release happens when `lib/gitlab_exporter/version.rb` changes on `master`.
|
|
72
|
+
The CI pipeline then generates the changelog from the `Changelog:` trailers
|
|
73
|
+
since the previous tag, creates the GitLab Release, and publishes the gem to
|
|
74
|
+
RubyGems. Keeping trailers accurate on every merged commit is what makes those
|
|
75
|
+
release notes meaningful.
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
data/Gemfile.lock
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
gitlab-exporter (17.0.
|
|
5
|
-
base64 (= 0.
|
|
4
|
+
gitlab-exporter (17.0.2)
|
|
5
|
+
base64 (= 0.3.0)
|
|
6
6
|
connection_pool (= 2.5.5)
|
|
7
7
|
deep_merge (~> 1.2.2)
|
|
8
8
|
faraday (= 2.14.3)
|
|
@@ -17,7 +17,7 @@ GEM
|
|
|
17
17
|
remote: https://rubygems.org/
|
|
18
18
|
specs:
|
|
19
19
|
ast (2.4.3)
|
|
20
|
-
base64 (0.
|
|
20
|
+
base64 (0.3.0)
|
|
21
21
|
connection_pool (2.5.5)
|
|
22
22
|
deep_merge (1.2.2)
|
|
23
23
|
diff-lcs (1.5.0)
|
|
@@ -57,11 +57,11 @@ GEM
|
|
|
57
57
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
58
58
|
rspec-support (~> 3.12.0)
|
|
59
59
|
rspec-support (3.12.0)
|
|
60
|
-
rubocop (1.
|
|
60
|
+
rubocop (1.89.0)
|
|
61
61
|
json (~> 2.3)
|
|
62
62
|
language_server-protocol (~> 3.17.0.2)
|
|
63
63
|
lint_roller (~> 1.1.0)
|
|
64
|
-
parallel (
|
|
64
|
+
parallel (>= 1.10)
|
|
65
65
|
parser (>= 3.3.0.2)
|
|
66
66
|
rainbow (>= 2.2.2, < 4.0)
|
|
67
67
|
regexp_parser (>= 2.9.3, < 3.0)
|
|
@@ -78,7 +78,7 @@ GEM
|
|
|
78
78
|
redis (>= 4.5.0, < 5)
|
|
79
79
|
unicode-display_width (3.1.4)
|
|
80
80
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
|
81
|
-
unicode-emoji (4.0
|
|
81
|
+
unicode-emoji (4.2.0)
|
|
82
82
|
webrick (1.9.1)
|
|
83
83
|
|
|
84
84
|
PLATFORMS
|
|
@@ -91,4 +91,4 @@ DEPENDENCIES
|
|
|
91
91
|
rubocop (~> 1.0)
|
|
92
92
|
|
|
93
93
|
BUNDLED WITH
|
|
94
|
-
|
|
94
|
+
4.0.10
|
data/README.md
CHANGED
|
@@ -23,9 +23,10 @@ metrics.
|
|
|
23
23
|
`gitlab_pg_sequences_min_value`, `gitlab_pg_sequences_max_value`, `gitlab_pg_sequences_current_value`
|
|
24
24
|
* [Row count queries](lib/gitlab_exporter/database/row_count.rb) --
|
|
25
25
|
`gitlab_database_rows`
|
|
26
|
-
* [CI builds](lib/gitlab_exporter/database/ci_builds.rb) --
|
|
26
|
+
* [CI builds](lib/gitlab_exporter/database/ci_builds.rb) (**deprecated**) --
|
|
27
27
|
`ci_pending_builds`, `ci_created_builds`, `ci_stale_builds`,
|
|
28
|
-
`ci_running_builds`
|
|
28
|
+
`ci_running_builds`, `ci_unarchived_traces`
|
|
29
|
+
(see [Deprecated: CI builds metrics](#deprecated-ci-builds-metrics))
|
|
29
30
|
* [Bloat](lib/gitlab_exporter/database/bloat.rb) --
|
|
30
31
|
`gitlab_database_bloat_$type_$key` with type `btree` (index bloat) or `table`
|
|
31
32
|
(table bloat) and keys `bloat_ratio bloat_size extra_size real_size` (see below)
|
|
@@ -133,6 +134,57 @@ Also see the [original documentation](https://github.com/ioguix/pgsql-bloat-esti
|
|
|
133
134
|
Note that all metrics returned are estimates without an upper bound for
|
|
134
135
|
the error.
|
|
135
136
|
|
|
137
|
+
### Deprecated: CI builds metrics
|
|
138
|
+
|
|
139
|
+
The [CI builds probe](lib/gitlab_exporter/database/ci_builds.rb) is deprecated and
|
|
140
|
+
will be removed in a future major version. It collects its metrics by querying
|
|
141
|
+
`p_ci_builds` directly, which puts avoidable load on tables that job scheduling
|
|
142
|
+
already loads heavily, and it has had almost no maintenance since 2021. GitLab
|
|
143
|
+
Rails and GitLab Runner instrument most of the same information by counting
|
|
144
|
+
events as they happen; GitLab.com stopped using this probe for CI state years
|
|
145
|
+
ago.
|
|
146
|
+
|
|
147
|
+
The probe prints a deprecation notice on every run, and each of its metrics
|
|
148
|
+
carries `(deprecated, ...)` in its `# HELP` line, so the warning reaches
|
|
149
|
+
Prometheus and Grafana and not only the exporter's log.
|
|
150
|
+
|
|
151
|
+
Replacements, where one exists:
|
|
152
|
+
|
|
153
|
+
| Deprecated metric | Replacement |
|
|
154
|
+
| --- | --- |
|
|
155
|
+
| `ci_pending_builds` | `gitlab_ci_current_queue_size` (Rails, gauge, by `runner_type`) |
|
|
156
|
+
| `ci_running_builds` | `gitlab_runner_jobs` (Runner, gauge, by `runner`, `state`, `stage`) |
|
|
157
|
+
| `ci_created_builds` | None. A `created` build is not queued yet, so nothing counts it. |
|
|
158
|
+
| `ci_stale_builds` | None. The nearest signal is `gitlab_ci_queue_operations_total{operation="build_status_stale"}` (Rails, counter), which counts stale rows met while queueing rather than how many are stale now. |
|
|
159
|
+
| `ci_unarchived_traces` | None. |
|
|
160
|
+
|
|
161
|
+
The replacements are not a like-for-like relabel: the Rails queue metrics are
|
|
162
|
+
keyed by `runner_type` and the Runner metrics by runner, so neither carries the
|
|
163
|
+
`namespace` label this probe reports. Queue health is better served by the Rails
|
|
164
|
+
metrics that have no exporter equivalent at all -- `job_queue_duration_seconds`
|
|
165
|
+
(how long jobs wait), `job_register_attempts_total` and
|
|
166
|
+
`job_register_attempts_failed_total`, and `gitlab_ci_queue_operations_total`.
|
|
167
|
+
Those four are always instrumented.
|
|
168
|
+
|
|
169
|
+
**`gitlab_ci_current_queue_size`, and every other `gitlab_ci_queue_*` metric, is
|
|
170
|
+
behind the `gitlab_ci_builds_queuing_metrics` ops feature flag, which is disabled
|
|
171
|
+
by default.** Enable it before pointing a dashboard at them, or the replacement
|
|
172
|
+
panels stay empty:
|
|
173
|
+
|
|
174
|
+
```ruby
|
|
175
|
+
Feature.enable(:gitlab_ci_builds_queuing_metrics)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Metric definitions live in
|
|
179
|
+
[`lib/gitlab/ci/queue/metrics.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/queue/metrics.rb)
|
|
180
|
+
(Rails) and
|
|
181
|
+
[`commands/builds_helper.go`](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/main/commands/builds_helper.go)
|
|
182
|
+
(Runner). See
|
|
183
|
+
[GitLab Prometheus metrics](https://docs.gitlab.com/administration/monitoring/prometheus/gitlab_metrics/)
|
|
184
|
+
for enabling the Rails exporter, and
|
|
185
|
+
[Monitoring runners](https://docs.gitlab.com/runner/monitoring/) for the
|
|
186
|
+
Runner's.
|
|
187
|
+
|
|
136
188
|
## Contributing
|
|
137
189
|
|
|
138
190
|
gitlab-exporter is an open source project and we are very happy to accept community contributions. Please refer to [CONTRIBUTING.md](/CONTRIBUTING.md) for details.
|
data/gitlab-exporter.gemspec
CHANGED
|
@@ -20,12 +20,12 @@ Gem::Specification.new do |s|
|
|
|
20
20
|
s.homepage = "https://gitlab.com/gitlab-org/ruby/gems/gitlab-exporter"
|
|
21
21
|
s.license = "MIT"
|
|
22
22
|
|
|
23
|
-
s.required_ruby_version = Gem::Requirement.new(">= 3.
|
|
23
|
+
s.required_ruby_version = Gem::Requirement.new(">= 3.1")
|
|
24
24
|
|
|
25
25
|
# base64 is required by sidekiq but not declared by it, and is no longer a
|
|
26
26
|
# default gem as of Ruby 3.4. It used to be pulled in transitively via
|
|
27
27
|
# sinatra -> rack-protection; declare it directly now that those are gone.
|
|
28
|
-
s.add_runtime_dependency "base64", "0.
|
|
28
|
+
s.add_runtime_dependency "base64", "0.3.0"
|
|
29
29
|
s.add_runtime_dependency "connection_pool", "2.5.5"
|
|
30
30
|
s.add_runtime_dependency "deep_merge", "~> 1.2.2"
|
|
31
31
|
s.add_runtime_dependency "faraday", "2.14.3"
|
|
@@ -294,12 +294,53 @@ module GitLab
|
|
|
294
294
|
|
|
295
295
|
# The prober which is called when gathering metrics
|
|
296
296
|
class CiBuildsProber
|
|
297
|
+
# The stdout notice in #probe_db reaches whoever reads the exporter's log,
|
|
298
|
+
# which is not who reads the metrics. HELP is the one channel that travels
|
|
299
|
+
# with the sample to the scraper, so the deprecation rides there too: it
|
|
300
|
+
# survives into Prometheus and shows up in Grafana's metric browser.
|
|
301
|
+
DEPRECATED = "(deprecated, to be removed in a future major version)".freeze
|
|
302
|
+
REPLACEMENT = "See the CI builds entry in README.md for replacements.".freeze
|
|
303
|
+
|
|
304
|
+
PrometheusMetrics.describe(
|
|
305
|
+
"ci_created_builds",
|
|
306
|
+
"#{DEPRECATED} Number of CI builds in the created state, by namespace. #{REPLACEMENT}",
|
|
307
|
+
"gauge"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
PrometheusMetrics.describe(
|
|
311
|
+
"ci_pending_builds",
|
|
312
|
+
"#{DEPRECATED} Number of CI builds in the pending state, by namespace. #{REPLACEMENT}",
|
|
313
|
+
"gauge"
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
PrometheusMetrics.describe(
|
|
317
|
+
"ci_stale_builds",
|
|
318
|
+
"#{DEPRECATED} Number of running CI builds not updated for over an hour. #{REPLACEMENT}",
|
|
319
|
+
"gauge"
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
PrometheusMetrics.describe(
|
|
323
|
+
"ci_running_builds",
|
|
324
|
+
"#{DEPRECATED} Number of running CI builds, by runner and namespace. #{REPLACEMENT}",
|
|
325
|
+
"gauge"
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
PrometheusMetrics.describe(
|
|
329
|
+
"ci_unarchived_traces",
|
|
330
|
+
"#{DEPRECATED} Number of finished CI builds whose trace is not archived. #{REPLACEMENT}",
|
|
331
|
+
"gauge"
|
|
332
|
+
)
|
|
333
|
+
|
|
297
334
|
def initialize(metrics: PrometheusMetrics.new, **opts)
|
|
298
335
|
@metrics = metrics
|
|
299
336
|
@collector = CiBuildsCollector.new(**opts)
|
|
300
337
|
end
|
|
301
338
|
|
|
302
339
|
def probe_db
|
|
340
|
+
puts "[DEPRECATED] probe_db and CiBuildsProber are now considered obsolete"\
|
|
341
|
+
" and will be removed in a future major version,"\
|
|
342
|
+
" please use the CI/CD queuing metrics emitted by GitLab Rails instead"
|
|
343
|
+
|
|
303
344
|
@results = @collector.run
|
|
304
345
|
|
|
305
346
|
ci_builds_metrics(@results[:created_builds], "ci_created_builds") if @results[:created_builds]
|
|
@@ -361,3 +361,55 @@ describe GitLab::Exporter::Database do
|
|
|
361
361
|
end
|
|
362
362
|
end
|
|
363
363
|
end
|
|
364
|
+
|
|
365
|
+
# Asserting on the notice keeps a later refactor of #probe_db from dropping it
|
|
366
|
+
# silently, which would leave operators unwarned before the probe goes (issue #119).
|
|
367
|
+
describe GitLab::Exporter::Database::CiBuildsProber do
|
|
368
|
+
let(:prober) do
|
|
369
|
+
described_class.new(connection_string: "host=localhost",
|
|
370
|
+
metrics: GitLab::Exporter::PrometheusMetrics.new(include_timestamp: false))
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
let(:metric_names) do
|
|
374
|
+
%w[ci_created_builds ci_pending_builds ci_stale_builds ci_running_builds ci_unarchived_traces]
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
it "warns that the probe is deprecated and names the replacement" do
|
|
378
|
+
allow_any_instance_of(GitLab::Exporter::Database::CiBuildsCollector).to receive(:run)
|
|
379
|
+
.and_return(pending_builds: [], stale_builds: 0, per_runner: [], unarchived_traces: 0)
|
|
380
|
+
|
|
381
|
+
expect { prober.probe_db }.to output(/\[DEPRECATED\].*CiBuildsProber.*GitLab Rails/m).to_stdout
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# The stdout notice never reaches the scraper. HELP does, so every metric the
|
|
385
|
+
# probe can emit has to carry the deprecation, not just the ones with a
|
|
386
|
+
# replacement.
|
|
387
|
+
it "describes every metric it can emit as deprecated" do
|
|
388
|
+
metric_names.each do |name|
|
|
389
|
+
expect(GitLab::Exporter::PrometheusMetrics.description(name))
|
|
390
|
+
.to start_with("(deprecated"), "#{name} is emitted without a deprecated HELP line"
|
|
391
|
+
expect(GitLab::Exporter::PrometheusMetrics.metric_type(name)).to eq("gauge")
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
it "renders the deprecation into the scrape output" do
|
|
396
|
+
allow_any_instance_of(GitLab::Exporter::Database::CiBuildsCollector).to receive(:run)
|
|
397
|
+
.and_return(pending_builds: [{ namespace: "1", shared_runners: "yes", value: 12 }],
|
|
398
|
+
stale_builds: 3, per_runner: [], unarchived_traces: 0)
|
|
399
|
+
|
|
400
|
+
output = StringIO.new
|
|
401
|
+
capture_stdout do prober.probe_db.write_to(output) end
|
|
402
|
+
|
|
403
|
+
expect(output.string).to include("# HELP ci_pending_builds (deprecated")
|
|
404
|
+
expect(output.string).to include("# TYPE ci_pending_builds gauge")
|
|
405
|
+
expect(output.string).to include(%(ci_pending_builds{namespace="1",shared_runners="yes"} 12.0))
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def capture_stdout
|
|
409
|
+
original = $stdout
|
|
410
|
+
$stdout = StringIO.new
|
|
411
|
+
yield
|
|
412
|
+
ensure
|
|
413
|
+
$stdout = original
|
|
414
|
+
end
|
|
415
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "gitlab_exporter/database/tuple_stats"
|
|
3
|
+
|
|
4
|
+
describe GitLab::Exporter::Database::TuplesProber do
|
|
5
|
+
let(:opts) { { connection_string: "" } }
|
|
6
|
+
let(:metrics) { double("PrometheusMetrics", add: nil) }
|
|
7
|
+
let(:collector) { double("TupleStatsCollector", run: data) }
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
allow(GitLab::Exporter::Database::TupleStatsCollector).to receive(:new).and_return(collector)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "#probe_db" do
|
|
14
|
+
subject { described_class.new(metrics: metrics, **opts).probe_db }
|
|
15
|
+
|
|
16
|
+
context "when the connection casts columns to native Integer (PG::BasicTypeMapForResults)" do
|
|
17
|
+
let(:data) { { "projects" => { "seq_tup_read" => 42, "n_dead_tup" => 0 } } }
|
|
18
|
+
|
|
19
|
+
it "still records a metric for every column" do
|
|
20
|
+
expect(metrics).to receive(:add)
|
|
21
|
+
.with("gitlab_database_stat_table_seq_tup_read", 42.0, table_name: "projects")
|
|
22
|
+
expect(metrics).to receive(:add)
|
|
23
|
+
.with("gitlab_database_stat_table_n_dead_tup", 0.0, table_name: "projects")
|
|
24
|
+
|
|
25
|
+
subject
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "when the connection returns unmapped string values" do
|
|
30
|
+
let(:data) { { "projects" => { "seq_tup_read" => "42" } } }
|
|
31
|
+
|
|
32
|
+
it "records a metric" do
|
|
33
|
+
expect(metrics).to receive(:add)
|
|
34
|
+
.with("gitlab_database_stat_table_seq_tup_read", 42.0, table_name: "projects")
|
|
35
|
+
|
|
36
|
+
subject
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -29,15 +29,29 @@ describe GitLab::Exporter::PrometheusMetrics do
|
|
|
29
29
|
|
|
30
30
|
allow(Time).to receive(:now).and_return(time)
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
# Descriptions are class-level state, and probes register theirs when their
|
|
33
|
+
# file loads, which happens once. Describing on a subclass keeps this example
|
|
34
|
+
# out of the shared registry: clearing it here would drop those registrations
|
|
35
|
+
# for every later example, and nothing can put them back.
|
|
36
|
+
metrics_class = Class.new(described_class)
|
|
37
|
+
metrics = metrics_class.new
|
|
38
|
+
|
|
39
|
+
metrics_class.describe("mymetric", "description")
|
|
40
|
+
metrics_class.describe("missingmetric", "otherdescription")
|
|
41
|
+
metrics.add("mymetric", 1.3, mylabel: "x", myotherlabel: "y")
|
|
42
|
+
|
|
43
|
+
expect(metrics.to_s).to eq(<<~METRICS)
|
|
37
44
|
# HELP mymetric description
|
|
38
45
|
mymetric{mylabel="x",myotherlabel="y"} 1.3 #{(time.to_f * 1000).to_i}
|
|
39
46
|
METRICS
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "clears descriptions" do
|
|
50
|
+
metrics_class = Class.new(described_class)
|
|
51
|
+
metrics_class.describe("mymetric", "description", "gauge")
|
|
40
52
|
|
|
41
|
-
|
|
53
|
+
expect { metrics_class.clear_descriptions }
|
|
54
|
+
.to change { metrics_class.description("mymetric") }.from("description").to(nil)
|
|
55
|
+
expect(metrics_class.metric_type("mymetric")).to be_nil
|
|
42
56
|
end
|
|
43
57
|
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: 17.0.
|
|
4
|
+
version: 17.0.2
|
|
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: 0.
|
|
19
|
+
version: 0.3.0
|
|
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: 0.
|
|
26
|
+
version: 0.3.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: connection_pool
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -191,6 +191,8 @@ files:
|
|
|
191
191
|
- ".rubocop.yml"
|
|
192
192
|
- ".rubocop_todo.yml"
|
|
193
193
|
- ".ruby-version"
|
|
194
|
+
- AGENTS.md
|
|
195
|
+
- CLAUDE.md
|
|
194
196
|
- CONTRIBUTING.md
|
|
195
197
|
- Gemfile
|
|
196
198
|
- Gemfile.lock
|
|
@@ -230,6 +232,7 @@ files:
|
|
|
230
232
|
- spec/database/ci_builds_spec.rb
|
|
231
233
|
- spec/database/pg_sequences_spec.rb
|
|
232
234
|
- spec/database/row_count_spec.rb
|
|
235
|
+
- spec/database/tuple_stats_spec.rb
|
|
233
236
|
- spec/database/zoekt_spec.rb
|
|
234
237
|
- spec/elasticsearch_spec.rb
|
|
235
238
|
- spec/fixtures/config.yml
|
|
@@ -256,7 +259,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
256
259
|
requirements:
|
|
257
260
|
- - ">="
|
|
258
261
|
- !ruby/object:Gem::Version
|
|
259
|
-
version: '3.
|
|
262
|
+
version: '3.1'
|
|
260
263
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
261
264
|
requirements:
|
|
262
265
|
- - ">="
|
|
@@ -273,6 +276,7 @@ test_files:
|
|
|
273
276
|
- spec/database/ci_builds_spec.rb
|
|
274
277
|
- spec/database/pg_sequences_spec.rb
|
|
275
278
|
- spec/database/row_count_spec.rb
|
|
279
|
+
- spec/database/tuple_stats_spec.rb
|
|
276
280
|
- spec/database/zoekt_spec.rb
|
|
277
281
|
- spec/elasticsearch_spec.rb
|
|
278
282
|
- spec/fixtures/config.yml
|