112 lines
3.2 KiB
JavaScript
112 lines
3.2 KiB
JavaScript
/**
|
|
* MongoDB TCP probe (+ optional serverStatus HTTP sidecar).
|
|
* Enable: PEARDATA_MONGODB=1
|
|
* URL: PEARDATA_MONGODB_URL=127.0.0.1:27017
|
|
*/
|
|
import net from 'net'
|
|
import { CollectorPlugin } from './plugin.js'
|
|
import { registerChart } from '../../../shared/metrics.js'
|
|
|
|
export function isMongodbEnabled() {
|
|
const v = process.env.PEARDATA_MONGODB
|
|
return v === '1' || v === 'on' || v === 'true'
|
|
}
|
|
|
|
function endpoint() {
|
|
const raw = process.env.PEARDATA_MONGODB_URL || '127.0.0.1:27017'
|
|
const u = raw.replace(/^mongodb:\/\//, '')
|
|
const [host, port] = u.split(':')
|
|
return { host: host || '127.0.0.1', port: Number(port) || 27017 }
|
|
}
|
|
|
|
function probeTcp(host, port, timeoutMs = 1500) {
|
|
return new Promise((resolve) => {
|
|
const start = Date.now()
|
|
const sock = net.connect({ host, port }, () => {
|
|
const ms = Date.now() - start
|
|
sock.end()
|
|
resolve({ up: 1, latency_ms: ms })
|
|
})
|
|
sock.setTimeout(timeoutMs)
|
|
sock.on('timeout', () => {
|
|
sock.destroy()
|
|
resolve({ up: 0, latency_ms: timeoutMs })
|
|
})
|
|
sock.on('error', () => resolve({ up: 0, latency_ms: timeoutMs }))
|
|
})
|
|
}
|
|
|
|
export class MongodbCollector extends CollectorPlugin {
|
|
constructor() {
|
|
super({ name: 'mongodb' })
|
|
}
|
|
|
|
isEnabled() {
|
|
return isMongodbEnabled()
|
|
}
|
|
|
|
async collect() {
|
|
const ts = Date.now()
|
|
const { host, port } = endpoint()
|
|
const probe = await probeTcp(host, port)
|
|
registerChart({
|
|
id: 'mongodb.up',
|
|
name: 'mongodb.up',
|
|
context: 'mongodb.up',
|
|
title: 'MongoDB up',
|
|
units: 'boolean',
|
|
family: 'mongodb',
|
|
chartType: 'line',
|
|
priority: 8700,
|
|
plugin: 'mongodb',
|
|
dimensions: [
|
|
{ id: 'up', name: 'up', algorithm: 'absolute' },
|
|
{ id: 'latency_ms', name: 'latency_ms', algorithm: 'absolute' },
|
|
],
|
|
})
|
|
/** @type {Array<{ chart: string, context: string, ts: number, values: object }>} */
|
|
const batch = [
|
|
{ chart: 'mongodb.up', context: 'mongodb.up', ts, values: probe },
|
|
]
|
|
const statsUrl = process.env.PEARDATA_MONGODB_STATS_URL
|
|
if (statsUrl) {
|
|
try {
|
|
const res = await fetch(statsUrl, { signal: AbortSignal.timeout(2000) })
|
|
const text = await res.text()
|
|
/** @type {Record<string, number>} */
|
|
const vals = {}
|
|
for (const line of text.split('\n')) {
|
|
const [k, v] = line.split(/[=\s]+/)
|
|
if (k && v != null && Number.isFinite(Number(v))) vals[k] = Number(v)
|
|
}
|
|
registerChart({
|
|
id: 'mongodb.stats',
|
|
name: 'mongodb.stats',
|
|
context: 'mongodb.stats',
|
|
title: 'MongoDB stats',
|
|
units: 'value',
|
|
family: 'mongodb',
|
|
chartType: 'line',
|
|
priority: 8710,
|
|
plugin: 'mongodb',
|
|
dimensions: Object.keys(vals).map((id) => ({
|
|
id,
|
|
name: id,
|
|
algorithm: 'absolute',
|
|
})),
|
|
})
|
|
batch.push({ chart: 'mongodb.stats', context: 'mongodb.stats', ts, values: vals })
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
return batch
|
|
}
|
|
}
|
|
|
|
let singleton = null
|
|
export function getMongodbCollector() {
|
|
if (!singleton) singleton = new MongodbCollector()
|
|
return singleton
|
|
}
|