diff --git a/dashboard/build.js b/dashboard/build.js
index 04608ad..cc46d4d 100644
--- a/dashboard/build.js
+++ b/dashboard/build.js
@@ -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,
};
diff --git a/dashboard/socket.js b/dashboard/socket.js
index 3a5b64f..8716b45 100644
--- a/dashboard/socket.js
+++ b/dashboard/socket.js
@@ -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;
diff --git a/entities/webservice.js b/entities/webservice.js
index 8753ac5..a805761 100644
--- a/entities/webservice.js
+++ b/entities/webservice.js
@@ -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: [
diff --git a/gui/dashboard/app.svelte b/gui/dashboard/app.svelte
index 6725b2a..68bc3aa 100644
--- a/gui/dashboard/app.svelte
+++ b/gui/dashboard/app.svelte
@@ -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);
+ }
@@ -71,8 +112,14 @@
{#if !loading}
-
-
+
+ {#if !clusterKeys?.length}
+
+
+ {:else}
+
+
+ {/if}
{:else}
loading
{/if}
diff --git a/index.js b/index.js
index b9f4c0c..dfaa8d0 100644
--- a/index.js
+++ b/index.js
@@ -85,17 +85,11 @@ module.exports = {
},
settings: {
- emailSender: {
- type: 'string',
- label: 'notification sender',
- description: 'Sender of notifications about service statuses. Format: Name ',
- default: '',
- },
- emailRecipient: {
- type: 'array',
- label: 'notification recipients',
- description: 'Recipients of notifications about service statuses. Format: Name ',
- 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 ',
+ default: '',
+ },
+ emailRecipient: {
+ type: 'array',
+ label: 'notification recipients',
+ description: 'Recipients of notifications about service statuses. Format: Name ',
+ 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 = {
-
+