Skip to content

Commit ccf69f6

Browse files
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).
1 parent 7a7b98e commit ccf69f6

File tree

4 files changed

+80
-43
lines changed

4 files changed

+80
-43
lines changed

README.md

+14-3
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ The MongoDB transport takes the following options. 'db' is required:
3434
'info'.
3535
* __silent:__ Boolean flag indicating whether to suppress output, defaults to
3636
false.
37-
* __db:__ MongoDB connection uri or preconnected db object.
37+
* __db:__ MongoDB connection uri, pre-connected db object or promise object
38+
which will be resolved with pre-connected db object.
3839
* __options:__ MongoDB connection parameters (optional, defaults to
3940
`{db: {native_parser: true}, server: {poolSize: 2, socketOptions: {autoReconnect: true}}}`).
4041
* __collection__: The name of the collection you want to store log messages in,
41-
defaults to 'logs'.
42+
defaults to 'log'.
4243
* __storeHost:__ Boolean indicating if you want to store machine hostname in
4344
logs entry, if set to true it populates MongoDB entry with 'hostname' field,
4445
which stores os.hostname() value.
@@ -74,11 +75,21 @@ settled by mongodb, defaults to `false`.
7475

7576
## Changelog
7677

78+
### Brief 1.1.0 changelog
79+
80+
* added support of passing promises objects which will be resolved with
81+
pre-connected db object in options.db;
82+
* fixed issue when events logged sometime between authorizeDb and
83+
processOpQuery calls may be lost;
84+
* renamed default log collection to 'log' because it makes more sense than
85+
'logs' ('log' is a list of messages already, plural form would imply
86+
multiple of such lists).
87+
7788
### Brief 1.0.0 changelog
7889

7990
* migrated to mongodb 2.x driver;
8091
* changed configuration format to MongoDB uri string;
81-
* added support of passing preconnected db object instead of MongoDB uri string;
92+
* added support of passing pre-connected db object instead of MongoDB uri string;
8293
* added support of passing MongoDB connection parameters in options property;
8394
* added support of replica sets through new options and db properties;
8495
* migrated to [Semantic Versioning](http://semver.org/) in package versions names;

lib/winston-mongodb.js

+45-36
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ var MongoDB = exports.MongoDB = function(options) {
6363
}
6464
};
6565
}
66-
this.collection = (options.collection || 'logs');
66+
this.collection = (options.collection || 'log');
6767
this.level = (options.level || 'info');
6868
this.silent = options.silent;
6969
this.username = options.username;
@@ -77,47 +77,55 @@ var MongoDB = exports.MongoDB = function(options) {
7777
this.hostname = os.hostname();
7878
}
7979

80-
81-
this._opQuery = [];
80+
this._opQueue = [];
8281

8382
var self = this;
8483

85-
function processOpQuery() {
86-
self._opQuery.forEach(function(operation) {
84+
function setupDatabaseAndEmptyQueue(db) {
85+
authorizeDb(db, function(err, db) {
86+
createCollection(db, function(err, db) {
87+
self.logDb = db;
88+
processOpQueue();
89+
});
90+
});
91+
}
92+
93+
function processOpQueue() {
94+
self._opQueue.forEach(function(operation) {
8795
self[operation.method].apply(self, operation.args);
8896
});
89-
delete self._opQuery;
97+
delete self._opQueue;
9098
}
9199

92-
function createCollection(cb) {
100+
function createCollection(db, cb) {
93101
var opts = {};
94102
if (self.capped) {
95103
opts = {capped: true, size: self.cappedSize};
96104
}
97-
self.mainDb.createCollection(self.collection, opts, function() {
98-
cb(null);
105+
db.createCollection(self.collection, opts, function() {
106+
cb(null, db);
99107
});
100108
}
101109

102-
function authorizeDb(cb) {
110+
function authorizeDb(db, cb) {
103111
if (self.username && self.password) {
104-
self.mainDb.authenticate(self.username, self.password,
112+
db.authenticate(self.username, self.password,
105113
function(err, result) {
106114
if (err) {
107115
console.error('winston-mongodb: error initialising logger', err);
108-
self.mainDb.close();
116+
db.close();
109117
return;
110118
}
111119
if (!result) {
112120
console.error('winston-mongodb: invalid username or password');
113-
self.mainDb.close();
121+
db.close();
114122
return;
115123
}
116-
cb(null);
124+
cb(null, db);
117125
}
118126
);
119127
}
120-
cb(null);
128+
cb(null, db);
121129
}
122130

123131
if ('string' === typeof this.db) {
@@ -126,16 +134,17 @@ var MongoDB = exports.MongoDB = function(options) {
126134
console.error('winston-mongodb: error initialising logger', err);
127135
return;
128136
}
129-
self.mainDb = db;
130-
authorizeDb(function() {
131-
createCollection(processOpQuery);
132-
});
137+
setupDatabaseAndEmptyQueue(db);
133138
});
134-
} else {
135-
this.mainDb = this.db;
136-
authorizeDb(function() {
137-
createCollection(processOpQuery);
139+
} else if ('function' === typeof this.db.then) {
140+
this.db.then(function(db) {
141+
setupDatabaseAndEmptyQueue(db);
142+
}, function(err) {
143+
console.error(
144+
'winston-mongodb: error initialising logger from promise', err);
138145
});
146+
} else {
147+
setupDatabaseAndEmptyQueue(this.db);
139148
}
140149
};
141150

@@ -161,8 +170,8 @@ winston.transports.MongoDB = MongoDB;
161170
* @param {Function} callback Continuation to respond to when complete.
162171
*/
163172
MongoDB.prototype.log = function(level, msg, opt_meta, callback) {
164-
if (!this.mainDb) {
165-
this._opQuery.push({
173+
if (!this.logDb) {
174+
this._opQueue.push({
166175
method: 'log',
167176
args: arguments
168177
});
@@ -186,7 +195,7 @@ MongoDB.prototype.log = function(level, msg, opt_meta, callback) {
186195
callback(err, null);
187196
}
188197

189-
self.mainDb.collection(self.collection, function(err, col) {
198+
self.logDb.collection(self.collection, function(err, col) {
190199
if (err) {
191200
onError(err);
192201
return;
@@ -225,8 +234,8 @@ MongoDB.prototype.log = function(level, msg, opt_meta, callback) {
225234
* @return {*}
226235
*/
227236
MongoDB.prototype.query = function(opt_options, callback) {
228-
if (!this.mainDb) {
229-
this._opQuery.push({
237+
if (!this.logDb) {
238+
this._opQueue.push({
230239
method: 'query',
231240
args: arguments
232241
});
@@ -257,7 +266,7 @@ MongoDB.prototype.query = function(opt_options, callback) {
257266
opt.fields = options.fields;
258267
}
259268

260-
this.mainDb.collection(this.collection, function(err, col) {
269+
this.logDb.collection(this.collection, function(err, col) {
261270
if (err) {
262271
callback(err);
263272
return;
@@ -293,8 +302,8 @@ MongoDB.prototype.stream = function(options, stream) {
293302
var self = this;
294303
var start = options.start;
295304

296-
if (!this.mainDb) {
297-
this._opQuery.push({
305+
if (!this.logDb) {
306+
this._opQueue.push({
298307
method: 'stream',
299308
args: [options, stream]
300309
});
@@ -310,7 +319,7 @@ MongoDB.prototype.stream = function(options, stream) {
310319
}
311320

312321
if (start != null) {
313-
this.mainDb.collection(this.collection, function(err, col) {
322+
this.logDb.collection(this.collection, function(err, col) {
314323
if (err) {
315324
stream.emit('error', err);
316325
return;
@@ -334,7 +343,7 @@ MongoDB.prototype.stream = function(options, stream) {
334343
return stream;
335344
}
336345

337-
this.mainDb.collection(this.collection, function(err, col) {
346+
this.logDb.collection(this.collection, function(err, col) {
338347
if (err) {
339348
stream.emit('error', err);
340349
return;
@@ -387,8 +396,8 @@ MongoDB.prototype.streamPoll = function(options, stream) {
387396
var start = options.start;
388397
var last;
389398

390-
if (!this.mainDb) {
391-
this._opQuery.push({
399+
if (!this.logDb) {
400+
this._opQueue.push({
392401
method: 'streamPoll',
393402
args: [options, stream]
394403
});
@@ -408,7 +417,7 @@ MongoDB.prototype.streamPoll = function(options, stream) {
408417
};
409418

410419
(function check() {
411-
self.mainDb.collection(self.collection, function(err, col) {
420+
self.logDb.collection(self.collection, function(err, col) {
412421
if (err) {
413422
stream.emit('error', err);
414423
return;

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "winston-mongodb",
33
"license": "MIT",
4-
"version": "1.0.1",
4+
"version": "1.1.0",
55
"description": "A MongoDB transport for winston",
66
"author": "Charlie Robbins <[email protected]>",
77
"contributors": [
@@ -19,7 +19,8 @@
1919
},
2020
"devDependencies": {
2121
"winston": "0.9.x",
22-
"vows": "0.8.x"
22+
"vows": "0.8.x",
23+
"bluebird": "2.9.x"
2324
},
2425
"main": "./lib/winston-mongodb",
2526
"scripts": { "test": "vows test/*-test.js --spec" }

test/winston-mongodb-test.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,33 @@
77
*/
88

99
var vows = require('vows');
10+
var mongodb = require('mongodb');
11+
var Promise = require('bluebird');
1012
var transport = require('winston/test/transports/transport');
1113
var MongoDB = require('../lib/winston-mongodb').MongoDB;
1214

1315
vows.describe('winston-mongodb').addBatch({
1416
'An instance of the MongoDB Transport': transport(MongoDB, {
1517
db: 'mongodb://localhost/winston'
1618
}),
17-
'And instance of the MongoDB Transport on capped collection':
19+
'An instance of the MongoDB Transport on capped collection':
1820
transport(MongoDB, {
1921
db: 'mongodb://localhost/winston',
2022
capped: true,
21-
collection: 'cappedLogs'
23+
collection: 'cappedLog'
24+
})
25+
}).addBatch({
26+
'An instance of the MongoDB Transport with promise':
27+
transport(MongoDB, {
28+
db: new Promise(function(resolve, reject) {
29+
mongodb.MongoClient.connect('mongodb://localhost/winston',
30+
function(err, db) {
31+
if (err) {
32+
reject(err);
33+
} else {
34+
resolve(db);
35+
}
36+
});
37+
})
2238
})
2339
}).export(module);

0 commit comments

Comments
 (0)