mirror of
https://github.com/smartyellow/status.git
synced 2025-01-18 21:47:58 +00:00
Basic cluster functionality
Signed-off-by: Romein van Buren <romein@vburen.nl>
This commit is contained in:
parent
aace2dd2de
commit
b626f23792
@ -9,7 +9,7 @@ const { default: resolve } = require('@rollup/plugin-node-resolve');
|
||||
const svelte = require('rollup-plugin-svelte');
|
||||
const { terser } = require('rollup-plugin-terser');
|
||||
|
||||
async function build(server) {
|
||||
async function build({ server, settings }) {
|
||||
const serverDomain = server.settings.domain || 'localhost';
|
||||
const serverPort = server.settings.port || 80;
|
||||
const serverBase = `${serverDomain}:${serverPort}`;
|
||||
@ -49,6 +49,7 @@ async function build(server) {
|
||||
preventAssignment: false,
|
||||
values: {
|
||||
'__SERVER__': serverBase,
|
||||
'__CLUSTERS__': JSON.stringify(settings.clusters),
|
||||
},
|
||||
}),
|
||||
],
|
||||
@ -62,6 +63,7 @@ async function build(server) {
|
||||
});
|
||||
|
||||
return {
|
||||
map: output[0].map.toUrl(),
|
||||
code: output[0].code,
|
||||
css: cssOutput.css,
|
||||
};
|
||||
|
@ -10,10 +10,15 @@ async function createDashboardSocket(server) {
|
||||
route: '/statusdashboard/socket',
|
||||
onOpen: async ws => {
|
||||
function sendTime() {
|
||||
ws.send(JSON.stringify({
|
||||
cmd: 'time',
|
||||
time: new Date().getTime(),
|
||||
}));
|
||||
try {
|
||||
ws.send(JSON.stringify({
|
||||
cmd: 'time',
|
||||
time: new Date().getTime(),
|
||||
}));
|
||||
}
|
||||
catch {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sendTime();
|
||||
@ -36,13 +41,19 @@ async function createDashboardSocket(server) {
|
||||
mappedServices[s.id] = {
|
||||
name: s.name,
|
||||
lastBeat: lastBeat || {},
|
||||
cluster: s.cluster,
|
||||
};
|
||||
}
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
cmd: 'data',
|
||||
data: mappedServices,
|
||||
}));
|
||||
try {
|
||||
ws.send(JSON.stringify({
|
||||
cmd: 'data',
|
||||
data: mappedServices,
|
||||
}));
|
||||
}
|
||||
catch {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sendStatuses();
|
||||
@ -51,7 +62,6 @@ async function createDashboardSocket(server) {
|
||||
onUpgrade: async () => ({ id: makeId(10) }),
|
||||
onMessage: async (ws, msg) => {
|
||||
msg = JSON.parse(decoder.decode(msg));
|
||||
console.log('msg', msg);
|
||||
|
||||
if (!msg || !msg.command) {
|
||||
return;
|
||||
|
@ -24,6 +24,7 @@ module.exports = {
|
||||
'name',
|
||||
'state',
|
||||
'public',
|
||||
'cluster',
|
||||
'tags',
|
||||
'channels',
|
||||
],
|
||||
@ -95,6 +96,18 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
|
||||
cluster: {
|
||||
label: 'cluster',
|
||||
fields: [
|
||||
{ key: 'cluster',
|
||||
editor: 'select',
|
||||
placeholder: 'select a cluster for this service...',
|
||||
visible: !!(settings.clusters && Object.keys(settings.clusters).length),
|
||||
options: settings.clusters,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
tags: {
|
||||
label: 'tags',
|
||||
fields: [
|
||||
|
@ -10,7 +10,13 @@
|
||||
let servicesUp = {};
|
||||
let servicesDown = {};
|
||||
let servicesUnknown = {};
|
||||
let servicesInCluster = {};
|
||||
let servicesInClusterUnknown = {};
|
||||
const clusters = JSON.parse('__CLUSTERS__');
|
||||
const clusterKeys = clusters ? Object.keys(clusters) : false;
|
||||
let currentClusterIndex = -1;
|
||||
let loading = true;
|
||||
let lock = false;
|
||||
|
||||
onMount(() => {
|
||||
const ws = new WebSocket('ws://__SERVER__/statusdashboard/socket');
|
||||
@ -27,6 +33,8 @@
|
||||
break;
|
||||
|
||||
case 'data':
|
||||
while (lock) {}
|
||||
|
||||
services = data.data;
|
||||
const ids = Object.keys(services);
|
||||
|
||||
@ -60,6 +68,39 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$: if (clusterKeys?.length && !loading) {
|
||||
function nextCluster() {
|
||||
lock = true;
|
||||
currentClusterIndex++;
|
||||
|
||||
if (currentClusterIndex >= clusterKeys.length) {
|
||||
currentClusterIndex = 0;
|
||||
}
|
||||
|
||||
const inClusterTemp = {};
|
||||
const inClusterTempUnknown = {};
|
||||
const currentClusterKey = clusterKeys[currentClusterIndex];
|
||||
|
||||
for (const [ id, s ] of Object.entries(services)) {
|
||||
if (s.cluster === currentClusterKey) {
|
||||
if (!s.lastBeat || !s.lastBeat.date) {
|
||||
inClusterTempUnknown[id] = s;
|
||||
}
|
||||
else {
|
||||
inClusterTemp[id] = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
servicesInCluster = inClusterTemp;
|
||||
servicesInClusterUnknown = inClusterTempUnknown;
|
||||
lock = false;
|
||||
}
|
||||
|
||||
nextCluster();
|
||||
setInterval(() => nextCluster, 10_000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Settings />
|
||||
@ -71,8 +112,14 @@
|
||||
|
||||
{#if !loading}
|
||||
<Tiles services={servicesDown} color="red" value="down" />
|
||||
<Tiles services={servicesUp} color="green" value="up" />
|
||||
<Tiles services={servicesUnknown} color="grey" value="no data" />
|
||||
|
||||
{#if !clusterKeys?.length}
|
||||
<Tiles services={servicesUp} color="green" value="up" />
|
||||
<Tiles services={servicesUnknown} color="grey" value="no data" />
|
||||
{:else}
|
||||
<Tiles services={servicesInCluster} color="green" value="up" />
|
||||
<Tiles services={servicesInClusterUnknown} color="grey" value="no data" />
|
||||
{/if}
|
||||
{:else}
|
||||
loading
|
||||
{/if}
|
||||
|
45
index.js
45
index.js
@ -85,17 +85,11 @@ module.exports = {
|
||||
},
|
||||
|
||||
settings: {
|
||||
emailSender: {
|
||||
type: 'string',
|
||||
label: 'notification sender',
|
||||
description: 'Sender of notifications about service statuses. Format: Name <email@example.com>',
|
||||
default: '',
|
||||
},
|
||||
emailRecipient: {
|
||||
type: 'array',
|
||||
label: 'notification recipients',
|
||||
description: 'Recipients of notifications about service statuses. Format: Name <email@example.com>',
|
||||
default: [],
|
||||
clusters: {
|
||||
type: 'keys',
|
||||
label: 'clusters',
|
||||
description: 'Clusters can be used to catogorise web services into groups.',
|
||||
default: {},
|
||||
},
|
||||
serviceTags: {
|
||||
type: 'keys',
|
||||
@ -109,10 +103,22 @@ module.exports = {
|
||||
description: 'Tags that can be assigned to outage messages to categorise them.',
|
||||
default: {},
|
||||
},
|
||||
emailSender: {
|
||||
type: 'string',
|
||||
label: 'notification sender',
|
||||
description: 'Sender of notifications about service statuses. Format: Name <email@example.com>',
|
||||
default: '',
|
||||
},
|
||||
emailRecipient: {
|
||||
type: 'array',
|
||||
label: 'notification recipients',
|
||||
description: 'Recipients of notifications about service statuses. Format: Name <email@example.com>',
|
||||
default: [],
|
||||
},
|
||||
draftOutageEntries: {
|
||||
type: 'boolean',
|
||||
label: 'draft outage entries',
|
||||
description: 'Automatically draft outage entry when a service is down.',
|
||||
description: 'Automatically draft an outage entry when a service is down?',
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
@ -200,10 +206,8 @@ module.exports = {
|
||||
{ id: 'startDashboardSocket',
|
||||
event: 'boot',
|
||||
order: 100,
|
||||
purpose: 'Start the websocket for the dashboard after server has booted',
|
||||
handler: async ({ server }) => {
|
||||
createDashboardSocket(server);
|
||||
},
|
||||
purpose: 'Start the websocket for the dashboard after boot',
|
||||
handler: () => createDashboardSocket(server),
|
||||
},
|
||||
|
||||
{ id: 'autotestOnSave',
|
||||
@ -232,7 +236,7 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
|
||||
routes: ({ server }) => [
|
||||
routes: ({ server, settings }) => [
|
||||
|
||||
// Get all services
|
||||
{ route: '/webservices',
|
||||
@ -533,7 +537,7 @@ module.exports = {
|
||||
handler: async (req, res) => {
|
||||
try {
|
||||
if (!renderedDashboard) {
|
||||
renderedDashboard = await buildDashboard(server);
|
||||
renderedDashboard = await buildDashboard({ server, settings });
|
||||
renderedDashboard.globalCss = await readFile(
|
||||
__dirname + '/gui/dashboard/app.css'
|
||||
);
|
||||
@ -550,7 +554,10 @@ module.exports = {
|
||||
<style>${renderedDashboard.css || ''}</style>
|
||||
</head>
|
||||
<body>
|
||||
<script>${renderedDashboard.code || ''}</script>
|
||||
<script>
|
||||
${renderedDashboard.code || ''}
|
||||
//# sourceMappingURL=${renderedDashboard.map || ''}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
|
Loading…
Reference in New Issue
Block a user