'use strict'; // Per-session JSON-lines logger shared across all variants. Writes to // rfid-daemon/diagnostics/run--.log so we can // compare variants apples-to-apples after a session. const fs = require('fs'); const path = require('path'); const pad2 = n => n.toString().padStart(2, '0'); function tsForFilename(d = new Date()) { return `${d.getFullYear()}${pad2(d.getMonth()+1)}${pad2(d.getDate())}-${pad2(d.getHours())}${pad2(d.getMinutes())}${pad2(d.getSeconds())}`; } function createLogger(variant, diagDir) { fs.mkdirSync(diagDir, { recursive: true }); const logPath = path.join(diagDir, `run-${variant}-${tsForFilename()}.log`); const stream = fs.createWriteStream(logPath, { flags: 'a' }); const counters = { write_ok: 0, write_failed: 0, read_ok: 0, read_failed: 0, inventory_ok: 0, inventory_failed: 0, timeout: 0, keepalive_sent: 0, preflight_run: 0, recover_attempted: 0, lockups: 0, }; let lastSuccessAt = null; let inLockupSince = null; const startedAt = Date.now(); function writeLine(obj) { stream.write(JSON.stringify(obj) + '\n'); } function event(name, data = {}) { const obj = { ts: new Date().toISOString(), ev: name, ...data }; writeLine(obj); if (name in counters) counters[name]++; const isSuccess = (name === 'write_ok' || name === 'read_ok' || name === 'inventory_ok'); if (isSuccess) { lastSuccessAt = Date.now(); if (inLockupSince) { writeLine({ ts: obj.ts, ev: 'recovered', afterMs: Date.now() - inLockupSince }); inLockupSince = null; } } if (name === 'timeout' && !inLockupSince) { inLockupSince = Date.now(); counters.lockups++; writeLine({ ts: obj.ts, ev: 'lockup_detected', sinceLastSuccessMs: lastSuccessAt ? Date.now() - lastSuccessAt : null }); } } function summary() { return { variant, runtimeMs: Date.now() - startedAt, counters: { ...counters }, lastSuccessAgoMs: lastSuccessAt ? Date.now() - lastSuccessAt : null, currentlyLocked: !!inLockupSince, }; } function close() { writeLine({ ts: new Date().toISOString(), ev: 'end', ...summary() }); stream.end(); } return { event, summary, close, logPath }; } module.exports = { createLogger };