mirror of
https://github.com/smartyellow/status.git
synced 2025-01-18 21:47:58 +00:00
Fork endpoint testing processes
Signed-off-by: Romein van Buren <romein@vburen.nl>
This commit is contained in:
parent
141d7009f6
commit
002df5cfb1
53
index.js
53
index.js
@ -1,8 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { makeId } = require('core/makeid');
|
||||
const { testService } = require('./lib/testservice');
|
||||
const { testServices } = require('./lib/testservices');
|
||||
const { fork } = require('child_process');
|
||||
const { processOutage } = require('./lib/processoutage');
|
||||
|
||||
const guiCluster = 'web service status';
|
||||
const icons = {
|
||||
@ -181,7 +180,29 @@ module.exports = {
|
||||
runAtBoot: true,
|
||||
active: true,
|
||||
interval: Number(settings.autotestInterval) * 60 * 1000,
|
||||
action: () => testServices({ server, settings, makeId }),
|
||||
action: async () => {
|
||||
const services = await server
|
||||
.storage
|
||||
.store('smartyellow/webservice')
|
||||
.find({ autotestEnabled: true })
|
||||
.toArray();
|
||||
|
||||
if (!services.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const runtime = fork(__dirname + '/lib/runtime.js');
|
||||
runtime.send({ command: 'testAll', services });
|
||||
|
||||
runtime.on('message', message => {
|
||||
if (message.error) {
|
||||
server.error(message.error);
|
||||
}
|
||||
else if (message.outage) {
|
||||
processOutage({ outage: message.outage, server, settings });
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -191,12 +212,24 @@ module.exports = {
|
||||
event: 'saveEntity',
|
||||
entity: [ 'smartyellow/webservice' ],
|
||||
purpose: 'Check whether services are up and send a notification if not.',
|
||||
handler: ({ item }) => testService({
|
||||
service: item,
|
||||
server,
|
||||
settings,
|
||||
makeId,
|
||||
}),
|
||||
handler: ({ item }) => {
|
||||
const runtime = fork(__dirname + '/lib/runtime.js');
|
||||
runtime.send({ command: 'testOne', service: item });
|
||||
runtime.on('message', message => {
|
||||
if (message.error) {
|
||||
server.error(message.error);
|
||||
}
|
||||
else if (message.outage) {
|
||||
processOutage({
|
||||
outage: {
|
||||
[item.id]: message.outage,
|
||||
},
|
||||
server,
|
||||
settings,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
|
@ -1,46 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
const { testEndpoints } = require('./testendpoints');
|
||||
const { roundDate } = require('./utils');
|
||||
const { makeId } = require('core/makeid');
|
||||
|
||||
async function testService({ service, server, settings, makeId }) {
|
||||
if (!service.autotestEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Autotest the service
|
||||
const result = await testEndpoints(service.autotest);
|
||||
const name = service.name.en;
|
||||
|
||||
// Insert check date
|
||||
async function processOutage({ outage, server, settings }) {
|
||||
for (const [ id, testResult ] of Object.entries(outage)) {
|
||||
// Update check date
|
||||
await server.storage.store('smartyellow/webservice').update(
|
||||
{ id: service.id },
|
||||
{ id },
|
||||
{ $set: { lastChecked: new Date() } }
|
||||
);
|
||||
|
||||
// Get all heartbeats plus the last one
|
||||
// Get service entry
|
||||
const service = await server
|
||||
.storage
|
||||
.store('smartyellow/webservice')
|
||||
.findOne({ id });
|
||||
|
||||
// Get last heartbeat
|
||||
const heartbeat = await server
|
||||
.storage
|
||||
.store('smartyellow/webserviceheartbeat')
|
||||
.find({ webservice: service.id })
|
||||
.find({ webservice: id })
|
||||
.toArray();
|
||||
const lastBeat = heartbeat[heartbeat.length - 1];
|
||||
|
||||
// Get date
|
||||
const date = roundDate(new Date());
|
||||
|
||||
// Error
|
||||
if (result.error) {
|
||||
server.error('Error while checking status: ' + name);
|
||||
server.error(result);
|
||||
// Encountered an error while checking status
|
||||
if (testResult.error) {
|
||||
server.error('Error while checking status of ' + id);
|
||||
server.error(testResult);
|
||||
}
|
||||
|
||||
// Service down
|
||||
else if (!result.serviceUp) {
|
||||
server.warn('Service down: ' + name);
|
||||
server.warn(result);
|
||||
|
||||
// Service is down
|
||||
else if (!testResult.serviceUp) {
|
||||
// Don't perform automatic actions if already done
|
||||
if ((lastBeat && lastBeat.down == false) || !lastBeat) {
|
||||
// Insert heartbeat if last one is not valid anymore
|
||||
@ -48,9 +39,9 @@ async function testService({ service, server, settings, makeId }) {
|
||||
await server.storage.store('smartyellow/webserviceheartbeat').insert({
|
||||
id: makeId(6),
|
||||
down: true,
|
||||
webservice: service.id,
|
||||
testResult: result,
|
||||
date: date,
|
||||
webservice: id,
|
||||
testResult,
|
||||
date: new Date(),
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
@ -64,10 +55,10 @@ async function testService({ service, server, settings, makeId }) {
|
||||
await server.sendEmail({
|
||||
sender: settings.emailSender,
|
||||
to: settings.emailRecipient,
|
||||
subject: `[outage] ${name} is down`,
|
||||
subject: `[outage] ${service.name} is down`,
|
||||
body: `<p>Dear recipient,</p>
|
||||
<p>This is to inform you about web service outage.
|
||||
The service <em>${name}</em> does not meet the
|
||||
The service <em>${service.name}</em> does not meet the
|
||||
requirements for being considered as 'working'.</p>
|
||||
<p>Please always check this before taking action.</p>`,
|
||||
});
|
||||
@ -87,7 +78,7 @@ async function testService({ service, server, settings, makeId }) {
|
||||
.insert({
|
||||
id: makeId(6),
|
||||
name: {
|
||||
en: `[automatic] Outage for ${name}`,
|
||||
en: `[automatic] Outage for ${service.name}`,
|
||||
},
|
||||
state: 'concept',
|
||||
resolved: false,
|
||||
@ -96,7 +87,7 @@ async function testService({ service, server, settings, makeId }) {
|
||||
notes: [ {
|
||||
date: new Date(),
|
||||
userId: 'system',
|
||||
text: `Automatically created outage. Reason: ${JSON.stringify(result, null, 2)}`,
|
||||
text: `Automatically created outage. Reason: ${JSON.stringify(testResult, null, 2)}`,
|
||||
} ],
|
||||
});
|
||||
}
|
||||
@ -110,17 +101,16 @@ async function testService({ service, server, settings, makeId }) {
|
||||
|
||||
// Service up
|
||||
else {
|
||||
server.info('Service up: ' + name);
|
||||
|
||||
// Insert heartbeat if last one is not valid anymore
|
||||
// Don't perform automatic actions if already done
|
||||
if ((lastBeat && lastBeat.down == true) || !lastBeat) {
|
||||
// Insert heartbeat if last one is not valid anymore
|
||||
try {
|
||||
await server.storage.store('smartyellow/webserviceheartbeat').insert({
|
||||
id: makeId(6),
|
||||
down: false,
|
||||
webservice: service.id,
|
||||
date: date,
|
||||
testResult: result,
|
||||
webservice: id,
|
||||
testResult,
|
||||
date: new Date(),
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
@ -130,9 +120,6 @@ async function testService({ service, server, settings, makeId }) {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
server.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { testService };
|
||||
module.exports = { processOutage };
|
46
lib/runtime.js
Normal file
46
lib/runtime.js
Normal file
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
const { testEndpoints } = require('./testendpoints');
|
||||
|
||||
process.on('message', async message => {
|
||||
switch (message.command) {
|
||||
case 'testAll':
|
||||
if (!message.services) {
|
||||
process.send({ error: 'services is not defined' });
|
||||
}
|
||||
else {
|
||||
const ids = [];
|
||||
const promises = [];
|
||||
for (const service of message.services) {
|
||||
if (service.autotestEnabled) {
|
||||
ids.push(service.id);
|
||||
promises.push(testEndpoints(service.autotest));
|
||||
}
|
||||
}
|
||||
|
||||
const result = await Promise.all(promises);
|
||||
const mapped = {};
|
||||
for (const [ i, id ] of ids.entries()) {
|
||||
mapped[id] = result[i];
|
||||
}
|
||||
|
||||
process.send({ outage: mapped });
|
||||
}
|
||||
break;
|
||||
|
||||
case 'testOne':
|
||||
if (!message.service) {
|
||||
process.send({ error: 'service is not defined' });
|
||||
}
|
||||
else {
|
||||
const { service } = message;
|
||||
const result = await testEndpoints(service.autotest);
|
||||
process.send({ outage: result });
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error('Unknown command:', message.command);
|
||||
break;
|
||||
}
|
||||
});
|
@ -1,19 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const { testService } = require('./testservice');
|
||||
|
||||
async function testServices({ server, settings, makeId }) {
|
||||
const services = await server
|
||||
.storage
|
||||
.store('smartyellow/webservice')
|
||||
.find({ autotestEnabled: true })
|
||||
.toArray();
|
||||
|
||||
services.forEach(async service => {
|
||||
if (service.autotestEnabled) {
|
||||
testService({ service, server, settings, makeId });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { testServices };
|
11
lib/utils.js
11
lib/utils.js
@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// Round minutes up to 10 and remove seconds
|
||||
// e.g. 15:34:51 -> 15:30:00
|
||||
function roundDate(d) {
|
||||
d.setMinutes(Math.round(d.getMinutes() / 10) * 10);
|
||||
d.setSeconds(0, 0);
|
||||
return d;
|
||||
}
|
||||
|
||||
module.exports = { roundDate };
|
Loading…
Reference in New Issue
Block a user