const { test } = require("tap"); const cluster = require("cluster"); const debug = require("debug")("log4js:pm2-test"); // PM2 runs everything as workers // - no master in the cluster (PM2 acts as master itself) // - we will simulate that here (avoid having to include PM2 as a dev dep) if (cluster.isMaster) { // create two worker forks // PASS IN NODE_APP_INSTANCE HERE const appEvents = {}; ["0", "1"].forEach(i => { cluster.fork({ NODE_APP_INSTANCE: i }); }); const messageHandler = (worker, msg) => { if (worker.type || worker.topic) { msg = worker; } if (msg.type === "testing") { debug( `Received testing message from ${msg.instance} with events ${msg.events}` ); appEvents[msg.instance] = msg.events; } // we have to do the re-broadcasting that the pm2-intercom module would do. if (msg.topic === "log4js:message") { debug(`Received log message ${msg}`); for (const id in cluster.workers) { cluster.workers[id].send(msg); } } }; cluster.on("message", messageHandler); let count = 0; cluster.on("exit", () => { count += 1; if (count === 2) { // wait for any IPC messages still to come, because it seems they are slooooow. setTimeout(() => { test("PM2 Support", batch => { batch.test("should not get any events when turned off", t => { t.notOk( appEvents["0"].filter( e => e && e.data[0].indexOf("will not be logged") > -1 ).length ); t.notOk( appEvents["1"].filter( e => e && e.data[0].indexOf("will not be logged") > -1 ).length ); t.end(); }); batch.test("should get events on app instance 0", t => { t.equal(appEvents["0"].length, 2); t.equal(appEvents["0"][0].data[0], "this should now get logged"); t.equal(appEvents["0"][1].data[0], "this should now get logged"); t.end(); }); batch.test("should not get events on app instance 1", t => { t.equal(appEvents["1"].length, 0); t.end(); }); batch.end(); cluster.removeListener("message", messageHandler); }); }, 1000); } }); } else { const recorder = require("../../lib/appenders/recording"); const log4js = require("../../lib/log4js"); log4js.configure({ appenders: { out: { type: "recording" } }, categories: { default: { appenders: ["out"], level: "info" } } }); const logger = log4js.getLogger("test"); logger.info( "this is a test, but without enabling PM2 support it will not be logged" ); // IPC messages can take a while to get through to start with. setTimeout(() => { log4js.shutdown(() => { log4js.configure({ appenders: { out: { type: "recording" } }, categories: { default: { appenders: ["out"], level: "info" } }, pm2: true }); const anotherLogger = log4js.getLogger("test"); setTimeout(() => { anotherLogger.info("this should now get logged"); }, 1000); // if we're the pm2-master we should wait for the other process to send its log messages setTimeout(() => { log4js.shutdown(() => { const events = recorder.replay(); debug( `Sending test events ${events} from ${process.env.NODE_APP_INSTANCE}` ); process.send( { type: "testing", instance: process.env.NODE_APP_INSTANCE, events }, () => { setTimeout(() => { cluster.worker.disconnect(); }, 1000); } ); }); }, 3000); }); }, 2000); }