78 lines
2.1 KiB
JavaScript
78 lines
2.1 KiB
JavaScript
const logger = require("../utils/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)))
|
|
};
|
|
};
|
|
|
|
/**
|
|
* 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 normLevel = lvl.toLowerCase();
|
|
const msg = typeof message === "string" ? message : (message?.toString?.() ?? JSON.stringify(message));
|
|
|
|
const payload = {
|
|
timestamp: ts,
|
|
level: lvl,
|
|
message: msg,
|
|
meta: safeMeta(meta)
|
|
};
|
|
|
|
// Central logger (Winston + CloudWatch + S3)
|
|
try {
|
|
// user = "RR", record = null, meta = payload.meta
|
|
logger.log(`[RR] ${msg}`, normLevel, "RR", null, payload.meta);
|
|
} catch {
|
|
// Fallback console
|
|
console.log(`[RR] ${new Date(ts).toISOString()} | ${lvl} | ${msg}`, payload.meta);
|
|
}
|
|
|
|
// Socket
|
|
try {
|
|
socket?.emit?.("rr-log-event", payload);
|
|
} catch {
|
|
// ignore socket failures
|
|
}
|
|
|
|
return payload;
|
|
};
|
|
|
|
module.exports = CreateRRLogEvent;
|