import { Writable } from "node:stream"; import pino, { type Logger } from "pino"; import { db } from "../db/db.controller.js"; import { logs } from "../db/schema/logs.schema.js"; import { emitToRoom } from "../socket.io/roomEmitter.socket.js"; import { tryCatch } from "../utils/trycatch.utils.js"; //import build from "pino-abstract-transport"; export const logLevel = process.env.LOG_LEVEL || "info"; const pinoLogLevels: Record = { 10: "trace", 20: "debug", 30: "info", 40: "warn", 50: "error", 60: "fatal", }; // ✅ Custom DB writable stream const dbStream = new Writable({ objectMode: true, async write(chunk, _enc, callback) { try { const obj = JSON.parse(chunk.toString()); const levelName = pinoLogLevels[obj.level] || "unknown"; const res = await tryCatch( db .insert(logs) .values({ level: levelName, module: obj?.module?.toLowerCase(), subModule: obj?.subModule?.toLowerCase(), hostname: obj?.hostname?.toLowerCase(), message: obj.msg, stack: obj?.stack, }) .returning(), ); if (res.error) { console.error(res.error); } if (obj.room) { emitToRoom(obj.room, res.data ? res.data[0] : obj); } emitToRoom("logs", res.data ? res.data[0] : obj); callback(); } catch (err) { console.error("DB log insert error:", err); callback(); } }, }); const rootLogger: Logger = pino( { level: logLevel, redact: { paths: ["email", "password"], remove: true }, }, pino.multistream([ { level: logLevel, stream: pino.transport({ target: "pino-pretty", options: { colorize: true, singleLine: true, }, }), }, { level: logLevel, stream: dbStream, }, ]), ); /** * * * example data to put in as a reference * rooms logs | labels | etc */ export const createLogger = (bindings: Record): Logger => { return rootLogger.child(bindings); };