Merge pull request #10735 from overleaf/jpa-mongo-connection-pool-stats

[web] collect metrics for mongo connection pool

GitOrigin-RevId: 71ca95af4e04f124f5ae12c8967ce85d4d9d0428
This commit is contained in:
Jakob Ackermann 2022-11-30 14:37:26 +00:00 committed by Copybot
parent 648a08b6b8
commit 7fcdd69cee
2 changed files with 38 additions and 1 deletions

View file

@ -2,6 +2,7 @@ const mongoose = require('mongoose')
const Settings = require('@overleaf/settings')
const logger = require('@overleaf/logger')
const { addConnectionDrainer } = require('./GracefulShutdown')
const { collectStatsForDb } = require('./mongodb')
if (
typeof global.beforeEach === 'function' &&
@ -60,6 +61,8 @@ async function getNativeDb() {
return mongooseInstance.connection.db
}
getNativeDb().then(db => collectStatsForDb(db, 'mongoose'))
mongoose.getNativeDb = getNativeDb
mongoose.connectionPromise = connectionPromise

View file

@ -1,7 +1,11 @@
const Metrics = require('@overleaf/metrics')
const Settings = require('@overleaf/settings')
const { MongoClient, ObjectId } = require('mongodb')
const OError = require('@overleaf/o-error')
const { addConnectionDrainer } = require('./GracefulShutdown')
const {
addConnectionDrainer,
addOptionalCleanupHandlerAfterDrainingConnections,
} = require('./GracefulShutdown')
if (
typeof global.beforeEach === 'function' &&
@ -32,6 +36,7 @@ async function waitForDb() {
const db = {}
async function setupDb() {
const internalDb = (await clientPromise).db()
collectStatsForDb(internalDb, 'native')
db.contacts = internalDb.collection('contacts')
db.deletedFiles = internalDb.collection('deletedFiles')
@ -115,6 +120,34 @@ async function getCollectionInternal(name) {
return internalDb.collection(name)
}
function collectStatsForDb(internalDb, label) {
const collectOnce = () => {
for (const [name, server] of internalDb.s.topology.s.servers.entries()) {
const { availableConnectionCount, waitQueueSize } = server.s.pool
const { maxPoolSize } = server.s.pool.options
const opts = { status: `${label}:${name}` }
Metrics.gauge('mongo_connection_pool_max', maxPoolSize, 1, opts)
Metrics.gauge(
'mongo_connection_pool_available',
availableConnectionCount,
1,
opts
)
Metrics.gauge('mongo_connection_pool_waiting', waitQueueSize, 1, opts)
}
}
collectOnce() // init metrics
const intervalHandle = setInterval(collectOnce, 60_000)
addOptionalCleanupHandlerAfterDrainingConnections(
`collect mongo connection pool metrics (${label})`,
() => {
clearInterval(intervalHandle)
// collect one more time.
collectOnce()
}
)
}
module.exports = {
db,
ObjectId,
@ -122,4 +155,5 @@ module.exports = {
getCollectionInternal,
dropTestDatabase,
waitForDb,
collectStatsForDb,
}