Version 1.1.0 released:
* added support of passing promises objects which will be resolved with pre-connected db object in options.db; * fixed issue when events logged sometime between authorizeDb and processOpQuery calls may be lost; * renamed default log collection to 'log' because it makes more sense than 'logs' ('log' is a list of messages already, plural form would imply multiple of such lists); * this.mainDb renamed to this.logDb; * this._opQuery renamed to this._opQueue; * added test to promises support (bluebird added to devDependencies as A+ promises implementation).
This commit is contained in:
Родитель
7a7b98ed25
Коммит
ccf69f6cc7
17
README.md
17
README.md
|
@ -34,11 +34,12 @@ The MongoDB transport takes the following options. 'db' is required:
|
|||
'info'.
|
||||
* __silent:__ Boolean flag indicating whether to suppress output, defaults to
|
||||
false.
|
||||
* __db:__ MongoDB connection uri or preconnected db object.
|
||||
* __db:__ MongoDB connection uri, pre-connected db object or promise object
|
||||
which will be resolved with pre-connected db object.
|
||||
* __options:__ MongoDB connection parameters (optional, defaults to
|
||||
`{db: {native_parser: true}, server: {poolSize: 2, socketOptions: {autoReconnect: true}}}`).
|
||||
* __collection__: The name of the collection you want to store log messages in,
|
||||
defaults to 'logs'.
|
||||
defaults to 'log'.
|
||||
* __storeHost:__ Boolean indicating if you want to store machine hostname in
|
||||
logs entry, if set to true it populates MongoDB entry with 'hostname' field,
|
||||
which stores os.hostname() value.
|
||||
|
@ -74,11 +75,21 @@ settled by mongodb, defaults to `false`.
|
|||
|
||||
## Changelog
|
||||
|
||||
### Brief 1.1.0 changelog
|
||||
|
||||
* added support of passing promises objects which will be resolved with
|
||||
pre-connected db object in options.db;
|
||||
* fixed issue when events logged sometime between authorizeDb and
|
||||
processOpQuery calls may be lost;
|
||||
* renamed default log collection to 'log' because it makes more sense than
|
||||
'logs' ('log' is a list of messages already, plural form would imply
|
||||
multiple of such lists).
|
||||
|
||||
### Brief 1.0.0 changelog
|
||||
|
||||
* migrated to mongodb 2.x driver;
|
||||
* changed configuration format to MongoDB uri string;
|
||||
* added support of passing preconnected db object instead of MongoDB uri string;
|
||||
* added support of passing pre-connected db object instead of MongoDB uri string;
|
||||
* added support of passing MongoDB connection parameters in options property;
|
||||
* added support of replica sets through new options and db properties;
|
||||
* migrated to [Semantic Versioning](http://semver.org/) in package versions names;
|
||||
|
|
|
@ -63,7 +63,7 @@ var MongoDB = exports.MongoDB = function(options) {
|
|||
}
|
||||
};
|
||||
}
|
||||
this.collection = (options.collection || 'logs');
|
||||
this.collection = (options.collection || 'log');
|
||||
this.level = (options.level || 'info');
|
||||
this.silent = options.silent;
|
||||
this.username = options.username;
|
||||
|
@ -77,47 +77,55 @@ var MongoDB = exports.MongoDB = function(options) {
|
|||
this.hostname = os.hostname();
|
||||
}
|
||||
|
||||
|
||||
this._opQuery = [];
|
||||
this._opQueue = [];
|
||||
|
||||
var self = this;
|
||||
|
||||
function processOpQuery() {
|
||||
self._opQuery.forEach(function(operation) {
|
||||
self[operation.method].apply(self, operation.args);
|
||||
function setupDatabaseAndEmptyQueue(db) {
|
||||
authorizeDb(db, function(err, db) {
|
||||
createCollection(db, function(err, db) {
|
||||
self.logDb = db;
|
||||
processOpQueue();
|
||||
});
|
||||
});
|
||||
delete self._opQuery;
|
||||
}
|
||||
|
||||
function createCollection(cb) {
|
||||
function processOpQueue() {
|
||||
self._opQueue.forEach(function(operation) {
|
||||
self[operation.method].apply(self, operation.args);
|
||||
});
|
||||
delete self._opQueue;
|
||||
}
|
||||
|
||||
function createCollection(db, cb) {
|
||||
var opts = {};
|
||||
if (self.capped) {
|
||||
opts = {capped: true, size: self.cappedSize};
|
||||
}
|
||||
self.mainDb.createCollection(self.collection, opts, function() {
|
||||
cb(null);
|
||||
db.createCollection(self.collection, opts, function() {
|
||||
cb(null, db);
|
||||
});
|
||||
}
|
||||
|
||||
function authorizeDb(cb) {
|
||||
function authorizeDb(db, cb) {
|
||||
if (self.username && self.password) {
|
||||
self.mainDb.authenticate(self.username, self.password,
|
||||
db.authenticate(self.username, self.password,
|
||||
function(err, result) {
|
||||
if (err) {
|
||||
console.error('winston-mongodb: error initialising logger', err);
|
||||
self.mainDb.close();
|
||||
db.close();
|
||||
return;
|
||||
}
|
||||
if (!result) {
|
||||
console.error('winston-mongodb: invalid username or password');
|
||||
self.mainDb.close();
|
||||
db.close();
|
||||
return;
|
||||
}
|
||||
cb(null);
|
||||
cb(null, db);
|
||||
}
|
||||
);
|
||||
}
|
||||
cb(null);
|
||||
cb(null, db);
|
||||
}
|
||||
|
||||
if ('string' === typeof this.db) {
|
||||
|
@ -126,16 +134,17 @@ var MongoDB = exports.MongoDB = function(options) {
|
|||
console.error('winston-mongodb: error initialising logger', err);
|
||||
return;
|
||||
}
|
||||
self.mainDb = db;
|
||||
authorizeDb(function() {
|
||||
createCollection(processOpQuery);
|
||||
});
|
||||
setupDatabaseAndEmptyQueue(db);
|
||||
});
|
||||
} else if ('function' === typeof this.db.then) {
|
||||
this.db.then(function(db) {
|
||||
setupDatabaseAndEmptyQueue(db);
|
||||
}, function(err) {
|
||||
console.error(
|
||||
'winston-mongodb: error initialising logger from promise', err);
|
||||
});
|
||||
} else {
|
||||
this.mainDb = this.db;
|
||||
authorizeDb(function() {
|
||||
createCollection(processOpQuery);
|
||||
});
|
||||
setupDatabaseAndEmptyQueue(this.db);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -161,8 +170,8 @@ winston.transports.MongoDB = MongoDB;
|
|||
* @param {Function} callback Continuation to respond to when complete.
|
||||
*/
|
||||
MongoDB.prototype.log = function(level, msg, opt_meta, callback) {
|
||||
if (!this.mainDb) {
|
||||
this._opQuery.push({
|
||||
if (!this.logDb) {
|
||||
this._opQueue.push({
|
||||
method: 'log',
|
||||
args: arguments
|
||||
});
|
||||
|
@ -186,7 +195,7 @@ MongoDB.prototype.log = function(level, msg, opt_meta, callback) {
|
|||
callback(err, null);
|
||||
}
|
||||
|
||||
self.mainDb.collection(self.collection, function(err, col) {
|
||||
self.logDb.collection(self.collection, function(err, col) {
|
||||
if (err) {
|
||||
onError(err);
|
||||
return;
|
||||
|
@ -225,8 +234,8 @@ MongoDB.prototype.log = function(level, msg, opt_meta, callback) {
|
|||
* @return {*}
|
||||
*/
|
||||
MongoDB.prototype.query = function(opt_options, callback) {
|
||||
if (!this.mainDb) {
|
||||
this._opQuery.push({
|
||||
if (!this.logDb) {
|
||||
this._opQueue.push({
|
||||
method: 'query',
|
||||
args: arguments
|
||||
});
|
||||
|
@ -257,7 +266,7 @@ MongoDB.prototype.query = function(opt_options, callback) {
|
|||
opt.fields = options.fields;
|
||||
}
|
||||
|
||||
this.mainDb.collection(this.collection, function(err, col) {
|
||||
this.logDb.collection(this.collection, function(err, col) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
|
@ -293,8 +302,8 @@ MongoDB.prototype.stream = function(options, stream) {
|
|||
var self = this;
|
||||
var start = options.start;
|
||||
|
||||
if (!this.mainDb) {
|
||||
this._opQuery.push({
|
||||
if (!this.logDb) {
|
||||
this._opQueue.push({
|
||||
method: 'stream',
|
||||
args: [options, stream]
|
||||
});
|
||||
|
@ -310,7 +319,7 @@ MongoDB.prototype.stream = function(options, stream) {
|
|||
}
|
||||
|
||||
if (start != null) {
|
||||
this.mainDb.collection(this.collection, function(err, col) {
|
||||
this.logDb.collection(this.collection, function(err, col) {
|
||||
if (err) {
|
||||
stream.emit('error', err);
|
||||
return;
|
||||
|
@ -334,7 +343,7 @@ MongoDB.prototype.stream = function(options, stream) {
|
|||
return stream;
|
||||
}
|
||||
|
||||
this.mainDb.collection(this.collection, function(err, col) {
|
||||
this.logDb.collection(this.collection, function(err, col) {
|
||||
if (err) {
|
||||
stream.emit('error', err);
|
||||
return;
|
||||
|
@ -387,8 +396,8 @@ MongoDB.prototype.streamPoll = function(options, stream) {
|
|||
var start = options.start;
|
||||
var last;
|
||||
|
||||
if (!this.mainDb) {
|
||||
this._opQuery.push({
|
||||
if (!this.logDb) {
|
||||
this._opQueue.push({
|
||||
method: 'streamPoll',
|
||||
args: [options, stream]
|
||||
});
|
||||
|
@ -408,7 +417,7 @@ MongoDB.prototype.streamPoll = function(options, stream) {
|
|||
};
|
||||
|
||||
(function check() {
|
||||
self.mainDb.collection(self.collection, function(err, col) {
|
||||
self.logDb.collection(self.collection, function(err, col) {
|
||||
if (err) {
|
||||
stream.emit('error', err);
|
||||
return;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "winston-mongodb",
|
||||
"license": "MIT",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"description": "A MongoDB transport for winston",
|
||||
"author": "Charlie Robbins <charlie.robbins@gmail.com>",
|
||||
"contributors": [
|
||||
|
@ -19,7 +19,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"winston": "0.9.x",
|
||||
"vows": "0.8.x"
|
||||
"vows": "0.8.x",
|
||||
"bluebird": "2.9.x"
|
||||
},
|
||||
"main": "./lib/winston-mongodb",
|
||||
"scripts": { "test": "vows test/*-test.js --spec" }
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
*/
|
||||
|
||||
var vows = require('vows');
|
||||
var mongodb = require('mongodb');
|
||||
var Promise = require('bluebird');
|
||||
var transport = require('winston/test/transports/transport');
|
||||
var MongoDB = require('../lib/winston-mongodb').MongoDB;
|
||||
|
||||
|
@ -14,10 +16,24 @@ vows.describe('winston-mongodb').addBatch({
|
|||
'An instance of the MongoDB Transport': transport(MongoDB, {
|
||||
db: 'mongodb://localhost/winston'
|
||||
}),
|
||||
'And instance of the MongoDB Transport on capped collection':
|
||||
'An instance of the MongoDB Transport on capped collection':
|
||||
transport(MongoDB, {
|
||||
db: 'mongodb://localhost/winston',
|
||||
capped: true,
|
||||
collection: 'cappedLogs'
|
||||
collection: 'cappedLog'
|
||||
})
|
||||
}).addBatch({
|
||||
'An instance of the MongoDB Transport with promise':
|
||||
transport(MongoDB, {
|
||||
db: new Promise(function(resolve, reject) {
|
||||
mongodb.MongoClient.connect('mongodb://localhost/winston',
|
||||
function(err, db) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(db);
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
}).export(module);
|
||||
|
|
Загрузка…
Ссылка в новой задаче