Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Hooking into Node.js stdout
var util = require('util')
function hook_stdout(callback) {
var old_write = process.stdout.write
process.stdout.write = (function(write) {
return function(string, encoding, fd) {
write.apply(process.stdout, arguments)
callback(string, encoding, fd)
}
})(process.stdout.write)
return function() {
process.stdout.write = old_write
}
}
console.log('a')
console.log('b')
var unhook = hook_stdout(function(string, encoding, fd) {
util.debug('stdout: ' + util.inspect(string))
})
console.log('c')
console.log('d')
unhook()
console.log('e')
console.log('f')
@isaacs

JS FTW!

@tommedema

Thanks, I've created a use case example for when one uses cluster and wishes to separate per-process output.

module.exports = function(mediator) {

    var fs          = require('fs'),
        path        = require('path'),
        config      = require('../../config'),
        env         = process.env,
        stdout      = process.stdout,
        stderr      = process.stderr,
        workerId    = env.NODE_WORKER_ID || env.NODE_UNIQUE_ID,
        logDir      = config.debug.logDir,
        stdoutFile  = path.resolve(logDir, 'worker#' + workerId + '.log'),
        stderrFile  = path.resolve(logDir, 'worker#' + workerId + '.err.log');

    //run prior to boot ready
    mediator.once('boot.init', function() {

        //create a new stdout file stream
        var stdoutFS = fs.createWriteStream(stdoutFile, {
            encoding: 'utf8',
            flags   : 'a+'
        });

        //create a new stderr file stream
        var stderrFS = fs.createWriteStream(stderrFile, {
            encoding: 'utf8',
            flags   : 'a+'
        });

        //pipe stdout to a worker file
        var unhookStdout = hook_writestream(stdout, function(string, encoding, fd) {
            stdoutFS.write(string, encoding || 'utf8');
        });
        console.log('\n\nPrepared new stdout hook to worker file.');

        //pipe stderr to a worker file
        var unhookStderr = hook_writestream(stderr, function(string, encoding, fd) {
            stderrFS.write(string, encoding || 'utf8');
        });
        console.log('\n\nPrepared new stderr hook to worker file.');

        //unhook when things go wrong
        stdoutFS.once('close', function() {
            unhookStdout();
            console.log('Unhooked stdout.');
        });
        stdoutFS.once('error', function(err) {
            unhookStdout();
            console.error('Error: Unhooked stdout due to error %j.', err);
        });
        stderrFS.once('close', function() {
            unhookStderr();
            console.log('Unhooked stderr.');
        });
        stderrFS.once('error', function(err) {
            unhookStderr();
            console.error('Error: Unhooked stderr due to error %j.', err);
        });

    });

    function hook_writestream(stream, callback) {
        var old_write = stream.write;

        stream.write = (function(write) {
            return function(string, encoding, fd) {
                write.apply(stream, arguments);
                callback(string, encoding, fd);
            };
        })(stream.write);

        return function() {
            stream.write = old_write;
        };
    }

};
@tleen

Thanks for this :)

@mikermcneil

Thanks!

@mikermcneil

Crystallized it a bit further here:
https://github.com/mikermcneil/fixture-stdout

@IonicaBizau

Awesome magic here. :smile: Thanks!

@dmarcelino

Thanks @pguillory, I've used it on debug-logger

@wthit56

Genius! In my implementation, I created a new object to add my changes to:

var stdout = process.stdout;
var shadow = process.stdout = Object.create(process.stdout);
shadow.original = stdout;
shadow.write = function() {
    // stdout.original.write.apply(stdout, arguments); // not shown
    result.stdout += data;
};

(Which didn't work. Ignore me. ;P)

@jkuri

Thanks for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.