feature/IO-3357-Reynolds-and-Reynolds-DMS-API-Integration - Expanded Logs / Formatting change
This commit is contained in:
@@ -1,44 +1,75 @@
|
||||
// File: server/rr/rr-logger-event.js
|
||||
// Fortellis-style log helper for RR flows.
|
||||
// Usage: CreateRRLogEvent(socket, "DEBUG"|"INFO"|"WARN"|"ERROR", message, details?)
|
||||
const logger = require("../utils/logger");
|
||||
|
||||
const RRLogger = require("../rr/rr-logger");
|
||||
/**
|
||||
* Convert an Error object to a plain object for serialization.
|
||||
* @param err
|
||||
* @returns {{[p: string]: unknown, name: *, message: *, stack: *}|null}
|
||||
*/
|
||||
const toPlainError = (err) => {
|
||||
if (!err) return null;
|
||||
return {
|
||||
name: err.name,
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
...Object.fromEntries(Object.entries(err).filter(([k]) => !["stack"].includes(k)))
|
||||
};
|
||||
};
|
||||
|
||||
// Normalize level to upper + provide console + socket event with coherent payload
|
||||
function CreateRRLogEvent(socket, level = "DEBUG", message = "", details = {}) {
|
||||
const lvl = String(level || "DEBUG").toUpperCase();
|
||||
/**
|
||||
* Safely serialize meta information for logging.
|
||||
* @param meta
|
||||
* @returns {{note: string}|any|{[p: string]: *, name: *, message: *, stack: *}|null}
|
||||
*/
|
||||
const safeMeta = (meta) => {
|
||||
try {
|
||||
if (meta instanceof Error) return toPlainError(meta);
|
||||
if (meta && typeof meta === "object") {
|
||||
// JSON-safe clone w/ BigInt -> string
|
||||
return JSON.parse(JSON.stringify(meta, (_k, v) => (typeof v === "bigint" ? v.toString() : v)));
|
||||
}
|
||||
return meta ?? null;
|
||||
} catch {
|
||||
return { note: "meta not serializable" };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create and emit a Reynolds log event.
|
||||
* @param socket
|
||||
* @param level
|
||||
* @param message
|
||||
* @param meta
|
||||
* @returns {{timestamp: number, level: string, message: string|string, meta: {note: string}|*|{[p: string]: *, name: *, message: *, stack: *}|null}}
|
||||
* @constructor
|
||||
*/
|
||||
const CreateRRLogEvent = (socket, level = "INFO", message = "", meta = null) => {
|
||||
const ts = Date.now();
|
||||
const lvl = String(level || "INFO").toUpperCase();
|
||||
const msg = typeof message === "string" ? message : (message?.toString?.() ?? JSON.stringify(message));
|
||||
|
||||
// Console (uses existing RRLogger, which also emits "RR:LOG" to sockets for live tail)
|
||||
const payload = {
|
||||
timestamp: ts,
|
||||
level: lvl,
|
||||
message: msg,
|
||||
meta: safeMeta(meta)
|
||||
};
|
||||
|
||||
// Console
|
||||
try {
|
||||
const log = RRLogger(socket);
|
||||
const fn = lvl === "ERROR" ? "error" : lvl === "WARN" ? "warn" : lvl === "INFO" ? "info" : "debug";
|
||||
log(fn, message, { ts, ...safeJson(details) });
|
||||
const fn = logger?.logger?.[lvl.toLowerCase()] ?? logger?.logger?.info ?? console.log;
|
||||
fn(`[RR] ${new Date(ts).toISOString()} | ${lvl} | ${msg}`, payload.meta);
|
||||
} catch {
|
||||
/* ignore console/log failures */
|
||||
// ignore console failures
|
||||
}
|
||||
|
||||
// Structured RR event for FE debug panel (parity with Fortellis' CreateFortellisLogEvent)
|
||||
// socket.emit("fortellis-log-event", { level, message, txnDetails });
|
||||
// Socket
|
||||
try {
|
||||
socket?.emit?.("rr-log-event", {
|
||||
level: lvl,
|
||||
message,
|
||||
ts,
|
||||
txnDetails: details
|
||||
});
|
||||
socket?.emit?.("rr-log-event", payload);
|
||||
} catch {
|
||||
/* ignore socket emit failures */
|
||||
// ignore socket failures
|
||||
}
|
||||
}
|
||||
|
||||
// Best-effort ensure details are JSON-safe (avoid circular / BigInt)
|
||||
function safeJson(obj) {
|
||||
try {
|
||||
return JSON.parse(JSON.stringify(obj ?? {}));
|
||||
} catch {
|
||||
return { _unsafe: true };
|
||||
}
|
||||
}
|
||||
return payload;
|
||||
};
|
||||
|
||||
module.exports = CreateRRLogEvent;
|
||||
|
||||
Reference in New Issue
Block a user