/* * SysDeck - Benchmark Panel (v0.0.11) * Author: Jeremy Anderson (https://dcos.net) * * System benchmarking via sysbench. Attributes the cockpit-benchmark * plugin (MIT, ealier) whose standalone plugin lives at * https://github.com/ealier/cockpit-benchmark. * * This panel invokes sysbench via cockpit.spawn as a separate process — * no cockpit-benchmark or sysbench code is bundled. sysbench is GPL-2.0 * licensed; the suite (MIT) and sysbench remain independent programs. * * Shows available tests, run controls, and results history. * * v0.1.4 SECURITY: raw sysbench output (result.raw — stdout+stderr, * includes echoed test names) and spawn error messages are untrusted * tool output; both previously landed in innerHTML unescaped (0.3.0 * audit). Now escaped; the numeric fields are formatted to strings * before escaping too. */ function escapeHtml(s) { return String(s == null ? '' : s) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } export async function mount(panel, { bridge, EventBus }) { panel.innerHTML = renderSkeleton(); let tests = []; try { tests = await bridge.benchmark.listTests(); } catch (err) { panel.innerHTML = renderError(err); return; } panel.innerHTML = `

System Benchmark

sysbench + cockpit-benchmark integration

MIT · ealier

Available Tests

${tests.map((t) => ``).join('') || ''}
TestToolActions
${escapeHtml(t.name)} ${escapeHtml(t.tool)}
No benchmarks available. Install sysbench.

Quick Benchmarks

No results yet. Click a benchmark to run.
`; const resultsDiv = panel.querySelector('#benchmark-results'); const runBench = async (name, resultFn) => { resultsDiv.innerHTML = `Running ${escapeHtml(name)} benchmark...`; try { const result = await resultFn(); EventBus.emit('benchmark.run', { test: name, result }); resultsDiv.innerHTML = `

${escapeHtml(name)} Results

Events/sec: ${escapeHtml(result.events_per_sec ?? 'N/A')}

Avg latency: ${result.latency_ms != null ? escapeHtml(result.latency_ms.toFixed(2)) + ' ms' : 'N/A'}

Raw output
${escapeHtml(result.raw || 'N/A')}
`; } catch (err) { resultsDiv.innerHTML = `Error: ${escapeHtml(err.message || err)}`; } }; panel.querySelector('#btn-run-cpu')?.addEventListener('click', () => runBench('CPU', () => bridge.benchmark.runCpu())); panel.querySelector('#btn-run-memory')?.addEventListener('click', () => runBench('Memory', () => bridge.benchmark.runMemory())); panel.querySelector('#btn-run-io')?.addEventListener('click', () => runBench('File I/O', () => bridge.benchmark.runIo())); panel.querySelectorAll('[data-test]').forEach((btn) => { btn.addEventListener('click', async () => { const test = btn.dataset.test; btn.disabled = true; try { const result = await bridge.benchmark.runTest(test); EventBus.emit('benchmark.run', { test }); resultsDiv.innerHTML = `

${escapeHtml(test)} completed

${escapeHtml(result)}
`; } catch (err) { resultsDiv.innerHTML = `${escapeHtml(err.message || err)}`; } btn.disabled = false; }); }); panel.querySelector('#btn-benchmark-refresh')?.addEventListener('click', () => { mount(panel, { bridge, EventBus }); }); } function renderSkeleton() { return `
`; } function renderError(err) { return `

Benchmark tools unavailable

${escapeHtml(err.message || err)}. Install sysbench for system benchmarking.

cockpit-benchmark (MIT) by ealier — https://github.com/ealier/cockpit-benchmark

sysbench (GPL-2.0) — https://github.com/akopytov/sysbench

`; }