Trevor
Trevor

Reputation: 2932

how to set up websocket in nodejs to send console.logs to the browser

I am having trouble with this one and need some ideas.

My code so far works... once, for one user. If another user goes to the page, or even another tab, it stops working. I assume it's because console.log is global so it can't keep getting overwritten. So I need an idea on how to do this.

What I have so far

wss.on('connection', function (ws) {
    const _privateLog = console.log;
    const _privateError = console.error;
    const _privateInfo = console.info;
    const _privateWarn = console.warn;
    const _privateDebug = console.debug;
    (function(){
        console.log = function (message) {
            ws.send('<span style="color:lightgreen">' + message + '</span>');
            _privateLog.apply(console, arguments);
        };
    })();
    (function(){
        console.error = function (message) {
            ws.send('<span style="color:red">' + message + '</span>');
            _privateError.apply(console, arguments);
        };
    })();
    (function(){
        console.info = function (message) {
            ws.send('<span style="color:cyan">' + message + '</span>');
            _privateInfo.apply(console, arguments);
        };
    })();
    (function(){
        console.warn = function (message) {
            ws.send('<span style="color:yellow">' + message + '</span>');
            _privateWarn.apply(console, arguments);
        };
    })();
    (function(){
        console.debug = function (message) {
            ws.send('<span style="color:white">' + message + '</span>');
            _privateDebug.apply(console, arguments);
        };
    })();
});

Each new connection makes the previous connection stop getting updates.

I own the code so I could change all instances of console.log, error, etc. to call a function instead, but I am not sure how I would make that function notify every active connection, so same problem from a different angle. My first guess is to create an array of ws connections, then every console.log, loop through it sending the message to each of them. And on disconnect, remove them from the array. Would that work, or is there a better way?

Thanks.

Upvotes: 1

Views: 1379

Answers (1)

jfriend00
jfriend00

Reputation: 707996

To make it send to all currently connected sockets, you need to keep track of which sockets are currently connected and them moving your overwrite of the console functions outside of the connect event like this:

let activeSockets = new Set();

// override console functions
(function() {
    const _privateLog = console.log;
    const _privateError = console.error;
    const _privateInfo = console.info;
    const _privateWarn = console.warn;
    const _privateDebug = console.debug;

    function send(style, data) {
        // send to all currently connected webSockets
        if (typeof data === "object") {
            data = JSON.stringify(data);
        }
        for (let ws of activeSockets) {
            ws.send(`<span style="${style}">${data}</span>`);
        }
    }

    console.log = function (message) {
        send('color:lightgreen', message);
        _privateLog.apply(console, arguments);
    };
    console.error = function (message) {
        send('color:red', message);
        _privateError.apply(console, arguments);
    };
    console.info = function (message) {
        send('color:cyan', message);
        _privateInfo.apply(console, arguments);
    };
    console.warn = function (message) {
        send('color:yellow', message);
        _privateWarn.apply(console, arguments);
    };
    console.debug = function (message) {
        send('color:white', message);
        _privateDebug.apply(console, arguments);
    };
})();

wss.on('connection', function (ws) {
    // maintain list of activeSockets
    activeSockets.add(ws);
    ws.on('close', function() {
        activeSockets.delete(ws);
    });
})

Upvotes: 2

Related Questions