@zwave-js/winston-daily-rotate-file
Version:
A transport for winston which logs to a rotating file each day.
264 lines (224 loc) • 9.6 kB
JavaScript
/* eslint-disable max-nested-callbacks,no-unused-expressions,handle-callback-err */
;
var fs = require('fs');
var path = require('path');
var expect = require('chai').expect;
var rimraf = require('rimraf');
var moment = require('moment');
var winston = require('winston');
var MemoryStream = require('./memory-stream');
var randomString = require('./random-string');
var DailyRotateFile = require('../daily-rotate-file');
function sendLogItem(transport, level, message, meta, cb) { // eslint-disable-line max-params
var logger = winston.createLogger({
transports: [transport]
});
transport.on('logged', function () {
if (cb) {
cb(null, true);
}
});
logger.info({
level: level,
message: message
});
}
describe('winston/transports/daily-rotate-file', function () {
beforeEach(function () {
this.stream = new MemoryStream();
this.transport = new DailyRotateFile({
json: true,
stream: this.stream
});
});
it('should have the proper methods defined', function () {
var transport = new DailyRotateFile({stream: new MemoryStream()});
expect(transport).to.be.instanceOf(DailyRotateFile);
expect(transport).to.respondTo('log');
expect(transport).to.respondTo('query');
});
it('should not allow invalid characters in the filename', function () {
expect(function () {
// eslint-disable-next-line no-new
new DailyRotateFile({
filename: 'test\0log.log'
});
}).to.throw();
});
it('should not allow invalid characters in the dirname', function () {
expect(function () {
// eslint-disable-next-line no-new
new DailyRotateFile({
dirname: 'C:\\application<logs>',
filename: 'test_%DATE%.log'
});
}).to.throw();
});
it('should write to the stream', function (done) {
var self = this;
sendLogItem(this.transport, 'info', 'this message should write to the stream', {}, function (err, logged) {
expect(err).to.be.null;
expect(logged).to.be.true;
var logEntry = JSON.parse(self.stream.toString());
expect(logEntry.level).to.equal('info');
expect(logEntry.message).to.equal('this message should write to the stream');
done();
});
});
describe('when passed metadata', function () {
var circular = {};
circular.metadata = circular;
var params = {
no: {},
object: {metadata: true},
primitive: 'metadata',
circular: circular
};
Object.keys(params).forEach(function (param) {
it('should accept log messages with ' + param + ' metadata', function (done) {
sendLogItem(this.transport, 'info', 'test log message', params[param], function (err, logged) {
expect(err).to.be.null;
expect(logged).to.be.true;
// TODO parse the metadata value to make sure its set properly
done();
});
});
});
});
describe('when using a filename or dirname', function () {
var logDir = path.join(__dirname, 'logs');
var now = moment().utc().format('YYYY-MM-DD-HH');
var filename = path.join(logDir, 'application-' + now + '.testlog');
var options = {
json: true,
dirname: logDir,
filename: 'application-%DATE%',
datePattern: 'YYYY-MM-DD-HH',
utc: true,
extension: '.testlog'
};
beforeEach(function (done) {
var self = this;
rimraf(logDir, function () {
self.transport = new DailyRotateFile(options);
done();
});
});
it('should write to the file', function (done) {
this.transport.once('finish', function () {
var logEntries = fs.readFileSync(filename).toString().split('\n').slice(0, -1);
expect(logEntries.length).to.equal(1);
var logEntry = JSON.parse(logEntries[0]);
expect(logEntry.level).to.equal('info');
expect(logEntry.message).to.equal('this message should write to the file');
done();
});
sendLogItem(this.transport, 'info', 'this message should write to the file', {}, function (err, logged) {
expect(err).to.be.null;
expect(logged).to.be.true;
});
this.transport.close();
});
it('should not allow the stream to be set', function () {
var opts = Object.assign({}, options);
opts.stream = new MemoryStream();
expect(function () {
var transport = new DailyRotateFile(opts);
expect(transport).to.not.be.null;
}).to.throw();
});
it('should raise the new event for a new log file', function (done) {
this.transport.on('new', function (newFile) {
expect(newFile).to.equal(filename);
done();
});
sendLogItem(this.transport, 'info', 'this message should write to the file');
this.transport.close();
});
it('should raise the logRemoved event when pruning old log files', function (done) {
var opts = Object.assign({}, options);
opts.maxSize = '1k';
opts.maxFiles = 1;
this.transport = new DailyRotateFile(opts);
this.transport.on('logRemoved', function (removedFilename) {
expect(removedFilename).to.equal(filename);
done();
});
sendLogItem(this.transport, 'info', randomString(1056));
sendLogItem(this.transport, 'info', randomString(1056));
this.transport.close();
});
describe('when setting zippedArchive', function () {
it('should archive the log after rotating', function (done) {
var opts = Object.assign({}, options);
opts.zippedArchive = true;
opts.maxSize = '1k';
this.transport = new DailyRotateFile(opts);
this.transport.on('finish', function () {
fs.readdir(logDir, function (err, files) {
expect(files.filter(function (file) {
return path.extname(file) === '.gz';
}).length).to.equal(1);
done();
});
});
sendLogItem(this.transport, 'info', randomString(1056));
sendLogItem(this.transport, 'info', randomString(1056));
this.transport.close();
});
});
describe('query', function () {
it('should call callback when no files are present', function () {
this.transport.query(function (err, results) {
expect(results).to.not.be.null;
expect(results.length).to.equal(0);
});
});
it('should raise error when calling with stream', function () {
expect(function () {
var transport = new DailyRotateFile({stream: new MemoryStream()});
transport.query(null);
}).to.throw();
});
it('should raise error when calling with json set to false', function () {
expect(function () {
var opts = Object.assign({}, options);
opts.json = false;
var transport = new DailyRotateFile(opts);
transport.query(null);
}).to.throw();
});
it('should return log entries that match the query', function (done) {
sendLogItem(this.transport, 'info', randomString(1056));
sendLogItem(this.transport, 'info', randomString(1056));
sendLogItem(this.transport, 'info', randomString(1056));
sendLogItem(this.transport, 'info', randomString(1056));
var self = this;
this.transport.on('finish', function () {
self.transport.query(function (err, results) {
expect(results).to.not.be.null;
expect(results.length).to.equal(4);
done();
});
});
this.transport.close();
});
it('should search within archived files', function (done) {
var opts = Object.assign({}, options);
opts.zippedArchive = true;
opts.maxSize = '1k';
this.transport = new DailyRotateFile(opts);
sendLogItem(this.transport, 'info', randomString(1056));
sendLogItem(this.transport, 'info', randomString(1056));
var self = this;
self.transport.on('archive', function () {
self.transport.query(function (err, results) {
expect(results).to.not.be.null;
expect(results.length).to.equal(2);
done();
});
});
});
});
});
});