@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
JavaScript
// 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