Separat status och mottagningsräknare för varje kanal.
Senaste råmeddelande, fel och ignoreringsorsaker. Pausa visning, rensa och kopiera logg. Uppdateras utan att störa inställningsfält eller tidtagning.
This commit is contained in:
50
src/decoder_diagnostics.js
Normal file
50
src/decoder_diagnostics.js
Normal file
@@ -0,0 +1,50 @@
|
||||
export const DIAGNOSTIC_ROLES = ["main", "split", "pit_entry", "pit_exit"];
|
||||
export function createDecoderDiagnostics(now = Date.now) {
|
||||
const channels = new Map();
|
||||
function channel(role) {
|
||||
const key = DIAGNOSTIC_ROLES.includes(role) ? role : "main";
|
||||
if (!channels.has(key)) channels.set(key, { role: key, status: "disconnected", url: "", connectedAt: null, lastReceivedAt: null, frames: 0, messages: 0, passings: 0, handled: 0, ignored: 0, invalid: 0, parseErrors: 0, lastFrame: "", log: [] });
|
||||
return channels.get(key);
|
||||
}
|
||||
function log(entry, reason, sample = "") {
|
||||
entry.log.push({ at: now(), reason, sample: String(sample).slice(0, 512) });
|
||||
if (entry.log.length > 50) entry.log.splice(0, entry.log.length - 50);
|
||||
}
|
||||
return {
|
||||
socket(role, status, url = "") {
|
||||
const entry = channel(role);
|
||||
entry.status = status;
|
||||
if (url) entry.url = String(url);
|
||||
if (status === "connected") entry.connectedAt = now();
|
||||
log(entry, status);
|
||||
},
|
||||
frame(role, data) {
|
||||
const entry = channel(role);
|
||||
entry.frames++;
|
||||
entry.lastReceivedAt = now();
|
||||
entry.lastFrame = String(data).slice(0, 512);
|
||||
},
|
||||
parseError(role) {
|
||||
const entry = channel(role);
|
||||
entry.parseErrors++;
|
||||
log(entry, "invalid_json", entry.lastFrame);
|
||||
},
|
||||
message(role, msg, reason, outcome = "ignored") {
|
||||
const entry = channel(role);
|
||||
entry.messages++;
|
||||
if (String(msg?.msg || msg?.type || "").toUpperCase() === "PASSING") entry.passings++;
|
||||
if (["handled", "ignored", "invalid"].includes(outcome)) entry[outcome]++;
|
||||
let sample = "";
|
||||
try { sample = JSON.stringify({ type: msg?.msg || msg?.type, transponder: msg?.transponder ?? msg?.tran_code, rtc_time: msg?.rtc_time }); } catch {}
|
||||
log(entry, reason, sample);
|
||||
},
|
||||
snapshot() { return DIAGNOSTIC_ROLES.map(role => { const entry = channel(role); return { ...entry, log: entry.log.map(item => ({ ...item })) }; }); },
|
||||
clear(role) {
|
||||
const entry = channel(role);
|
||||
for (const key of ["frames", "messages", "passings", "handled", "ignored", "invalid", "parseErrors"]) entry[key] = 0;
|
||||
entry.lastFrame = "";
|
||||
entry.log = [];
|
||||
},
|
||||
};
|
||||
}
|
||||
export const decoderDiagnostics = createDecoderDiagnostics();
|
||||
Reference in New Issue
Block a user