Public
Edited
Aug 11, 2024
Importers
Insert cell
Insert cell
Insert cell
Insert cell
serviceStatusDisplay({
hostName: configuration.host,
accountName: configuration.account,
repositoryName: configuration.repository,
width: 900,
height: 200,
limit: configuration.limit
})
Insert cell
function serviceStatusDisplay({
hostName,
accountName,
repositoryName,
...options
} = {}) {
console.log("serviceStatusDisplay", hostName, accountName, repositoryName);
let interval = options.interval;
let panel = document.createElement("div");
let titleElement = document.createElement("div");
let gaugeElement = document.createElement("div");
let timeseriesElement = document.createElement("div");
let width = options.width || 800;
let height = options.height || 200;
let titleWidth = 50;
let gaugeOptions = Object.assign(
{ width: 200, height: height },
options.gauge || {}
);
let timeseriesOptions = Object.assign(
{
width: width - (titleWidth + gaugeOptions.width),
height: Math.floor(height * 0.75),
account: accountName,
repository: repositoryName
},
options.timeseries || {}
);

panel.appendChild(titleElement);
panel.appendChild(gaugeElement);
panel.appendChild(timeseriesElement);
function acceptSQS(sqs) {
console.log("acceptSQS", sqs);
function acceptSQH(sqh) {
console.log("acceptSQH", sqh);
function acceptSS(status) {
let { averageElapsedTime, sampleElapsedTime } =
queryElapsedTimeStatistics(sqs, sqh, 100);
status.sampleElapsedTime = sampleElapsedTime;
status.averageElapsedTime = averageElapsedTime;
console.log("status continued", status);
let gauge = makeGaugeInstance(status, gaugeOptions);
gaugeElement.innerHTML = "";
gaugeElement.appendChild(gauge);
titleElement.innerHTML = `version: ${status.VersionTimestamp} ...<br />host: <a href='https://${hostName}/admin/status.html' target='_blank'>${hostName}</a>`;
}
let timeseries = makeTimeseriesInstance(sqs, sqh, timeseriesOptions);
timeseriesElement.innerHTML = "";
timeseriesElement.appendChild(timeseries);
serverStatus(acceptSS, hostName);
}
systemQueryHistory(
acceptSQH,
hostName,
accountName,
repositoryName,
options.limit
);
}
systemQueryStatus(acceptSQS, hostName, accountName, repositoryName, {});

panel.style.cssText = `
border: ${options.border || "none"};
display: grid;
grid-template-areas: 'title gauge timeseries';
grid-gap: 10px;
padding-bottom: 20px;
`;
panel.style.width = width + "px";
panel.style.height = height + "px";
titleElement.className = "title";
titleElement.style.cssText = `width: ${titleWidth}px; height: ${height}px;
grid-area: title;
border: none;
writing-mode: vertical-lr;
text-align: center;
font-size: 10pt;
`;
timeseriesElement.className = "timeseries";
timeseriesElement.style.cssText = `width: ${timeseriesOptions.width}px; height: ${height}px;
grid-area: timeseries;
border: none;
`;
gaugeElement.className = "gauge";
gaugeElement.style.cssText = `width: ${gaugeOptions.width}px; height: ${height}px;
grid-area: gauge;
border: none;
`;
return panel;
}
Insert cell
Insert cell
makeTimeseriesInstance = function (sqs, sqh, options = {}) {
let average = sqs[0].value;
let plot = Plot.dot(sqh, {
x: "timestamp",
y: "elapsed_time",
// stroke: "match_responses",
r: 0.5
}).plot({
x: {
tickRotate: 30,
tickFormat: Plot.formatIsoDate
//grid: true
//type: "utc"
},
y: { label: "time (ms)", type: "log", tickFormat: "," }, //, domain: [0, 1000], clamp: true },
marks: [
Plot.frame(),
Plot.ruleY([average], {
stroke: "red",
strokeDasharray: [2, 4],
title: "elapsed time average"
})
],
marginBottom: 60,
marginLeft: 50,
height: options.height || 200,
width: options.width || 600,
caption:
sqh && sqh[0]
? html`${options.account}/${options.repository} : ${Plot.formatIsoDate(
sqh[0].timestamp
)}--${Plot.formatIsoDate(sqh[sqh.length - 1].timestamp)}`
: html`${options.account}/${options.repository} : no results`
});
return plot;
}
Insert cell
makeGaugeInstance = function(status, options = {}) {
console.log("status for gauge", status);
let div = document.createElement('div');
let memused = status.MemTotal - status.MemAvailable;
let memcaches = status.MemAvailable - status.MemFree;
let memfree = status.MemFree;
let cpuused =
(100 * (status.CputimeTotal - status.CputimeFree)) / status.CputimeTotal;
let averageElapsedTime = status.averageElapsedTime;
let sampleElapsedTime = status.sampleElapsedTime;
let dataset = [
{
level: status.MemTotal * .75,
maximum: status.MemTotal,
samples: [memused, memcaches, memfree],
label: "memory",
colors: ["red", "yellow", "green"],
levelColor: "silver"
},
{
level: 10,
maximum: 20,
samples: [status.Loadavg, 20 - status.Loadavg],
label: "load average",
colors: ["red", "green"],
levelColor: "silver"
},
{
level: 90,
maximum: 100,
samples: [cpuused, 100 - cpuused],
label: "cpu %",
colors: ["red", "green"],
levelColor: "silver"
},
{
// depict relation between latest sample average and history average
level: sampleElapsedTime,
maximum: Math.max(sampleElapsedTime, averageElapsedTime),
samples: [averageElapsedTime],
label: "query load",
levelColor: sampleElapsedTime > averageElapsedTime ? "red" : "green"
}
];
div.style.cssText = "width: 100px; height: 400px";
console.log("dataset", dataset);
makeGauge(
div,
dataset,
Object.assign(
{
width: 200,
height: 400,
ringWidth: 10,
startAngle: -Math.PI,
endAngle: Math.PI / 2
},
options
)
);
return div;
}
Insert cell
systemQueryHistory = function (
continuation,
hostName,
accountName,
repositoryName,
limit
) {
console.log("serviceQueryHistory", hostName, accountName, repositoryName);
ResourceAccess.getResource(
resourceHistoryURL(hostName, accountName, repositoryName, limit),
{
Accept: "application/json"
},
function (series) {
for (let value of series) {
value.timestamp = new Date(value.timestamp);
}
continuation(series);
}
);
}
Insert cell
function systemQueryStatus(
continuation,
hostName,
accountName,
repositoryName,
options = {}
) {
console.log("serviceQueryStatus", hostName, accountName, repositoryName);
function acceptResult(solutions) {
console.log("sqs solutions", solutions);
let statisticsArray = [];
let statisticsSolution = solutions[0];
console.log("statisticsSolution", statisticsSolution);
statisticsArray.push({
name: "elapsed_time_average",
value: statisticsSolution.elapsed_time / statisticsSolution.query_count
});
for (let key of Object.keys(statisticsSolution)) {
let entry = {};
entry.name = key;
entry.value = statisticsSolution[key];
statisticsArray.push(entry);
}
continuation(statisticsArray);
}

function getAndAccept() {
ResourceAccess.getResource(
resourceStatisticsURL(hostName, accountName, repositoryName),
{
Accept: "application/json"
},
acceptResult
);
}
let interval = options.interval;
if (interval) {
setInterval(getAndAccept, interval);
} else {
getAndAccept();
}
}
Insert cell
serverStatus = function (continuation, hostname) {
let url = `https://${hostname}/system/status`;
ResourceAccess.getResource(
url,
{ Accept: "application/json" },
function (result) {
continuation(result[0]);
}
);
}
Insert cell
function queryElapsedTimeStatistics(sqs, sqh, sampleCount) {
let result = { sampleElapsedTime: 0, averageElapsedTime: 0 };
function serverQueryStatisticValue(name) {
for (let entry of sqs) {
if (name == entry.name) {
return entry.value;
}
}
}
let historyIndex = sqh.length - 1;
let sampleCounted = 0;
let sampleTotal = 0;
let sampleAverageElapsedTime = 0;
for (; sampleCount > 0 && historyIndex >= 0; historyIndex--) {
let historyValue = sqh[historyIndex]["elapsed_time"];
if (historyValue) {
sampleTotal += historyValue;
sampleCount--;
sampleCounted++;
}
}
if (sampleCounted > 0) {
sampleAverageElapsedTime = sampleTotal / sampleCounted;
}
result.averageElapsedTime =
serverQueryStatisticValue("elapsed_time_average") || 0;
result.sampleElapsedTime = sampleAverageElapsedTime;
return result;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
asyncGetResource = async function(url, options) {
return new Promise(function(accept, reject) {
ResourceAccess.getResource(
url,
options,
function(result) {
accept(result);
},
reject
);
});
}
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more