diff --git a/prom.md b/prom.md index e5c3b39..51ba2e8 100644 --- a/prom.md +++ b/prom.md @@ -3,7 +3,7 @@ The goal of this version is to offer a few basic metrics for initial testing. The set of supported metrics can be extended. -The current implementation is +The current implementation is partly [unconventional](https://prometheus.io/docs/instrumenting/writing_exporters) in that it creates new metrics each time but does not register a custom collector. Reasons are that the exporter should @@ -17,18 +17,13 @@ of `multiparty-meeting` but connected as an interactive client. ## Configuration -| `.env` | description | -|--------|-------| -| `DEBUG` | e.g. `*WARN*,*ERROR*,*:prom` for debugging | -| `PROM_DEIDENTIFY` | if set, deidentify IP addresses | -| `PROM_NUMERIC` | if set, show numerical IP addresses | -| `PROM_PORT` | if set, enable exporter on this port | -| `PROM_QUIET` | if set, include fewer labels | +See `prometheus` in `server/config/config.example.js` for options and +applicable defaults. If `multiparty-meeting` was installed with [`mm-absible`](https://github.com/misi/mm-ansible) -it may be necessary to open the `iptables` firewall that was established -with `ferm` for incoming TCP traffic on `PROM_PORT`. +it may be necessary to open the `iptables` firewall for incoming TCP traffic +on the allocated port (see `/etc/ferm/ferm.conf`). ## Metrics diff --git a/server/config/config.example.js b/server/config/config.example.js index 12bf938..6ff279a 100644 --- a/server/config/config.example.js +++ b/server/config/config.example.js @@ -342,4 +342,13 @@ module.exports = maxIncomingBitrate : 1500000 } } + // Prometheus exporter + /* + prometheus: { + deidentify: false, // deidentify IP addresses + numeric: false, // show numeric IP addresses + port: 8889, // allocated port + quiet: false // include fewer labels + } + */ }; diff --git a/server/lib/promExporter.js b/server/lib/promExporter.js index af277eb..e54f241 100644 --- a/server/lib/promExporter.js +++ b/server/lib/promExporter.js @@ -52,33 +52,6 @@ set_value = function(key, m, labels, v) { } } -addr = async function(ip, port) { - if ('PROM_DEIDENTIFY' in process.env) { - let a = ip.split('.') - for (let i = 0; i < a.length - 2; i++) { - a[i] = 'xx'; - } - return `${a.join('.')}:${port}`; - } - else if ('PROM_NUMERIC' in process.env) { - return `${ip}:${port}`; - } - else { - try { - let a = await resolver.reverse(ip); - ip = a[0]; - } - catch (err) { - logger.error(`reverse DNS query failed: ${ip} ${err.code}`); - } - return `${ip}:${port}`; - } -} - -quiet = function(s) { - return 'PROM_QUIET' in process.env ? '' : s; -} - collect = async function(registry, rooms, peers) { metrics = function(subsystem) { @@ -191,46 +164,64 @@ collect = async function(registry, rooms, peers) { } } -module.exports = async function(rooms, peers) { - try { - logger.debug(`PROM_DEIDENTIFY=${process.env.PROM_DEIDENTIFY}`); - logger.debug(`PROM_NUMERIC=${process.env.PROM_NUMERIC}`); - logger.debug(`PROM_PORT=${process.env.PROM_PORT}`); - logger.debug(`PROM_QUIET=${process.env.PROM_QUIET}`); - let s_port = process.env.PROM_PORT; - if (!s_port) { - logger.info('exporter disabled'); +module.exports = async function(rooms, peers, config) { + + addr = async function(ip, port) { + if (config.deidentify) { + let a = ip.split('.') + for (let i = 0; i < a.length - 2; i++) { + a[i] = 'xx'; + } + return `${a.join('.')}:${port}`; + } + else if (config.numeric) { + return `${ip}:${port}`; } else { - let n_port = Number(s_port); - if (Number.isNaN(n_port)) { - throw new TypeError(`PROM_PORT has illegal value: ${s_port}`); + try { + let a = await resolver.reverse(ip); + ip = a[0]; } - - mediasoup.observer.on('newworker', worker => { - logger.debug(`observing newworker ${worker.pid} #${workers.size}`); - workers.set(worker.pid, worker); - worker.observer.on('close', () => { - logger.debug(`observing close worker ${worker.pid} #${workers.size - 1}`); - workers.delete(worker.pid); - }); - }); - - let app = express(); - app.get('/', async (req, res) => { - logger.debug(`GET ${req.originalUrl}`); - let registry = new prom.Registry(); - await collect(registry, rooms, peers); - res.set('Content-Type', registry.contentType); - let data = registry.metrics(); - res.end(data); - }); - let server = app.listen(n_port, () => { - address = server.address(); - logger.info(`listening ${address.address}:${address.port}`); - }); + catch (err) { + logger.error(`reverse DNS query failed: ${ip} ${err.code}`); + } + return `${ip}:${port}`; } } + + quiet = function(s) { + return config.quiet ? '' : s; + } + + try { + logger.debug(`config.deidentify=${config.deidentify}`); + logger.debug(`config.numeric=${config.numeric}`); + logger.debug(`config.port=${config.port}`); + logger.debug(`config.quiet=${config.quiet}`); + + mediasoup.observer.on('newworker', worker => { + logger.debug(`observing newworker ${worker.pid} #${workers.size}`); + workers.set(worker.pid, worker); + worker.observer.on('close', () => { + logger.debug(`observing close worker ${worker.pid} #${workers.size - 1}`); + workers.delete(worker.pid); + }); + }); + + let app = express(); + app.get('/', async (req, res) => { + logger.debug(`GET ${req.originalUrl}`); + let registry = new prom.Registry(); + await collect(registry, rooms, peers); + res.set('Content-Type', registry.contentType); + let data = registry.metrics(); + res.end(data); + }); + let server = app.listen(config.port || 8889, () => { + address = server.address(); + logger.info(`listening ${address.address}:${address.port}`); + }); + } catch (err) { logger.error(err); } diff --git a/server/server.js b/server/server.js index 90e299a..82aa9ab 100755 --- a/server/server.js +++ b/server/server.js @@ -134,7 +134,9 @@ async function run() await interactiveServer(rooms, peers); // start Prometheus exporter - await promExporter(rooms, peers); + if (config.prometheus) { + await promExporter(rooms, peers, config.prometheus); + } if (typeof(config.auth) === 'undefined') {