better metrics (dashboard and show no sessions in metrics page if nothing is running for active sessions donut graph)

This commit is contained in:
KingKDot
2026-06-05 23:02:22 -05:00
parent 91149853ce
commit 7f8e5ff333
2 changed files with 66 additions and 20 deletions
@@ -97,6 +97,19 @@ function formatWeekLabel(timestamp) {
}); });
} }
function compactRepeatedTickLabel(value, index, ticks) {
const labelFor = (tickValue) => {
const labels = this?.chart?.data?.labels || [];
return labels[Number(tickValue)] ?? this?.getLabelForValue?.(tickValue) ?? "";
};
const labels = (ticks || []).map((tick) => labelFor(tick.value));
const current = labels[index] || labelFor(value);
if (!current) return "";
const isRunStart = index === 0 || labels[index - 1] !== current;
const isRunEnd = index === labels.length - 1 || labels[index + 1] !== current;
return isRunStart || isRunEnd ? current : "";
}
function aggregateOnlineHistory(history, snapshot) { function aggregateOnlineHistory(history, snapshot) {
const now = Date.now(); const now = Date.now();
const weekAgo = now - 7 * 24 * 60 * 60 * 1000; const weekAgo = now - 7 * 24 * 60 * 60 * 1000;
@@ -227,7 +240,12 @@ function makeCharts() {
scales: { scales: {
x: { x: {
grid: { display: false }, grid: { display: false },
ticks: { color: palette.muted, maxRotation: 0, maxTicksLimit: 5 }, ticks: {
color: palette.muted,
maxRotation: 0,
maxTicksLimit: 5,
callback: compactRepeatedTickLabel,
},
}, },
y: { y: {
beginAtZero: true, beginAtZero: true,
+47 -19
View File
@@ -16,6 +16,9 @@ let latestByCountry = {};
const GEOJSON_URL = "/vendor/geo-countries/countries.geojson"; const GEOJSON_URL = "/vendor/geo-countries/countries.geojson";
const MAX_CHART_POINTS = 240; const MAX_CHART_POINTS = 240;
const METRICS_POLL_INTERVAL_MS = 5000; const METRICS_POLL_INTERVAL_MS = 5000;
const SESSION_LABELS = ["Console", "Remote Desktop", "Files", "Processes"];
const SESSION_COLORS = ["#34d399", "#c084fc", "#60a5fa", "#fb923c"];
const SESSION_EMPTY_COLOR = "rgba(100, 116, 139, 0.35)";
if (typeof Chart !== "undefined") { if (typeof Chart !== "undefined") {
Chart.defaults.color = "#cbd5e1"; Chart.defaults.color = "#cbd5e1";
@@ -76,6 +79,34 @@ function makeLineChart(canvas, datasets, options = {}) {
}); });
} }
function getSessionValues(sessions = {}) {
return [
Number(sessions.console) || 0,
Number(sessions.remoteDesktop) || 0,
Number(sessions.fileBrowser) || 0,
Number(sessions.process) || 0,
];
}
function updateSessionsChart(sessions = {}) {
if (!sessionsChart) return;
const values = getSessionValues(sessions);
const total = values.reduce((sum, value) => sum + value, 0);
const dataset = sessionsChart.data.datasets[0];
if (total > 0) {
sessionsChart.data.labels = SESSION_LABELS;
dataset.data = values;
dataset.backgroundColor = SESSION_COLORS;
sessionsChart.options.plugins.legend.display = true;
} else {
sessionsChart.data.labels = ["No active sessions"];
dataset.data = [1];
dataset.backgroundColor = [SESSION_EMPTY_COLOR];
sessionsChart.options.plugins.legend.display = false;
}
sessionsChart.update("none");
}
function initCharts() { function initCharts() {
const clientsCtx = document.getElementById("clients-chart"); const clientsCtx = document.getElementById("clients-chart");
const commandsCtx = document.getElementById("commands-chart"); const commandsCtx = document.getElementById("commands-chart");
@@ -403,10 +434,10 @@ function initCharts() {
sessionsChart = sessionsCtx ? new Chart(sessionsCtx, { sessionsChart = sessionsCtx ? new Chart(sessionsCtx, {
type: "doughnut", type: "doughnut",
data: { data: {
labels: ["Console", "Remote Desktop", "Files", "Processes"], labels: ["No active sessions"],
datasets: [{ datasets: [{
data: [0, 0, 0, 0], data: [1],
backgroundColor: ["#34d399", "#c084fc", "#60a5fa", "#fb923c"], backgroundColor: [SESSION_EMPTY_COLOR],
borderColor: "#0f172a", borderColor: "#0f172a",
borderWidth: 2, borderWidth: 2,
}], }],
@@ -417,8 +448,17 @@ function initCharts() {
animation: false, animation: false,
cutout: "64%", cutout: "64%",
plugins: { plugins: {
legend: { position: "right", labels: { boxWidth: 10, boxHeight: 10 } }, legend: { display: false, position: "right", labels: { boxWidth: 10, boxHeight: 10 } },
tooltip: chartTooltip(), tooltip: {
...chartTooltip(),
callbacks: {
label: (ctx) => {
if (ctx.chart.data.labels?.[ctx.dataIndex] === "No active sessions") return "No active sessions";
const value = Number(ctx.parsed) || 0;
return `${ctx.label}: ${value.toLocaleString()} session${value === 1 ? "" : "s"}`;
},
},
},
}, },
}, },
}) : null; }) : null;
@@ -533,11 +573,7 @@ function updateMetrics(data, debug) {
); );
animateCounter(document.getElementById("clients-total"), data.clients.total); animateCounter(document.getElementById("clients-total"), data.clients.total);
const totalSessions = const totalSessions = getSessionValues(data.sessions).reduce((sum, value) => sum + value, 0);
data.sessions.console +
data.sessions.remoteDesktop +
data.sessions.fileBrowser +
data.sessions.process;
animateCounter(document.getElementById("active-sessions"), totalSessions); animateCounter(document.getElementById("active-sessions"), totalSessions);
animateCounter( animateCounter(
@@ -657,15 +693,7 @@ function updateMetrics(data, debug) {
osList.innerHTML = '<div class="text-slate-500">No clients</div>'; osList.innerHTML = '<div class="text-slate-500">No clients</div>';
} }
if (sessionsChart) { updateSessionsChart(data.sessions);
sessionsChart.data.datasets[0].data = [
data.sessions.console || 0,
data.sessions.remoteDesktop || 0,
data.sessions.fileBrowser || 0,
data.sessions.process || 0,
];
sessionsChart.update("none");
}
if (osChart) { if (osChart) {
const osEntries = Object.entries(data.clients.byOS || {}) const osEntries = Object.entries(data.clients.byOS || {})