|
'use strict'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
var fs = require('fs'); |
|
var async = require('async'); |
|
var _ = require('lodash'); |
|
var zlib = require('zlib'); |
|
var EventEmitter = require('events').EventEmitter; |
|
var NumberedFileOps = require('./numberedfileops'); |
|
var DateStampedFileOps = require('./datestampedfileops'); |
|
|
|
var _DEBUG = false; |
|
|
|
function FileRotator(logpath, totalFiles, totalSize, gzip) { |
|
|
|
var base = new EventEmitter(); |
|
|
|
var stream; |
|
var streamPath; |
|
|
|
var fileops = null; |
|
|
|
if (DateStampedFileOps.isDateStamped(logpath)) { |
|
fileops = DateStampedFileOps(logpath, totalFiles, totalSize, gzip); |
|
} else { |
|
fileops = NumberedFileOps(logpath, totalFiles, totalSize, gzip); |
|
} |
|
|
|
function gzipCurrentFile(next) { |
|
if (!gzip) { |
|
return next(); |
|
} |
|
|
|
var unzippedPath = fileops.getStreamFilepath(false); |
|
var zippedPath = fileops.getStreamFilepath(true); |
|
|
|
fs.createReadStream(unzippedPath) |
|
.on('error', function (err) { |
|
base.emit('error', err); |
|
next(); |
|
}) |
|
.pipe(zlib.createGzip()) |
|
.pipe(fs.createWriteStream(zippedPath)) |
|
.on('finish', function () { |
|
fs.unlink(unzippedPath, next); |
|
}) |
|
} |
|
|
|
function streamErrorHandler(err) { |
|
base.emit('error', err); |
|
}; |
|
|
|
function initialiseNewFile(triggerinfo) { |
|
return function (next) { |
|
triggerinfo = triggerinfo || {}; |
|
fileops.newStreamFilepath(triggerinfo, function (err, filePath) { |
|
if (err) { |
|
return next(err); |
|
} |
|
|
|
stream = fs.createWriteStream(filePath, |
|
{flags: 'a', encoding: 'utf8'}); |
|
|
|
streamPath = filePath; |
|
|
|
stream.on('error', streamErrorHandler); |
|
|
|
stream.once('open', function () { |
|
fs.stat(filePath, function (err, stats) { |
|
if (err) { |
|
base.emit('error', err); |
|
} else { |
|
base.emit('newfile', { |
|
stream: stream, |
|
logpath: streamPath, |
|
stats: stats |
|
}); |
|
} |
|
|
|
if (next) { |
|
next(); |
|
} |
|
}); |
|
}); |
|
}); |
|
}; |
|
} |
|
|
|
function shutdownCurrentStream(next) { |
|
base.emit('closefile'); |
|
if (stream) { |
|
var streamCopy = stream; |
|
stream.end(function () { |
|
streamCopy.removeListener('error', streamErrorHandler); |
|
if (next) { |
|
next(); |
|
} |
|
}); |
|
stream = null; |
|
} |
|
}; |
|
|
|
|
|
|
|
|
|
function rotate(triggerinfo, callback) { |
|
async.series([ |
|
shutdownCurrentStream, |
|
gzipCurrentFile, |
|
fileops.moveIntermediateFiles, |
|
fileops.deleteFiles, |
|
initialiseNewFile(triggerinfo) |
|
], function (err) { |
|
callback(err, stream, streamPath); |
|
}); |
|
} |
|
|
|
|
|
|
|
var initialised = false; |
|
function initialise(startNewFile, callback) { |
|
if (!initialised) { |
|
initialised = true; |
|
|
|
async.series([ |
|
fileops.deleteFiles, |
|
initialiseNewFile({ startNewFile: startNewFile }) |
|
], function (err) { |
|
callback(err, stream, streamPath); |
|
}); |
|
} else { |
|
callback(); |
|
} |
|
} |
|
|
|
return _.extend({}, { |
|
initialise: initialise, |
|
rotate: rotate, |
|
end: shutdownCurrentStream |
|
}, base); |
|
} |
|
|
|
module.exports = FileRotator; |
|
|