Skip to content

Instantly share code, notes, and snippets.

@hayes
Last active August 29, 2015 14:09
Show Gist options
  • Save hayes/20d6013c139f495c6577 to your computer and use it in GitHub Desktop.
Save hayes/20d6013c139f495c6577 to your computer and use it in GitHub Desktop.
Most loggers write to streams in a risky way, here is a simple demonstration, and way to avoid the issue.
var fs = require('fs')
var http = require('http')
var count = 0
// using fs.createWriteStream directly will cause massive memory and cpu ussage
// var log = fs.createWriteStream('test.log')
// if you want to make your computer feel bad, replace this with the line above
var log = new Logger('test.log')
// a simple server that sends an empty response and logs a message.
http.createServer(function(req, res) {
count += 1
res.end()
log.write('handled a request\n ')
}).listen(9876)
// make a few simultainous requests to our server
for(var i = 0; i < 10; ++i) {
makeRequest()
}
// make a requests, on response, setup anotger request
function makeRequest() {
http.request('http://localhost:9876', function(res) {
res.on('end', makeRequest)
res.resume()
}).end()
}
// log out some performance stats
setInterval(function() {
console.log(count, 'requests/s.', 'memory ussage:', process.memoryUsage())
count = 0
}, 1000)
// A simple logger that ovoids this issue
function Logger(path) {
if(!(this instanceof Logger)) {
return new Logger(path)
}
// this will overwrite the previous file. Appending
// in this test is an unnessisary waist of disk space
this.stream = fs.createWriteStream(path)
// a place to store logs if the stream cant keep up
this.buffer = ''
// we will pause if the stream falls behind
this.paused = false
}
Logger.prototype.write = function write(msg) {
var logger = this
// if we are paused, add message to the buffer, we can deal with it later
if(logger.paused) {
return logger.buffer += msg
}
// writing to a stream returns a boolean, if it returns false we should pause
logger.paused = !logger.stream.write(msg)
// if we paused, wait for the stream to catch up
if(logger.paused) {
logger.stream.once('drain', function() {
// reset the state, then log out our accumulated messages
var msg = logger.buffer
logger.paused = false
logger.buffer = ''
logger.write(msg)
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment