extracted streams, date-format into separate modules

This commit is contained in:
Gareth Jones
2013-08-29 22:15:50 +10:00
parent 5e144e4004
commit 72c4fb48db
15 changed files with 10 additions and 988 deletions

View File

@@ -1,5 +1,5 @@
"use strict";
var streams = require('../streams')
var streams = require('streamroller')
, layouts = require('../layouts')
, path = require('path')
, os = require('os')

View File

@@ -2,7 +2,7 @@
var layouts = require('../layouts')
, path = require('path')
, fs = require('fs')
, streams = require('../streams')
, streams = require('streamroller')
, os = require('os')
, eol = os.EOL || '\n'
, openFiles = [];

View File

@@ -1,66 +0,0 @@
"use strict";
exports.ISO8601_FORMAT = "yyyy-MM-dd hh:mm:ss.SSS";
exports.ISO8601_WITH_TZ_OFFSET_FORMAT = "yyyy-MM-ddThh:mm:ssO";
exports.DATETIME_FORMAT = "dd MM yyyy hh:mm:ss.SSS";
exports.ABSOLUTETIME_FORMAT = "hh:mm:ss.SSS";
function padWithZeros(vNumber, width) {
var numAsString = vNumber + "";
while (numAsString.length < width) {
numAsString = "0" + numAsString;
}
return numAsString;
}
function addZero(vNumber) {
return padWithZeros(vNumber, 2);
}
/**
* Formats the TimeOffest
* Thanks to http://www.svendtofte.com/code/date_format/
* @private
*/
function offset(date) {
// Difference to Greenwich time (GMT) in hours
var os = Math.abs(date.getTimezoneOffset());
var h = String(Math.floor(os/60));
var m = String(os%60);
if (h.length == 1) {
h = "0" + h;
}
if (m.length == 1) {
m = "0" + m;
}
return date.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
}
exports.asString = function(/*format,*/ date) {
var format = exports.ISO8601_FORMAT;
if (typeof(date) === "string") {
format = arguments[0];
date = arguments[1];
}
var vDay = addZero(date.getDate());
var vMonth = addZero(date.getMonth()+1);
var vYearLong = addZero(date.getFullYear());
var vYearShort = addZero(date.getFullYear().toString().substring(2,4));
var vYear = (format.indexOf("yyyy") > -1 ? vYearLong : vYearShort);
var vHour = addZero(date.getHours());
var vMinute = addZero(date.getMinutes());
var vSecond = addZero(date.getSeconds());
var vMillisecond = padWithZeros(date.getMilliseconds(), 3);
var vTimeZone = offset(date);
var formatted = format
.replace(/dd/g, vDay)
.replace(/MM/g, vMonth)
.replace(/y{1,4}/g, vYear)
.replace(/hh/g, vHour)
.replace(/mm/g, vMinute)
.replace(/ss/g, vSecond)
.replace(/SSS/g, vMillisecond)
.replace(/O/g, vTimeZone);
return formatted;
};

View File

@@ -1,5 +1,5 @@
"use strict";
var dateFormat = require('./date_format')
var dateFormat = require('date-format')
, os = require('os')
, eol = os.EOL || '\n'
, util = require('util')

View File

@@ -1,84 +0,0 @@
"use strict";
var fs = require('fs')
, stream
, debug = require('debug')('log4js:BaseRollingFileStream')
, util = require('util')
, semver = require('semver');
if (semver.satisfies(process.version, '>=0.10.0')) {
stream = require('stream');
} else {
stream = require('readable-stream');
}
module.exports = BaseRollingFileStream;
function BaseRollingFileStream(filename, options) {
debug("In BaseRollingFileStream");
this.filename = filename;
this.options = options || { encoding: 'utf8', mode: parseInt('0644', 8), flags: 'a' };
this.currentSize = 0;
function currentFileSize(file) {
var fileSize = 0;
try {
fileSize = fs.statSync(file).size;
} catch (e) {
// file does not exist
}
return fileSize;
}
function throwErrorIfArgumentsAreNotValid() {
if (!filename) {
throw new Error("You must specify a filename");
}
}
throwErrorIfArgumentsAreNotValid();
debug("Calling BaseRollingFileStream.super");
BaseRollingFileStream.super_.call(this);
this.openTheStream();
this.currentSize = currentFileSize(this.filename);
}
util.inherits(BaseRollingFileStream, stream.Writable);
BaseRollingFileStream.prototype._write = function(chunk, encoding, callback) {
var that = this;
function writeTheChunk() {
debug("writing the chunk to the underlying stream");
that.currentSize += chunk.length;
that.theStream.write(chunk, encoding, callback);
}
debug("in _write");
if (this.shouldRoll()) {
this.currentSize = 0;
this.roll(this.filename, writeTheChunk);
} else {
writeTheChunk();
}
};
BaseRollingFileStream.prototype.openTheStream = function(cb) {
debug("opening the underlying stream");
this.theStream = fs.createWriteStream(this.filename, this.options);
if (cb) {
this.theStream.on("open", cb);
}
};
BaseRollingFileStream.prototype.closeTheStream = function(cb) {
debug("closing the underlying stream");
this.theStream.end(cb);
};
BaseRollingFileStream.prototype.shouldRoll = function() {
return false; // default behaviour is never to roll
};
BaseRollingFileStream.prototype.roll = function(filename, callback) {
callback(); // default behaviour is not to do anything
};

View File

@@ -1,88 +0,0 @@
"use strict";
var BaseRollingFileStream = require('./BaseRollingFileStream')
, debug = require('debug')('log4js:DateRollingFileStream')
, format = require('../date_format')
, async = require('async')
, fs = require('fs')
, util = require('util');
module.exports = DateRollingFileStream;
function DateRollingFileStream(filename, pattern, options, now) {
debug("Now is ", now);
if (pattern && typeof(pattern) === 'object') {
now = options;
options = pattern;
pattern = null;
}
this.pattern = pattern || '.yyyy-MM-dd';
this.now = now || Date.now;
this.lastTimeWeWroteSomething = format.asString(this.pattern, new Date(this.now()));
this.baseFilename = filename;
this.alwaysIncludePattern = false;
if (options) {
if (options.alwaysIncludePattern) {
this.alwaysIncludePattern = true;
filename = this.baseFilename + this.lastTimeWeWroteSomething;
}
delete options.alwaysIncludePattern;
if (Object.keys(options).length === 0) {
options = null;
}
}
debug("this.now is ", this.now, ", now is ", now);
DateRollingFileStream.super_.call(this, filename, options);
}
util.inherits(DateRollingFileStream, BaseRollingFileStream);
DateRollingFileStream.prototype.shouldRoll = function() {
var lastTime = this.lastTimeWeWroteSomething,
thisTime = format.asString(this.pattern, new Date(this.now()));
debug("DateRollingFileStream.shouldRoll with now = ",
this.now(), ", thisTime = ", thisTime, ", lastTime = ", lastTime);
this.lastTimeWeWroteSomething = thisTime;
this.previousTime = lastTime;
return thisTime !== lastTime;
};
DateRollingFileStream.prototype.roll = function(filename, callback) {
var that = this;
debug("Starting roll");
if (this.alwaysIncludePattern) {
this.filename = this.baseFilename + this.lastTimeWeWroteSomething;
async.series([
this.closeTheStream.bind(this),
this.openTheStream.bind(this)
], callback);
} else {
var newFilename = this.baseFilename + this.previousTime;
async.series([
this.closeTheStream.bind(this),
deleteAnyExistingFile,
renameTheCurrentFile,
this.openTheStream.bind(this)
], callback);
}
function deleteAnyExistingFile(cb) {
//on windows, you can get a EEXIST error if you rename a file to an existing file
//so, we'll try to delete the file we're renaming to first
fs.unlink(newFilename, function (err) {
//ignore err: if we could not delete, it's most likely that it doesn't exist
cb();
});
}
function renameTheCurrentFile(cb) {
debug("Renaming the ", filename, " -> ", newFilename);
fs.rename(filename, newFilename, cb);
}
};

View File

@@ -1,89 +0,0 @@
"use strict";
var BaseRollingFileStream = require('./BaseRollingFileStream')
, debug = require('debug')('log4js:RollingFileStream')
, util = require('util')
, path = require('path')
, fs = require('fs')
, async = require('async');
module.exports = RollingFileStream;
function RollingFileStream (filename, size, backups, options) {
this.size = size;
this.backups = backups || 1;
function throwErrorIfArgumentsAreNotValid() {
if (!filename || !size || size <= 0) {
throw new Error("You must specify a filename and file size");
}
}
throwErrorIfArgumentsAreNotValid();
RollingFileStream.super_.call(this, filename, options);
}
util.inherits(RollingFileStream, BaseRollingFileStream);
RollingFileStream.prototype.shouldRoll = function() {
debug("should roll with current size %d, and max size %d", this.currentSize, this.size);
return this.currentSize >= this.size;
};
RollingFileStream.prototype.roll = function(filename, callback) {
var that = this,
nameMatcher = new RegExp('^' + path.basename(filename));
function justTheseFiles (item) {
return nameMatcher.test(item);
}
function index(filename_) {
return parseInt(filename_.substring((path.basename(filename) + '.').length), 10) || 0;
}
function byIndex(a, b) {
if (index(a) > index(b)) {
return 1;
} else if (index(a) < index(b) ) {
return -1;
} else {
return 0;
}
}
function increaseFileIndex (fileToRename, cb) {
var idx = index(fileToRename);
debug('Index of ', fileToRename, ' is ', idx);
if (idx < that.backups) {
//on windows, you can get a EEXIST error if you rename a file to an existing file
//so, we'll try to delete the file we're renaming to first
fs.unlink(filename + '.' + (idx+1), function (err) {
//ignore err: if we could not delete, it's most likely that it doesn't exist
debug('Renaming ', fileToRename, ' -> ', filename, '.', (idx+1));
fs.rename(path.join(path.dirname(filename), fileToRename), filename + '.' + (idx + 1), cb);
});
} else {
cb();
}
}
function renameTheFiles(cb) {
//roll the backups (rename file.n to file.n+1, where n <= numBackups)
debug("Renaming the old files");
fs.readdir(path.dirname(filename), function (err, files) {
async.forEachSeries(
files.filter(justTheseFiles).sort(byIndex).reverse(),
increaseFileIndex,
cb
);
});
}
debug("Rolling, rolling, rolling");
async.series([
this.closeTheStream.bind(this),
renameTheFiles,
this.openTheStream.bind(this)
], callback);
};

View File

@@ -1,2 +0,0 @@
exports.RollingFileStream = require('./RollingFileStream');
exports.DateRollingFileStream = require('./DateRollingFileStream');