Files
bodyshop/server/rr/rr-logger.js

56 lines
1.7 KiB
JavaScript

/**
* @file rr-logger.js
* @description Structured logger for Reynolds & Reynolds (Rome) integration.
* Mirrors PBS/Fortellis log shape for consistent log parsing.
*/
const util = require("util");
const dayjs = require("dayjs");
/**
* @typedef {Object} LogContext
* @property {string} [jobid]
* @property {string} [action]
* @property {string} [stage]
* @property {string} [endpoint]
* @property {Object} [meta]
*/
/**
* Emit a structured log event to console, Socket.IO, or upstream logger.
* @param {Socket|null} socket - Optional socket for WsLogger passthrough
* @param {"info"|"debug"|"warn"|"error"} level
* @param {string} message - Primary log message
* @param {LogContext|any} [context]
*/
function RRLogger(socket, level, message, context = {}) {
const logEvent = {
source: "RR",
level,
timestamp: dayjs().toISOString(),
message,
...context
};
// Console log (stdout/stderr)
const serialized = `[RR] ${logEvent.timestamp} [${level.toUpperCase()}] ${message}`;
if (level === "error" || level === "warn") {
console.error(serialized, context ? util.inspect(context, { depth: 4, colors: false }) : "");
} else {
console.log(serialized, context ? util.inspect(context, { depth: 4, colors: false }) : "");
}
// Optional: forward to WsLogger (if your socket is configured that way)
try {
if (socket && typeof socket.emit === "function") {
socket.emit("rr-log-event", logEvent);
} else if (global.WsLogger && typeof global.WsLogger.createLogEvent === "function") {
global.WsLogger.createLogEvent(socket, level.toUpperCase(), message, context.jobid, context);
}
} catch (e) {
console.error("[RRLogger] forwarding error", e.message);
}
}
module.exports = RRLogger;