winston-daily-rotate-file
Advanced tools
Comparing version 1.1.4 to 1.1.5
43
index.js
@@ -12,2 +12,4 @@ 'use strict'; | ||
var weekday = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; | ||
// | ||
@@ -100,2 +102,3 @@ // ### function DailyRotateFile (options) | ||
this._minute = now.getUTCMinutes(); | ||
this._weekday = weekday[now.getUTCDay()]; | ||
@@ -123,3 +126,4 @@ var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhM])\1?/g; | ||
m: this._minute, | ||
mm: pad(this._minute) | ||
mm: pad(this._minute), | ||
ddd: this._weekday | ||
}; | ||
@@ -390,3 +394,2 @@ return this.datePattern.replace(token, function ($0) { | ||
DailyRotateFile.prototype.open = function (callback) { | ||
var now = new Date(); | ||
if (this.opening) { | ||
@@ -400,3 +403,3 @@ // | ||
} else if (!this._stream || (this.maxsize && this._size >= this.maxsize) || | ||
(this._year < now.getUTCFullYear() || this._month < now.getUTCMonth() || this._date < now.getUTCDate() || this._hour < now.getUTCHours() || this._minute < now.getUTCMinutes())) { | ||
this._filenameHasExpired()) { | ||
// | ||
@@ -556,3 +559,3 @@ // If we dont have a stream or have exceeded our size, then create | ||
var now = new Date(); | ||
if (self._year < now.getUTCFullYear() || self._month < now.getUTCMonth() || self._date < now.getUTCDate() || self._hour < now.getUTCHours() || self._minute < now.getUTCMinutes()) { | ||
if (self._filenameHasExpired()) { | ||
self._year = now.getUTCFullYear(); | ||
@@ -563,2 +566,3 @@ self._month = now.getUTCMonth(); | ||
self._minute = now.getUTCMinutes(); | ||
self._weekday = weekday[now.getUTCDay()]; | ||
self._created = 0; | ||
@@ -591,5 +595,9 @@ return checkFile(self._getFile()); | ||
if (remaining === 0) { | ||
fs.unlinkSync(path.join(this.dirname, filename)); | ||
try { | ||
fs.unlinkSync(path.join(this.dirname, filename)); | ||
} catch (e) {} | ||
} else { | ||
fs.unlinkSync(path.join(this.dirname, filename + '.' + remaining)); | ||
try { | ||
fs.unlinkSync(path.join(this.dirname, filename + '.' + remaining)); | ||
} catch (e) {} | ||
} | ||
@@ -641,1 +649,24 @@ } | ||
}; | ||
// | ||
// ### @private function _filenameHasExpired () | ||
// Checks whether the current log file is valid | ||
// based on given datepattern | ||
// | ||
DailyRotateFile.prototype._filenameHasExpired = function () { | ||
var now = new Date(); | ||
// searching for m is enough to say minute in date pattern | ||
if (this.datePattern.match(/m/)) { | ||
return (this._year < now.getUTCFullYear() || this._month < now.getUTCMonth() || this._date < now.getUTCDate() || this._hour < now.getUTCHours() || this._minute < now.getUTCMinutes()); | ||
} else if (this.datePattern.match(/H/)) { | ||
return (this._year < now.getUTCFullYear() || this._month < now.getUTCMonth() || this._date < now.getUTCDate() || this._hour < now.getUTCHours()); | ||
} else if (this.datePattern.match(/d/)) { | ||
return (this._year < now.getUTCFullYear() || this._month < now.getUTCMonth() || this._date < now.getUTCDate()); | ||
} else if (this.datePattern.match(/M/)) { | ||
return (this._year < now.getUTCFullYear() || this._month < now.getUTCMonth()); | ||
} else if (this.datePattern.match(/yy/)) { | ||
return (this._year < now.getUTCFullYear()); | ||
} | ||
return false; | ||
}; |
{ | ||
"name": "winston-daily-rotate-file", | ||
"version": "1.1.4", | ||
"version": "1.1.5", | ||
"description": "A transport for winston which logs to a rotating file each day.", | ||
@@ -37,3 +37,4 @@ "main": "index.js", | ||
"moment": "2.13.0", | ||
"rimraf": "2.5.2" | ||
"rimraf": "2.5.2", | ||
"timekeeper": "^0.1.1" | ||
}, | ||
@@ -40,0 +41,0 @@ "eslintConfig": { |
@@ -13,6 +13,6 @@ # winston-daily-rotate-file | ||
The DailyRotateFile transport can rotate files by minute, hour, day, month or year. In addition to the options accepted by the File transport, the Daily Rotate File Transport also accepts the following options: | ||
The DailyRotateFile transport can rotate files by minute, hour, day, month, year or weekday. In addition to the options accepted by the File transport, the Daily Rotate File Transport also accepts the following options: | ||
* __datePattern:__ A string representing the pattern to be used when appending the date to the filename (default '.yyyy-MM-dd'). The meta characters used in this string will dictate the frequency of the file rotation. For example, if your datePattern is simply '.HH' you will end up with 24 log files that are picked up and appended to every day. | ||
* __prepend:__ Defines if the rolling time of the log file should be prepended at the begging of the filename (default `false`) | ||
* __datePattern:__ A string representing the pattern to be used when appending the date to the filename (default 'yyyy-MM-dd'). The meta characters used in this string will dictate the frequency of the file rotation. For example, if your datePattern is simply 'HH' you will end up with 24 log files that are picked up and appended to every day. | ||
* __prepend:__ Defines if the rolling time of the log file should be prepended at the beginning of the filename (default 'false'). | ||
@@ -31,2 +31,3 @@ Valid meta characters in the datePattern are: | ||
* __mm:__ The zero padded minute. | ||
* __ddd:__ The weekday (Mon, Tue, ..., Sun). | ||
@@ -33,0 +34,0 @@ *Metadata:* Logged via util.inspect(meta); |
21
test.js
@@ -5,3 +5,4 @@ var winston = require('winston'); | ||
var fileTransportOpts = { | ||
filename: './server.log', | ||
filename: './server', | ||
datePattern: '.log', | ||
maxsize: 100, | ||
@@ -11,11 +12,4 @@ maxFiles: 2 | ||
var consoleTransportOpts = { | ||
colorize: true, | ||
timestamp: true, | ||
prettyPrint: true | ||
}; | ||
var logger = new (winston.Logger)({ | ||
transports: [ | ||
new (winston.transports.Console)(consoleTransportOpts), | ||
new (winston.transports.DailyRotateFile)(fileTransportOpts) | ||
@@ -26,5 +20,10 @@ ] | ||
for (var i = 0; i < 100000; i++) { | ||
setTimeout(function () { | ||
logger.log('info', 'Hello created log files!'); | ||
}, 1); | ||
setTimeout(function (counter) { | ||
logger.log('info', counter.toString() + ': Hello created log files!', {}, function (err, logged) { | ||
if (err) { | ||
console.log('ERR: ', err); | ||
} | ||
console.log(counter.toString() + ': ' + logged); | ||
}); | ||
}, 250, i); | ||
} |
@@ -10,2 +10,4 @@ /* eslint-disable max-nested-callbacks,no-unused-expressions */ | ||
var moment = require('moment'); | ||
var fs = require('fs'); | ||
var tk = require('timekeeper'); | ||
var MemoryStream = require('./memory-stream'); | ||
@@ -16,4 +18,2 @@ | ||
var fixturesDir = path.join(__dirname, 'fixtures'); | ||
rimraf.sync(fixturesDir); | ||
mkdirp(fixturesDir); | ||
@@ -29,2 +29,11 @@ var transports = { | ||
prepend: true | ||
}), | ||
'weekday file': new DailyRotateFile({ | ||
filename: path.join(fixturesDir, 'testfilename_weekday'), | ||
datePattern: '.ddd.log' | ||
}), | ||
'prepend weekday file': new DailyRotateFile({ | ||
filename: path.join(fixturesDir, 'testfilename_prepend_weekday.log'), | ||
datePattern: 'ddd-', | ||
prepend: true | ||
}) | ||
@@ -34,6 +43,11 @@ }; | ||
describe('winston/transports/daily-rotate-file', function () { | ||
before(function () { | ||
rimraf.sync(fixturesDir); | ||
mkdirp.sync(fixturesDir); | ||
}); | ||
describe('an instance of the transport', function () { | ||
describe('with default datePatterns', function () { | ||
it('should have a proper filename when prepend option is false', function () { | ||
var now = moment().format('YYYY-MM-DD'); | ||
var now = moment().utc().format('YYYY-MM-DD'); | ||
var transport = new DailyRotateFile({ | ||
@@ -48,3 +62,3 @@ filename: path.join(fixturesDir, 'prepend-false.log'), | ||
it('should have a proper filename when prepend options is true', function () { | ||
var now = moment().format('YYYY-MM-DD'); | ||
var now = moment().utc().format('YYYY-MM-DD'); | ||
var transport = new DailyRotateFile({ | ||
@@ -59,3 +73,3 @@ filename: path.join(fixturesDir, 'prepend-true.log'), | ||
it('should remove leading dot if one is provided with datePattern', function () { | ||
var now = moment().format('YYYYMMDD'); | ||
var now = moment().utc().format('YYYYMMDD'); | ||
var transport = new DailyRotateFile({ | ||
@@ -71,3 +85,3 @@ filename: path.join(fixturesDir, 'prepend-false.log'), | ||
it('should not add leading dot if one is not provided with datePattern', function () { | ||
var now = moment().format('YYYY-MM-DD'); | ||
var now = moment().utc().format('YYYY-MM-DD'); | ||
var transport = new DailyRotateFile({ | ||
@@ -82,3 +96,3 @@ filename: path.join(fixturesDir, 'log'), | ||
it('should remove leading dot if one is provided with datePattern when prepend option is true', function () { | ||
var now = moment().format('YYYY-MM-DD'); | ||
var now = moment().utc().format('YYYY-MM-DD'); | ||
var transport = new DailyRotateFile({ | ||
@@ -167,3 +181,234 @@ filename: path.join(fixturesDir, 'prepend-true.log'), | ||
}); | ||
describe('when passed an valid filename with different date patterns for log rotation', function () { | ||
// patterns having one start timestamp for which log file will be creted, | ||
// then one mid timestamp for which log file should not be rotated, | ||
// and finally one end timestamp for which log file should be rotated and | ||
// new logfile should be created. | ||
var patterns = { | ||
'full year pattern .yyyy': { | ||
pattern: '.yyyy', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1874993560000, // GMT: Fri, 01 Jun 2029 07:32:40 GMT | ||
end: 1893483160000, // GMT: Tue, 01 Jan 2030 07:32:40 GMT | ||
oldfile: 'test-rotation.log.2029', | ||
newfile: 'test-rotation.log.2030' | ||
}, | ||
'small year pattern .yy': { | ||
pattern: '.yy', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1874993560000, // GMT: Fri, 01 Jun 2029 07:32:40 GMT | ||
end: 1893483160000, // GMT: Tue, 01 Jan 2030 07:32:40 GMT | ||
oldfile: 'test-rotation.log.29', | ||
newfile: 'test-rotation.log.30' | ||
}, | ||
'month pattern .M': { | ||
pattern: '.M', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1863156760000, // GMT: Mon, 15 Jan 2029 07:32:40 GMT | ||
end: 1864625560000, // GMT: Thu, 01 Feb 2029 07:32:40 GMT | ||
oldfile: 'test-rotation.log.1', | ||
newfile: 'test-rotation.log.2' | ||
}, | ||
'zero padded month pattern .MM': { | ||
pattern: '.MM', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1863156760000, // GMT: Mon, 15 Jan 2029 07:32:40 GMT | ||
end: 1864625560000, // GMT: Thu, 01 Feb 2029 07:32:40 GMT | ||
oldfile: 'test-rotation.log.01', | ||
newfile: 'test-rotation.log.02' | ||
}, | ||
'daypattern .d': { | ||
pattern: '.d', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1861986760000, // GMT: Mon, 01 Jan 2029 18:32:40 GMT | ||
end: 1863156760000, // GMT: Mon, 15 Jan 2029 07:32:40 GMT | ||
oldfile: 'test-rotation.log.1', | ||
newfile: 'test-rotation.log.15' | ||
}, | ||
'zero padded day pattern .dd': { | ||
pattern: '.dd', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1861986760000, // GMT: Mon, 01 Jan 2029 18:32:40 GMT | ||
end: 1863156760000, // GMT: Mon, 15 Jan 2029 07:32:40 GMT | ||
oldfile: 'test-rotation.log.01', | ||
newfile: 'test-rotation.log.15' | ||
}, | ||
'hour pattern .H': { | ||
pattern: '.H', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1861947760000, // GMT: Mon, 01 Jan 2029 07:42:40 GMT | ||
end: 1861950760000, // GMT: Mon, 01 Jan 2029 08:32:40 GMT | ||
oldfile: 'test-rotation.log.7', | ||
newfile: 'test-rotation.log.8' | ||
}, | ||
'zero padded hour pattern .HH': { | ||
pattern: '.HH', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1861947760000, // GMT: Mon, 01 Jan 2029 07:42:40 GMT | ||
end: 1861950760000, // GMT: Mon, 01 Jan 2029 08:32:40 GMT | ||
oldfile: 'test-rotation.log.07', | ||
newfile: 'test-rotation.log.08' | ||
}, | ||
'minute pattern .m': { | ||
pattern: '.m', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:50 GMT | ||
mid: 1861947170000, // GMT: Mon, 01 Jan 2029 07:32:50 GMT | ||
end: 1861947760000, // GMT: Mon, 01 Jan 2029 07:42:40 GMT | ||
oldfile: 'test-rotation.log.32', | ||
newfile: 'test-rotation.log.42' | ||
}, | ||
'zero padded minute pattern .mm': { | ||
pattern: '.mm', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:50 GMT | ||
mid: 1861947170000, // GMT: Mon, 01 Jan 2029 07:32:50 GMT | ||
end: 1861947760000, // GMT: Mon, 01 Jan 2029 07:42:40 GMT | ||
oldfile: 'test-rotation.log.32', | ||
newfile: 'test-rotation.log.42' | ||
}, | ||
'daily rotation pattern .yyyy-MM-dd': { | ||
pattern: '.yyyy-MM-dd', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1861965828000, // GMT: Mon, 01 Jan 2029 12:43:48 GMT | ||
end: 1863156760000, // GMT: Mon, 15 Jan 2029 07:32:40 GMT | ||
oldfile: 'test-rotation.log.2029-01-01', | ||
newfile: 'test-rotation.log.2029-01-15' | ||
} | ||
}; | ||
Object.keys(patterns).forEach(function (pattern) { | ||
describe('when passed the pattern ' + pattern, function () { | ||
var transport; | ||
var rotationLogPath = path.join(fixturesDir, 'rotations'); | ||
beforeEach(function (done) { | ||
this.time = new Date(patterns[pattern].start); | ||
tk.travel(this.time); | ||
rimraf.sync(rotationLogPath); | ||
mkdirp.sync(rotationLogPath); | ||
transport = new DailyRotateFile({ | ||
filename: path.join(rotationLogPath, 'test-rotation.log'), | ||
datePattern: patterns[pattern].pattern | ||
}); | ||
done(); | ||
}); | ||
afterEach(function () { | ||
tk.reset(); | ||
}); | ||
it('should create log with proper timestamp', function (done) { | ||
var self = this; | ||
transport.log('error', 'test message', {}, function (err) { | ||
if (err) { | ||
done(err); | ||
} | ||
var filesCreated = fs.readdirSync(rotationLogPath); | ||
expect(filesCreated.length).to.eql(1); | ||
expect(filesCreated).to.include(patterns[pattern].oldfile); | ||
self.time = new Date(patterns[pattern].mid); | ||
tk.travel(self.time); | ||
transport.log('error', '2nd test message', {}, function (err) { | ||
if (err) { | ||
done(err); | ||
} | ||
filesCreated = fs.readdirSync(rotationLogPath); | ||
expect(filesCreated.length).to.eql(1); | ||
expect(filesCreated).to.include(patterns[pattern].oldfile); | ||
self.time = new Date(patterns[pattern].end); | ||
tk.travel(self.time); | ||
transport.log('error', '3rd test message', {}, function (err) { | ||
if (err) { | ||
done(err); | ||
} | ||
filesCreated = fs.readdirSync(rotationLogPath); | ||
expect(filesCreated.length).to.eql(2); | ||
expect(filesCreated).to.include(patterns[pattern].newfile); | ||
transport.close(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('when passed with maxsize and maxfiles', function () { | ||
var dailyRotationPattern = { | ||
pattern: '.yyyy-MM-dd', | ||
start: 1861947160000, // GMT: Mon, 01 Jan 2029 07:32:40 GMT | ||
mid: 1861986760000, // GMT: Mon, 01 Jan 2029 18:32:40 GMT | ||
file1: 'test-rotation.log.2029-01-01', | ||
file2: 'test-rotation.log.2029-01-01.1', | ||
file3: 'test-rotation.log.2029-01-01.2' | ||
}; | ||
describe('when passed the pattern ' + dailyRotationPattern.pattern, function () { | ||
var transport; | ||
var rotationLogPath = path.join(fixturesDir, 'rotations'); | ||
beforeEach(function (done) { | ||
this.time = new Date(dailyRotationPattern.start); | ||
tk.travel(this.time); | ||
rimraf.sync(rotationLogPath); | ||
mkdirp.sync(rotationLogPath); | ||
transport = new DailyRotateFile({ | ||
filename: path.join(rotationLogPath, 'test-rotation.log'), | ||
datePattern: dailyRotationPattern.pattern, | ||
maxFiles: 2, | ||
maxsize: 100 | ||
}); | ||
done(); | ||
}); | ||
afterEach(function () { | ||
tk.reset(); | ||
}); | ||
it('should properly rotate log with old files getting deleted', function (done) { | ||
var self = this; | ||
transport.log('error', 'test message with more than 100 bytes data', {}, function (err) { | ||
if (err) { | ||
done(err); | ||
} | ||
transport.log('error', '2nd test with more than 100 bytes data', {}, function (err) { | ||
if (err) { | ||
done(err); | ||
} | ||
self.time = new Date(dailyRotationPattern.mid); | ||
tk.travel(self.time); | ||
transport.log('error', '3rd test', {}, function (err) { | ||
if (err) { | ||
done(err); | ||
} | ||
transport.log('error', '4th test message with more than 100 bytes data', {}, function (err) { | ||
if (err) { | ||
done(err); | ||
} | ||
var filesCreated = fs.readdirSync(rotationLogPath); | ||
expect(filesCreated.length).to.eql(2); | ||
expect(filesCreated).not.to.include(dailyRotationPattern.file1); | ||
expect(filesCreated).to.include(dailyRotationPattern.file2); | ||
expect(filesCreated).to.include(dailyRotationPattern.file3); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
39045
987
46
8
2