UNPKG

@sp8d/diagnostics

Version:

sp8d-diagnostics: Advanced diagnostics, debugging, and observability for concurrent and distributed TypeScript/JavaScript systems. Detect race conditions, deadlocks, and monitor runtime.

107 lines (106 loc) 3.01 kB
// src/sp8d-diagnostics.ts function createChannelDiagnostics(channel, options = {}) { const intervalMs = options.intervalMs ?? 50; const slotSample = options.slotSample ?? "all"; let lastMsgCount = 0; let lastTime = Date.now(); let throughput = 0; let consumerLag = 0; let avgSlotAge = 0; let maxSlotAge = 0; let updateCb = options.onUpdate; let timer; const statsHistory = []; function getSlotState() { const testChannel = channel; if (!testChannel.slotStatus || !testChannel.slotClaimTimestamp) throw new Error("Channel internals not exposed"); const statusArr = testChannel.slotStatus[0]; const claimTS = testChannel.slotClaimTimestamp[0]; const result = []; const N = statusArr.length; if (slotSample === "all" || slotSample >= N) { for (let i = 0; i < N; i++) { result.push({ index: i, status: statusArr[i], ageMs: statusArr[i] === 1 || statusArr[i] === 2 ? Date.now() - claimTS[i] : 0 }); } } else { for (let s = 0; s < slotSample; s++) { const i = Math.floor(Math.random() * N); result.push({ index: i, status: statusArr[i], ageMs: statusArr[i] === 1 || statusArr[i] === 2 ? Date.now() - claimTS[i] : 0 }); } } return result; } function updateStats() { const stats = channel.stats(); const currentTime = Date.now(); throughput = (stats.used - lastMsgCount) * 1e3 / (currentTime - lastTime); lastMsgCount = stats.used; lastTime = currentTime; const slotState = getSlotState(); const ages = slotState.filter((s) => s.status !== 0).map((s) => s.ageMs).sort((a, b) => a - b); avgSlotAge = ages.length > 0 ? ages.reduce((a, b) => a + b) / ages.length : 0; maxSlotAge = ages.length > 0 ? ages[ages.length - 1] : 0; consumerLag = maxSlotAge; const enhancedStats = { ...stats, throughput: Math.max(0, throughput), consumerLag, avgSlotAge, maxSlotAge, slotState // <-- include slotState for dashboard }; statsHistory.push(stats); if (updateCb) updateCb(enhancedStats); return enhancedStats; } function start() { timer = setInterval(updateStats, intervalMs); } function stop() { clearInterval(timer); } function onUpdate(cb) { updateCb = cb; } function getHistory() { return statsHistory.slice(); } updateStats(); return { get stats() { return updateStats(); }, getSlotState, getHistory, start, stop, onUpdate }; } function startDiagnosticsWorker(channel, options = {}) { const worker = new Worker( new URL("./sp8d-diagnostics-worker.js", import.meta.url), { type: "module" } ); const testChannel = channel; worker.postMessage({ buffer: testChannel.sab || testChannel.buffer, options }); return worker; } export { createChannelDiagnostics, startDiagnosticsWorker }; //# sourceMappingURL=sp8d-diagnostics.js.map