Repository navigation
fix: read the pool gauges when they are scraped, and never export a negative overflow - #62
Merged
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #54.
Problem
The three pool gauges were sampled from the pool's
checkout/checkinevents and exported unchanged:pool_overflowwasQueuePool.overflow(), which starts at-pool_size. A pool withsize=10and one open connection reported-9.checkinfires before the connection goes back to the pool, and nothing fires once the pool is idle. So an idle pool kept reporting its last burst (checked_out=2, overflow=2with every connection returned).pool_sizeis the configuredpool_size, but the HELP text and docs called it the current size.Change
PoolStatsFunctionRecorder.set_pool_stats_functions(pool_size, pool_checked_out, pool_overflow). It takes zero-argument callables and lives next toCheckoutWaitRecorder, detected the same way withisinstance, soPostgresMetricsProtocolis unchanged.PostgresMetricsimplements it withGauge.set_function, which means the gauges are read when Prometheus scrapes.attach_metricsbinds the callables toengine.pool, looked up on each read, so the pool thatdispose()creates is the one reported. For such a recorder the pool events no longer sample the gauges. They still feed the held-duration histogram.pool_overflowismax(pool.overflow(), 0)on both paths.pool_sizekeeps its value, the configuredpool_size, and the HELP text, protocol docstring and docs now say so. The utilization PromQL gets a note that it passes 100 % while overflow connections are in use.record_pool_statskeeps the event path (with the clamp). Its docstring and the docs say that it lags one return behind and point at the new capability.Exported from
sqlalchemy_foundation_kitandsqlalchemy_foundation_kit.protocols;docs/agents.mdis updated.Considered and rejected
pool_sizereport open connections (checkedin() + checkedout()), as the old docs claimed. That would silently change the meaning of a series people already graph. Correcting the text costs nobody anything.checkinlistener. That depends on SQLAlchemy dispatchingcheckinbefore_return_connand onQueuePoolclosing a returned connection when the queue is full. It's internal ordering, and reading at scrape time doesn't need it.Who notices
Dashboards and alerts on
postgres_db_pool_overflow(no more negative values) andpostgres_db_pool_checked_out(drops to 0 when the pool is idle, instead of holding the last burst).pool_sizevalues don't change, only its HELP text. A custom metrics class doesn't need to change. It can opt in to read-on-scrape by addingset_pool_stats_functions. Release-wise this is afix:that adds one optional protocol.Evidence
New tests against the old
manager.py,metrics/postgres.pyand protocols (swapped in fromorigin/master): 8 failed. That includes the integration test, which runs the reporter's sequence on PostgreSQL 17 and reads the registry by name.The reporter's script after the fix:
Gate:
make checkclean;make test634 passed, coverage 93.87%.