8000 Working date rolling file stream · LikeABossProgrammer/log4js-node@185f343 · GitHub
[go: up one dir, main page]

Skip to content

Commit 185f343

Browse files
author
Gareth Jones
committed
Working date rolling file stream
1 parent be1272c commit 185f343

File tree

3 files changed

+175
-20
lines changed

3 files changed

+175
-20
lines changed

lib/streams/BaseRollingFileStream.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@ var fs = require('fs'),
22
util = require('util');
33

44
function debug(message) {
5-
// util.debug(message);
65
// console.log(message);
76
}
87

98
module.exports = BaseRollingFileStream;
109

1110
function BaseRollingFileStream(filename, options) {
11+
12+
debug("In BaseRollingFileStream");
1213
this.filename = filename;
1314
this.options = options || { encoding: 'utf8', mode: 0644, flags: 'a' };
1415
this.rolling = false;
1516
this.writesWhileRolling = [];
1617
this.currentSize = 0;
18+
this.rollBeforeWrite = false;
1719

1820
function currentFileSize(file) {
1921
var fileSize = 0;
@@ -32,7 +34,7 @@ function BaseRollingFileStream(filename, options) {
3234
}
3335

3436
throwErrorIfArgumentsAreNotValid();
35-
37+
debug("Calling BaseRollingFileStream.super");
3638
BaseRollingFileStream.super_.call(this, this.filename, this.options);
3739
this.currentSize = currentFileSize(this.filename);
3840
}
@@ -67,18 +69,24 @@ BaseRollingFileStream.prototype.initRolling = function() {
6769
};
6870

6971
BaseRollingFileStream.prototype.write = function(data, encoding) {
72+
var canWrite = false;
7073
if (this.rolling) {
7174
this.writesWhileRolling.push({ data: data, encoding: encoding });
72-
return false;
7375
} else {
74-
var canWrite = BaseRollingFileStream.super_.prototype.write.call(this, data, encoding);
75-
this.currentSize += data.length;
76-
debug('current size = ' + this.currentSize);
77-
if (this.shouldRoll()) {
76+
if (this.rollBeforeWrite && this.shouldRoll()) {
77+
this.writesWhileRolling.push({ data: data, encoding: encoding });
7878
this.initRolling();
79+
} else {
80+
canWrite = BaseRollingFileStream.super_.prototype.write.call(this, data, encoding);
81+
this.currentSize += data.length;
82+
debug('current size = ' + this.currentSize);
83+
84+
if (!this.rollBeforeWrite && this.shouldRoll()) {
85+
this.initRolling();
86+
}
7987
}
80-
return canWrite;
8188
}
89+
return canWrite;
8290
};
8391

8492
BaseRollingFileStream.prototype.shouldRoll = function() {

lib/streams/DateRollingFileStream.js

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,89 @@
11
var BaseRollingFileStream = require('./BaseRollingFileStream'),
2+
format = require('../date_format'),
3+
async = require('async'),
4+
fs = require('fs'),
25
util = require('util');
36

47
module.exports = DateRollingFileStream;
58

6-
function DateRollingFileStream(filename, pattern, options) {
7-
if (typeof(pattern) === 'object') {
9+
function debug(message) {
10+
// console.log(message);
11+
}
12+
13+
function DateRollingFileStream(filename, pattern, options, now) {
14+
debug("Now is " + now);
15+
if (pattern && typeof(pattern) === 'object') {
16+
now = options;
817
options = pattern;
918
pattern = null;
1019
}
11-
this.pattern = pattern || 'yyyy-mm-dd';
20+
this.pattern = pattern || '.yyyy-MM-dd';
21+
this.now = now || Date.now;
22+
this.lastTimeWeWroteSomething = format.asString(this.pattern, new Date(this.now()));
23+
debug("this.now is " + this.now + ", now is " + now);
1224

1325
DateRollingFileStream.super_.call(this, filename, options);
26+
this.rollBeforeWrite = true;
1427
}
1528

1629
util.inherits(DateRollingFileStream, BaseRollingFileStream);
30+
31+
DateRollingFileStream.prototype.shouldRoll = function() {
32+
var lastTime = this.lastTimeWeWroteSomething,
33+
thisTime = format.asString(this.pattern, new Date(this.now()));
34+
35+
debug("DateRollingFileStream.shouldRoll with now = " + this.now() + ", thisTime = " + thisTime + ", lastTime = " + lastTime);
36+
37+
this.lastTimeWeWroteSomething = thisTime;
38+
this.previousTime = lastTime;
39+
40+
return thisTime !== lastTime;
41+
};
42+
43+
DateRollingFileStream.prototype.roll = function(filename, callback) {
44+
var that = this,
45+
newFilename = filename + this.previousTime;
46+
47+
debug("Starting roll");
48+
debug("Queueing up data until we've finished rolling");
49+
debug("Flushing underlying stream");
50+
this.flush();
51+
52+
async.series([
53+
deleteAnyExistingFile,
54+
renameTheCurrentFile,
55+
openANewFile
56+
], callback);
57+
58+
function deleteAnyExistingFile(cb) {
59+
//on windows, you can get a EEXIST error if you rename a file to an existing file
60+
//so, we'll try to delete the file we're renaming to first
61+
fs.unlink(newFilename, 10000 function (err) {
62+
//ignore err: if we could not delete, it's most likely that it doesn't exist
63+
cb();
64+
});
65+
}
66+
67+
function renameTheCurrentFile(cb) {
68+
debug("Renaming the " + filename + " -> " + newFilename);
69+
fs.rename(filename, newFilename, cb);
70+
}
71+
72+
function openANewFile(cb) {
73+
debug("Opening a new file");
74+
fs.open(
75+
filename,
76+
that.options.flags,
77+
that.options.mode,
78+
function (err, fd) {
79+
debug("opened new file");
80+
var oldLogFileFD = that.fd;
81+
that.fd = fd;
82+
that.writable = true;
83+
fs.close(oldLogFileFD, cb);
84+
}
85+
);
86+
}
87+
88+
89+
};

test/streams/DateRollingFileStream-test.js

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
var vows = require('vows'),
22
assert = require('assert'),
33
fs = require('fs'),
4-
DateRollingFileStream = require('../../lib/streams').DateRollingFileStream;
4+
DateRollingFileStream = require('../../lib/streams').DateRollingFileStream,
5+
testTime = new Date(2012, 8, 12, 10, 37, 11);
6+
7+
function cleanUp(filename) {
8+
return function() {
9+
fs.unlink(filename);
10+
};
11+
}
12+
13+
function now() {
14+
return testTime.getTime();
15+
}
516

617
vows.describe('DateRollingFileStream').addBatch({
718
'arguments': {
8-
topic: new DateRollingFileStream('test-date-rolling-file-stream', 'yyyy-mm-dd.hh'),
19+
topic: new DateRollingFileStream(__dirname + '/test-date-rolling-file-stream-1', 'yyyy-mm-dd.hh'),
20+
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-1'),
921

1022
'should take a filename and a pattern and return a FileWriteStream': function(stream) {
11-
assert.equal(stream.filename, 'test-date-rolling-file-stream');
23+
assert.equal(stream.filename, __dirname + '/test-date-rolling-file-stream-1');
1224
assert.equal(stream.pattern, 'yyyy-mm-dd.hh');
1325
assert.instanceOf(stream, fs.FileWriteStream);
1426
},
@@ -20,29 +32,91 @@ vows.describe('DateRollingFileStream').addBatch({
2032
},
2133

2234
'default arguments': {
23-
topic: new DateRollingFileStream('test-date-rolling-file-stream'),
35+
topic: new DateRollingFileStream(__dirname + '/test-date-rolling-file-stream-2'),
36+
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-2'),
2437

25-
'pattern should be yyyy-mm-dd': function(stream) {
26-
assert.equal(stream.pattern, 'yyyy-mm-dd');
38+
'pattern should be .yyyy-MM-dd': function(stream) {
39+
assert.equal(stream.pattern, '.yyyy-MM-dd');
2740
}
2841
},
2942

3043
'with stream arguments': {
31-
topic: new DateRollingFileStream('test-rolling-file-stream', 'yyyy-mm-dd', { mode: 0666 }),
44+
topic: new DateRollingFileStream(__dirname + '/test-date-rolling-file-stream-3', 'yyyy-MM-dd', { mode: 0666 }),
45+
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-3'),
3246

3347
'should pass them to the underlying stream': function(stream) {
3448
assert.equal(stream.mode, 0666);
3549
}
3650
},
3751

3852
'with stream arguments but no pattern': {
39-
topic: new DateRollingFileStream('test-rolling-file-stream', { mode: 0666 }),
53+
topic: new DateRollingFileStream(__dirname + '/test-date-rolling-file-stream-4', { mode: 0666 }),
54+
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-4'),
4055

4156
'should pass them to the underlying stream': function(stream) {
4257
assert.equal(stream.mode, 0666);
4358
},
4459
'should use default pattern': function(stream) {
45-
assert.equal(stream.pattern, 'yyyy-mm-dd');
60+
assert.equal(stream.pattern, '.yyyy-MM-dd');
61+
}
62+
},
63+
64+
'with a pattern of .yyyy-MM-dd': {
65+
topic: function() {
66+
var that = this,
67+
stream = new DateRollingFileStream(__dirname + '/test-date-rolling-file-stream-5', '.yyyy-MM-dd', null, now);
68+
stream.on("open", function() {
69+
stream.write("First message\n");
70+
//wait for the file system to catch up with us
71+
that.callback(null, stream);
72+
});
73+
},
74+
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-5'),
75+
76+
'should create a file with the base name': {
77+
topic: function(stream) {
78+
fs.readFile(__dirname + '/test-date-rolling-file-stream-5', this.callback);
79+
},
80+
'file should contain first message': function(result) {
81+
assert.equal(result.toString(), "First message\n");
82+
}
83+
},
84+
85+
'when the day changes': {
86+
topic: function(stream) {
87+
testTime = new Date(2012, 8, 13, 0, 10, 12);
88+
stream.write("Second message\n");
89+
setTimeout(this.callback, 100);
90+
},
91+
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-5.2012-09-12'),
92+
93+
94+
'the number of files': {
95+
topic: function() {
96+
fs.readdir(__dirname, this.callback);
97+
},
98+
'should be two': function(files) {
99+
assert.equal(files.filter(function(file) { return file.indexOf('test-date-rolling-file-stream-5') > -1; }).length, 2);
100+
}
101+
},
102+
103+
'the file without a date': {
104+
topic: function() {
105+
fs.readFile(__dirname + '/test-date-rolling-file-stream-5', this.callback);
106+
},
107+
'should contain the second message': function(contents) {
108+
assert.equal(contents.toString(), "Second message\n");
109+
}
110+
},
111+
112+
'the file with the date': {
113+
topic: function() {
114+
fs.readFile(__dirname + '/test-date-rolling-file-stream-5.2012-09-12', this.callback);
115+
},
116+
'should contain the first message': function(contents) {
117+
assert.equal(contents.toString(), "First message\n");
118+
}
119+
}
46120
}
47121
}
48122

0 commit comments

Comments
 (0)
0