-
-
Save pguillory/729616 to your computer and use it in GitHub Desktop.
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') |
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;
};
}
};
Thanks for this :)
Thanks!
Crystallized it a bit further here:
https://github.com/mikermcneil/fixture-stdout
Another approach with knobs
https://gist.github.com/stringparser/b539b8cfd5769542037d
Awesome magic here. 😄 Thanks!
Thanks @pguillory, I've used it on debug-logger
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)
Thanks for this.
FYI. Commenting out this line mutes the log too.
This implementation redirects both stdout
and stderr
to a log file:
var log_file = require('fs').createWriteStream(__dirname + '/log.txt', {flags : 'w'})
function hook_stream(stream, callback) {
var old_write = stream.write
stream.write = (function(write) {
return function(string, encoding, fd) {
write.apply(stream, arguments) // comments this line if you don't want output in the console
callback(string, encoding, fd)
}
})(stream.write)
return function() {
stream.write = old_write
}
}
console.log('a')
console.error('b')
var unhook_stdout = hook_stream(process.stdout, function(string, encoding, fd) {
log_file.write(string, encoding)
})
var unhook_stderr = hook_stream(process.stderr, function(string, encoding, fd) {
log_file.write(string, encoding)
})
console.log('c')
console.error('d')
unhook_stdout()
unhook_stderr()
console.log('e')
console.error('f')
It should print in the console
a
b
c
d
e
f
and in the log file:
c
d
This one works with AWS Lambda:
function hookStdout(callback) {
const boundProcessStdout = process.stdout.write.bind(process.stdout)
const boundProcessStderr = process.stderr.write.bind(process.stderr)
process.stdout.write = (string, encoding, fd) => {
boundProcessStdout(string, encoding, fd)
callback(string, encoding, fd, false)
}
process.stderr.write = (string, encoding, fd) => {
boundProcessStderr(string, encoding, fd)
callback(string, encoding, fd, true)
}
return () => {
process.stdout.write = boundProcessStdout
process.stderr.write = boundProcessStderr
}
}
thanks for this.
Thank you so much for this! I'm trying to make an advanced CLI for a nextjs app, but webpack uses stdout
and messes up all of the formatting!
JS FTW!