UNPKG

@dsheiko/splitlog

Version:

A minimalistic logger transport that forwards debug logs over UDP and lets you visualize different log channels in separate terminal windows with a simple CLI tool. Perfect for managing noisy logs in local or distributed development.

91 lines (76 loc) 1.98 kB
import dgram from "node:dgram"; import fs from "node:fs"; const CHANNEL_FILE = "/tmp/splitlog_channel"; const idleTimeout = 1000; // ms of idle time before cleanup let socket = null; let cleanupTimer = null; let port = null; function closeSocket() { socket && typeof socket.close === "function" && socket.close(); } process.on( "exit", () => { closeSocket(); }); process.on( "SIGINT", () => { closeSocket(); process.exit(); }); process.on( "SIGTERM", () => { closeSocket(); process.exit(); }); function createSocket() { if (!socket || socket._handle === null) { socket = dgram.createSocket("udp4"); } } function scheduleCleanup() { if (cleanupTimer) { clearTimeout(cleanupTimer); } cleanupTimer = setTimeout(() => { if (socket) { socket.close(); socket = null; } }, idleTimeout); } function discoverOpenPort() { try { return parseInt(fs.readFileSync(CHANNEL_FILE, "utf8"), 10); } catch (err) { return 0; } } /** * Creates a wrapped logger that sends messages via both debug and UDP. * @param {Function} logger - A `debug` logger instance. * @param {Object} [options] * @param {string} [options.host="127.0.0.1"] * @param {number} [options.port=41234] */ export default function splitlog( logger, options = {} ) { port = port || options.port || discoverOpenPort(); const host = options.host || "127.0.0.1", channel = logger.namespace; return function (...args) { // Original debug output logger(...args); // Ensure socket is open createSocket(); const message = JSON.stringify({ channel, options, timestamp: new Date().toISOString(), payload: args .map((a) => (typeof a === "string" ? a : JSON.stringify(a))) .join(" "), }); socket.send(Buffer.from(message), port, host, (err) => { if (err) { console.error(`[splitlog] UDP error: ${err.message}`); } scheduleCleanup(); }); }; }