Merge pull request #13055 from overleaf/jpa-monitor-sockets-everywhere

[metrics] collect HTTP socket stats for all the services

GitOrigin-RevId: 52872f4ca46d8cf351f7f4b4df90f9d6b05010b3
This commit is contained in:
Jakob Ackermann 2023-05-22 11:36:51 +01:00 committed by Copybot
parent 7432904d0a
commit 5638f06b3a
15 changed files with 43 additions and 12 deletions

View file

@ -25,7 +25,13 @@ const SEEN_HOSTS_HTTPS = new Set()
const FREE_SEEN_HOSTS_HTTP = new Set() const FREE_SEEN_HOSTS_HTTP = new Set()
const FREE_SEEN_HOSTS_HTTPS = new Set() const FREE_SEEN_HOSTS_HTTPS = new Set()
function collectConnectionsCount(sockets, seenHosts, status, https) { function collectConnectionsCount(
sockets,
seenHosts,
status,
https,
emitLegacyMetric
) {
const Metrics = require('./index') const Metrics = require('./index')
Object.keys(sockets).forEach(host => seenHosts.add(host)) Object.keys(sockets).forEach(host => seenHosts.add(host))
seenHosts.forEach(host => { seenHosts.forEach(host => {
@ -40,7 +46,7 @@ function collectConnectionsCount(sockets, seenHosts, status, https) {
method: https, method: https,
status, status,
}) })
if (status === 'open') { if (status === 'open' && emitLegacyMetric) {
// Emit legacy metric to keep old time series intact. // Emit legacy metric to keep old time series intact.
Metrics.gauge( Metrics.gauge(
`${status}_connections.${https}.${hostname}`, `${status}_connections.${https}.${hostname}`,
@ -51,29 +57,43 @@ function collectConnectionsCount(sockets, seenHosts, status, https) {
} }
module.exports = OpenSocketsMonitor = { module.exports = OpenSocketsMonitor = {
monitor(logger) { monitor(emitLegacyMetric) {
const interval = setInterval( const interval = setInterval(
() => OpenSocketsMonitor.gaugeOpenSockets(), () => OpenSocketsMonitor.gaugeOpenSockets(emitLegacyMetric),
5 * seconds 5 * seconds
) )
const Metrics = require('./index') const Metrics = require('./index')
return Metrics.registerDestructor(() => clearInterval(interval)) return Metrics.registerDestructor(() => clearInterval(interval))
}, },
gaugeOpenSockets() { gaugeOpenSockets(emitLegacyMetric) {
collectConnectionsCount(SOCKETS_HTTP, SEEN_HOSTS_HTTP, 'open', 'http') collectConnectionsCount(
collectConnectionsCount(SOCKETS_HTTPS, SEEN_HOSTS_HTTPS, 'open', 'https') SOCKETS_HTTP,
SEEN_HOSTS_HTTP,
'open',
'http',
emitLegacyMetric
)
collectConnectionsCount(
SOCKETS_HTTPS,
SEEN_HOSTS_HTTPS,
'open',
'https',
emitLegacyMetric
)
collectConnectionsCount( collectConnectionsCount(
FREE_SOCKETS_HTTP, FREE_SOCKETS_HTTP,
FREE_SEEN_HOSTS_HTTP, FREE_SEEN_HOSTS_HTTP,
'free', 'free',
'http' 'http',
false
) )
collectConnectionsCount( collectConnectionsCount(
FREE_SOCKETS_HTTPS, FREE_SOCKETS_HTTPS,
FREE_SEEN_HOSTS_HTTPS, FREE_SEEN_HOSTS_HTTPS,
'free', 'free',
'https' 'https',
false
) )
}, },
} }

View file

@ -189,7 +189,7 @@ describe('Metrics module', function () {
}) })
describe('gaugeOpenSockets()', function () { describe('gaugeOpenSockets()', function () {
beforeEach(function runGaugeOpenSockets() { beforeEach(function runGaugeOpenSockets() {
Metrics.open_sockets.gaugeOpenSockets() Metrics.open_sockets.gaugeOpenSockets(true)
}) })
describe('without pending connections', function () { describe('without pending connections', function () {

View file

@ -11,6 +11,7 @@ const __dirname = fileURLToPath(new URL('.', import.meta.url))
metrics.initialize('chat') metrics.initialize('chat')
logger.initialize('chat') logger.initialize('chat')
metrics.open_sockets.monitor()
export async function createServer() { export async function createServer() {
const app = express() const app = express()

View file

@ -16,7 +16,7 @@ const Errors = require('./app/js/Errors')
const Path = require('path') const Path = require('path')
Metrics.open_sockets.monitor(logger) Metrics.open_sockets.monitor(true)
Metrics.memory.monitor(logger) Metrics.memory.monitor(logger)
const ProjectPersistenceManager = require('./app/js/ProjectPersistenceManager') const ProjectPersistenceManager = require('./app/js/ProjectPersistenceManager')

View file

@ -8,6 +8,7 @@ import * as Errors from './Errors.js'
Metrics.initialize('contacts') Metrics.initialize('contacts')
logger.initialize('contacts') logger.initialize('contacts')
Metrics.event_loop?.monitor(logger) Metrics.event_loop?.monitor(logger)
Metrics.open_sockets.monitor()
export const app = express() export const app = express()
app.use(Metrics.http.monitor(logger)) app.use(Metrics.http.monitor(logger))

View file

@ -23,6 +23,7 @@ logger.initialize('docstore')
if (Metrics.event_loop != null) { if (Metrics.event_loop != null) {
Metrics.event_loop.monitor(logger) Metrics.event_loop.monitor(logger)
} }
Metrics.open_sockets.monitor()
const app = express() const app = express()

View file

@ -23,6 +23,7 @@ const async = require('async')
const bodyParser = require('body-parser') const bodyParser = require('body-parser')
Metrics.event_loop.monitor(logger, 100) Metrics.event_loop.monitor(logger, 100)
Metrics.open_sockets.monitor()
const app = express() const app = express()
app.use(bodyParser.json({ limit: Settings.maxJsonRequestSize })) app.use(bodyParser.json({ limit: Settings.maxJsonRequestSize }))

View file

@ -22,7 +22,7 @@ if (settings.sentry && settings.sentry.dsn) {
logger.initializeErrorReporting(settings.sentry.dsn) logger.initializeErrorReporting(settings.sentry.dsn)
} }
Metrics.open_sockets.monitor(logger) Metrics.open_sockets.monitor(true)
Metrics.memory.monitor(logger) Metrics.memory.monitor(logger)
if (Metrics.event_loop) { if (Metrics.event_loop) {
Metrics.event_loop.monitor(logger) Metrics.event_loop.monitor(logger)

View file

@ -26,6 +26,7 @@ const app = express()
module.exports = app module.exports = app
logger.initialize('history-v1') logger.initialize('history-v1')
Metrics.open_sockets.monitor()
Metrics.injectMetricsRoute(app) Metrics.injectMetricsRoute(app)
app.use(Metrics.http.monitor(logger)) app.use(Metrics.http.monitor(logger))

View file

@ -18,6 +18,7 @@ const { mongoClient } = require('./app/js/mongodb')
const controller = require('./app/js/NotificationsController') const controller = require('./app/js/NotificationsController')
metrics.memory.monitor(logger) metrics.memory.monitor(logger)
metrics.open_sockets.monitor()
const HealthCheckController = require('./app/js/HealthCheckController') const HealthCheckController = require('./app/js/HealthCheckController')

View file

@ -16,6 +16,7 @@ if (Settings.sentry.dsn) {
Metrics.initialize('project-history') Metrics.initialize('project-history')
Metrics.event_loop.monitor(logger) Metrics.event_loop.monitor(logger)
Metrics.memory.monitor(logger) Metrics.memory.monitor(logger)
Metrics.open_sockets.monitor()
// log updates as truncated strings // log updates as truncated strings
function truncateFn(updates) { function truncateFn(updates) {

View file

@ -6,6 +6,7 @@ const async = require('async')
const logger = require('@overleaf/logger') const logger = require('@overleaf/logger')
logger.initialize('real-time') logger.initialize('real-time')
Metrics.event_loop.monitor(logger) Metrics.event_loop.monitor(logger)
Metrics.open_sockets.monitor()
const express = require('express') const express = require('express')
const session = require('express-session') const session = require('express-session')

View file

@ -12,6 +12,7 @@ if (Settings.sentry?.dsn != null) {
logger.initializeErrorReporting(Settings.sentry.dsn) logger.initializeErrorReporting(Settings.sentry.dsn)
} }
metrics.memory.monitor(logger) metrics.memory.monitor(logger)
metrics.open_sockets.monitor()
export const app = express() export const app = express()

View file

@ -41,6 +41,7 @@ TrackChangesLogger.addSerializers({
const Path = require('path') const Path = require('path')
Metrics.memory.monitor(logger) Metrics.memory.monitor(logger)
Metrics.open_sockets.monitor()
const childProcess = require('child_process') const childProcess = require('child_process')

View file

@ -34,6 +34,7 @@ http.globalAgent.maxSockets = Settings.limits.httpGlobalAgentMaxSockets
https.globalAgent.maxSockets = Settings.limits.httpsGlobalAgentMaxSockets https.globalAgent.maxSockets = Settings.limits.httpsGlobalAgentMaxSockets
metrics.memory.monitor(logger) metrics.memory.monitor(logger)
metrics.open_sockets.monitor()
const Server = require('./app/src/infrastructure/Server') const Server = require('./app/src/infrastructure/Server')
const QueueWorkers = require('./app/src/infrastructure/QueueWorkers') const QueueWorkers = require('./app/src/infrastructure/QueueWorkers')