/*! meta-admin/modules/watchdog */
/*jslint
browser, long
*/
/*global
Blob, BroadcastChannel
*/
import Logger from "js-logger";
import ko from "knockout";
import objects from "meta-client/modules/objects";
import model from "meta-core/modules/model";
import protocol from "meta-core/modules/protocol";
import _ from "underscore";
import dates from "util-web/modules/dates";
import ext from "util-web/modules/ext";
import i18next from "util-web/modules/i18next";
import nav from "util-web/modules/nav";
import ui from "util-web/modules/ui";
import template from "./watchdog.html";
const LOG = Logger.get("meta-admin/watchdog");
/**
* watchdog component.
*
* @module meta-admin/modules/component/watchdog
*/
export default Object.freeze({
template,
viewModel: {
createViewModel: function ({viewmodel}) {
const getInfoJson = function (info) {
if (_.isEmpty(info) === false) {
if (0 === info.indexOf("{")) {
return JSON.parse(info);
}
return info;
}
};
const getVersion = function (info) {
if (_.isEmpty(info) === false) {
if (0 === info.indexOf("{")) { // New JSON info
return JSON.parse(info).rt.version;
}
if (info.includes(",")) { // Old string info
return info.substring(0, info.indexOf(","));
}
}
};
const notificationChannel = new BroadcastChannel("meta-admin");
const vm = {};
vm.viewmodel = viewmodel;
vm.activeServerUpdate = ko.observable();
vm.serverInfo = ko.observable();
vm.errorReply = ko.observable();
vm.isUpdating = ko.observable(false);
vm.updateFileKey = ko.observable();
vm.updateSchedule = ko.observable();
const updateScheduleSub = dates.insertDateTimes({fromDateObservable: vm.updateSchedule});
vm.activateServerInfo = function (status) {
vm.serverInfo(JSON.stringify(getInfoJson(status.info()), undefined, 4));
};
vm.activateUpdate = function (status) {
vm.activeServerUpdate(status);
};
vm.processUpdate = function (form) {
const status = vm.activeServerUpdate();
if (ui.validateForm(form) === false) {
return;
}
LOG.debug(`processUpdate, engineId=${status.engineId()}`);
vm.isUpdating(true);
return vm.viewmodel.client.writeObjectUpdate(protocol.writeObjectUpdateRequest({
channel: protocol.WATCHDOG_STATUS_CHANNEL,
meta: model.metaObject({
id: status.id,
typeId: vm.statusObjects.typeId,
value: {
update: model.watchdogStatusUpdate({
fileKey: vm.updateFileKey(),
schedule: vm.updateSchedule()
}),
updateStatus: null
}
})
})).then(function () {
vm.errorReply(undefined);
vm.activeServerUpdate(undefined);
vm.updateFileKey(undefined);
vm.updateSchedule(undefined);
ui.resetForm(form);
}, function (exc) {
vm.errorReply(JSON.stringify(exc, undefined, 4));
}).then(function () {
vm.isUpdating(false);
});
};
vm.clearUpdateStatus = function (status) {
return vm.viewmodel.client.writeObjectUpdate(protocol.writeObjectUpdateRequest({
channel: protocol.WATCHDOG_STATUS_CHANNEL,
meta: model.metaObject({
id: status.id,
typeId: vm.statusObjects.typeId,
value: {
updateStatus: null
}
})
})).then(function () {
vm.errorReply(undefined);
status.updateStatus(undefined);
}, function (exc) {
vm.errorReply(JSON.stringify(exc, undefined, 4));
});
};
vm.statusObjects = objects({
loadById: objects.loadByMetaId.bind(undefined, vm.viewmodel.client),
sort: ext.simpleSort.bind(undefined, "engineId"),
toVm: vm.viewmodel.toWatchdogStatusVm,
typeId: model.WATCHDOG_STATUS_TYPE_ID
});
const eventHandle = vm.viewmodel.client.registerOnEvent(vm.statusObjects);
vm.unhealthyServers = ko.pureComputed(function () {
return vm.statusObjects.objects().filter(function (statusVm) {
return statusVm.healthy() === false;
});
});
vm.alertServers = ko.pureComputed(function () {
return vm.statusObjects.objects().filter(function (statusVm) {
return statusVm.healthy() && (statusVm.hasAlerts() || statusVm.updateStatus());
});
});
vm.healthyServers = ko.pureComputed(function () {
return vm.statusObjects.objects().filter(function (statusVm) {
return statusVm.healthy() && statusVm.hasAlerts() === false && Boolean(statusVm.updateStatus()) === false;
});
});
vm.serverAlertNotification = ko.computed(function () {
const noOfUnhealthy = vm.unhealthyServers().length;
if (0 < noOfUnhealthy) {
ext.displayNotification({
options: {
body: i18next.t("watchdog_alarm_body", {count: noOfUnhealthy}),
tag: "watchdog"
},
title: i18next.t("watchdog_alarm")
});
}
});
notificationChannel.onmessage = function (message) {
const data = message.data;
switch (data.type) {
case "onclick":
LOG.debug(`notification clicked, tag=${data.tag}`);
break;
case "onclose":
LOG.debug(`notification closed, tag=${data.tag}`);
break;
}
};
vm.loadStatus = function () {
LOG.debug("loadStatus");
vm.statusObjects.clear();
return vm.statusObjects.processSearch(
vm.viewmodel.client.search(protocol.searchRequest({
cursor: vm.statusObjects.searchCursor(),
limit: 200,
query: vm.statusObjects.newSearchQuery()
}))
).then(function () {
const mapApi = vm.viewmodel.mapApiProvider();
if (mapApi) {
mapApi.objectMarkers(vm.statusObjects.objects());
}
}, function (exc) {
LOG.warn("loadStatus failed", exc);
});
};
vm.isExportActive = ko.observable(false);
vm.exportVersionByServer = ko.pureComputed(function () {
const vms = vm.statusObjects.objects();
const servers = {};
vms.forEach(function (statusVm) {
const version = getVersion(statusVm.info());
if (version) {
servers[statusVm.engineId()] = version;
}
});
return JSON.stringify(servers, undefined, 4);
});
vm.exportServersByVersion = ko.pureComputed(function () {
const vms = vm.statusObjects.objects();
const versions = {};
vms.forEach(function (statusVm) {
const version = getVersion(statusVm.info());
if (version) {
if (Boolean(versions[version]) === false) {
versions[version] = [statusVm.engineId()];
} else {
versions[version].push(statusVm.engineId());
}
}
});
return JSON.stringify(versions, undefined, 4);
});
vm.exportServerInfos = ko.pureComputed(function () {
const vms = vm.statusObjects.objects();
const infos = {};
vms.forEach(function (statusVm) {
infos[statusVm.engineId()] = getInfoJson(statusVm.info());
});
return JSON.stringify(infos, undefined, 4);
});
vm.activateExport = function () {
vm.isExportActive(true);
};
nav.register({
id: vm.viewmodel.COMPONENTS.WATCHDOG,
onUpdate: vm.loadStatus
});
vm.dispose = function () {
LOG.debug("dispose");
vm.viewmodel.client.unregisterOnEvent(eventHandle);
updateScheduleSub.dispose();
};
return Object.freeze(vm);
}
}
});