feat(metrics): expose pgx pool acquisition metrics

What

Surfaces pgx's pgxpool.Stat() acquisition statistics on the existing scrape-time pool collector (internal/metrics/database.go). No new collector, no ticker: the same Collect that already reads the pool for the size and capacity gauges now also emits four cumulative counters.

Why

The only pool telemetry was gitlab_artifact_registry_database_connection_pool_size{state} plus the capacity gauge, which show composition and not pressure. Acquisition waits, pool-exhaustion stalls and abandoned acquires were invisible, and those are exactly the signals an operator needs when the service slows down under load with the database itself healthy. A saturated pool and an idle one also look identical one scrape after a stall clears, so the gauges cannot recover it after the fact.

Metrics

All unlabeled, so the mean wait is a plain division with no matching modifier:

Name Type Source
gitlab_artifact_registry_database_connection_pool_acquires_total Counter Stat.AcquireCount
gitlab_artifact_registry_database_connection_pool_acquire_duration_seconds_total Counter Stat.AcquireDuration
gitlab_artifact_registry_database_connection_pool_empty_acquires_total Counter Stat.EmptyAcquireCount
gitlab_artifact_registry_database_connection_pool_canceled_acquires_total Counter Stat.CanceledAcquireCount

Stat.MaxConns was already published as gitlab_artifact_registry_database_connection_pool_max_size, so the issue's "configured max connections" needs no new series.

Counters rather than gauges, because each value is a lifetime total that only grows while the pool lives, and the pool is created once per process. A sum of waits rather than a histogram, because Stat reports only the total: there is no per-acquisition observation to bucket, so no quantile is available from it.

The four publish unconditionally, including before Client.Start creates the pool: zero acquisitions is a true count, unlike a zero maximum, which the capacity gauge still withholds.

Tests

internal/metrics/database_test.go mirrors the existing collector suite: the counter type and value per name, publication at the PoolStats zero value, and the scrape-time read (a growing total surfaces on the second gather without re-registration). The pedantic-registry Describe test now covers all six descriptors.

cmd/artifact-registry/main_integration_test.go gets the live-pool coverage the poolStats adapter needs, alongside the existing size and capacity assertions: the adapter maps four pgxpool.Stat accessors, and only a real pool separates a wired field from the zero value.

No e2e scenario

Metrics-only. No route, status code, payload or database write changes, so no scenario in docs/testing/ is added or affected.

Closes #1085 (closed)

Merge request reports

Loading
Loading