blob: d37c24d6af6f65763e0031362ac77a2be5b76abb [file] [log] [blame]
/*
* Copyright (C) 2929, Unicode, Inc.
* For terms of use, see http://www.unicode.org/terms_of_use.html
*/
const express = require('express');
const process = require('process');
const server = express();
const client = require('prom-client');
const bent = require('bent');
const getJson = bent('json');
const config = require('./config.json');
const {register} = client; // global registry
const items = {
responses: new client.Counter({
name: 'surveytool_exporter_responses',
help: 'Number of pages served by this exporter'
}),
oks: new client.Counter({
name: 'surveytool_exporter_oks',
help: 'Number of OK fetches',
labelNames: ['instance']
}),
fails: new client.Counter({
name: 'surveytool_exporter_fails',
help: 'Number of failed fetches',
labelNames: ['instance']
}),
ok: new client.Gauge({
name: 'surveytool_ok',
help: '1 if the surveytool is ok, otherwise 0',
labelNames: ['instance']
}),
isSetup: new client.Gauge({
name: 'surveytool_setup',
help: '1 if the surveytool is setup, otherwise 0',
labelNames: ['instance']
}),
isBusted: new client.Gauge({
name: 'surveytool_busted',
help: '1 if the surveytool is busted, otherwise 0',
labelNames: ['instance'/*, 'err'*/]
}),
fetchTime: new client.Gauge({
name: 'surveytool_fetchTime',
help: 'time of successful fetch',
labelNames: ['instance']
}),
fetchErr: new client.Gauge({
name: 'surveytool_fetchErr',
help: 'error code on failed fetch, or 200',
labelNames: ['instance'/*, 'err'*/]
}),
pages: new client.Gauge({
name: 'surveytool_pages',
help: 'page count',
labelNames: ['instance']
}),
users: new client.Gauge({
name: 'surveytool_users',
help: 'user count',
labelNames: ['instance']
}),
stamp: new client.Gauge({
name: 'surveytool_stamp',
help: 'survey running stamp',
labelNames: ['instance' /*,
'phase', 'sysprocs', 'environment', 'currev', 'newVersion'*/]
}),
memtotal: new client.Gauge({
name: 'surveytool_memtotal',
help: 'total memory in process',
labelNames: ['instance']
}),
memfree: new client.Gauge({
name: 'surveytool_memfree',
help: 'total free memory',
labelNames: ['instance']
}),
dbused: new client.Gauge({
name: 'surveytool_dbused',
help: 'db queries used',
labelNames: ['instance']
}),
sysload: new client.Gauge({
name: 'surveytool_sysload',
help: 'system load, if available',
labelNames: ['instance']
}),
};
async function update(e) {
const [instance, url] = e;
try {
const res = await getJson(url);
items.oks.inc({instance});
items.fetchErr.set({ instance }, 200);
items.fetchTime.set({ instance }, new Date().getTime()/1000);
items.ok.set({instance}, Number(res.SurveyOK));
items.isSetup.set({instance}, Number(res.isSetup));
if(res.status) {
const{phase, memtotal, sysprocs, isBusted, isUnofficial, lockOut,
users, uptime, memfree, environment, pages, specialHeader, currev,
dbopen, surveyRunningStamp, guests, dbused,sysload, isSetup, newVersion} = res.status;
items.pages.set({instance}, Number(pages));
items.users.set({instance}, Number(users));
items.memtotal.set({instance}, Number(memtotal));
items.memfree.set({instance}, Number(memfree));
items.dbused.set({instance}, Number(dbused));
items.sysload.set({instance}, Number(sysload));
items.stamp.set({instance /*,
phase, sysprocs, environment, currev, newVersion*/},
surveyRunningStamp);
if(isBusted) {
items.isBusted.set({instance/*, err: isBusted*/}, Number(1));
} else {
items.isBusted.set({instance/*, err: (res.err || '')*/}, Number(res.isBusted));
}
} else {
items.isBusted.set({instance/*, err: (res.err || '')*/}, Number(res.isBusted));
}
} catch(ex) {
items.fails.inc({instance});
items.fetchErr.set({ instance /*, err: ex.toString()*/ }, 999);
}
}
async function updateAll() {
return Promise.all(Object.entries(config.instances)
.map(e => update(e)));
}
server.get('/metrics', async (req, res) => {
items.responses.inc();
res.contentType(register.contentType);
await updateAll();
res.end(register.metrics());
});
const port = process.env.PORT || config.port || 3000;
server.listen(port, () => {
console.log('ST exporter listening on port ' + port);
});