Skip to content

Commit 3747ccf

Browse files
committed
[refactor] Make some performance optimizations for Logger.prototype.log.
1 parent 0d955d3 commit 3747ccf

File tree

1 file changed

+61
-38
lines changed

1 file changed

+61
-38
lines changed

lib/winston/logger.js

+61-38
Original file line numberDiff line numberDiff line change
@@ -104,22 +104,27 @@ Logger.prototype.configure = function (options) {
104104
// Core logging method exposed to Winston. Metadata is optional.
105105
//
106106
Logger.prototype.log = function (level) {
107-
var self = this,
108-
args = Array.prototype.slice.call(arguments, 1);
107+
var args = Array.prototype.slice.call(arguments, 1),
108+
self = this,
109+
transports;
109110

110-
while(args[args.length - 1] === null) {
111+
while (args[args.length - 1] === null) {
111112
args.pop();
112113
}
113114

115+
//
116+
// Determining what is `meta` and what are arguments for string interpolation
117+
// turns out to be VERY tricky. e.g. in the cases like this:
118+
//
119+
// logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' });
120+
//
114121
var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null,
115122
meta = typeof args[args.length - 1] === 'object' && Object.prototype.toString.call(args[args.length - 1]) !== '[object RegExp]' ? args.pop() : {},
116123
msg = util.format.apply(null, args);
117124

118-
// If we should pad for levels, do so
119-
if (this.padLevels) {
120-
msg = new Array(this.levelLength - level.length + 1).join(' ') + msg;
121-
}
122-
125+
//
126+
// Handle errors appropriately.
127+
//
123128
function onError(err) {
124129
if (callback) {
125130
callback(err);
@@ -129,13 +134,49 @@ Logger.prototype.log = function (level) {
129134
}
130135
}
131136

132-
if (Object.keys(this.transports).length === 0) {
137+
if (this._names.length === 0) {
133138
return onError(new Error('Cannot log with no transports.'));
134139
}
135140
else if (typeof self.levels[level] === 'undefined') {
136141
return onError(new Error('Unknown log level: ' + level));
137142
}
138143

144+
//
145+
// If there are no transports that match the level
146+
// then be eager and return. This could potentially be calculated
147+
// during `setLevels` for more performance gains.
148+
//
149+
var targets = this._names.filter(function (name) {
150+
var transport = self.transports[name];
151+
return (transport.level && self.levels[transport.level] >= self.levels[level])
152+
|| (!transport.level && self.levels[self.level] >= self.levels[level]);
153+
});
154+
155+
if (!targets.length) {
156+
if (callback) { callback(); }
157+
return;
158+
}
159+
160+
//
161+
// Respond to the callback.
162+
//
163+
function finish(err) {
164+
if (callback) {
165+
if (err) return callback(err);
166+
callback(null, level, msg, meta);
167+
}
168+
169+
callback = null;
170+
if (!err) {
171+
self.emit('logged', level, msg, meta);
172+
}
173+
}
174+
175+
// If we should pad for levels, do so
176+
if (this.padLevels) {
177+
msg = new Array(this.levelLength - level.length + 1).join(' ') + msg;
178+
}
179+
139180
this.rewriters.forEach(function (rewriter) {
140181
meta = rewriter(level, msg, meta, self);
141182
});
@@ -165,39 +206,21 @@ Logger.prototype.log = function (level) {
165206
//
166207
// Log for each transport and emit 'logging' event
167208
//
168-
function emit(name, next) {
209+
function transportLog(name, next) {
169210
var transport = self.transports[name];
170-
if ((transport.level && self.levels[transport.level] >= self.levels[level])
171-
|| (!transport.level && self.levels[self.level] >= self.levels[level])) {
172-
transport.log(level, msg, meta, function (err) {
173-
if (err) {
174-
err.transport = transport;
175-
cb(err);
176-
return next();
177-
}
178-
self.emit('logging', transport, level, msg, meta);
179-
next();
180-
});
181-
} else {
182-
next();
183-
}
184-
}
211+
transport.log(level, msg, meta, function (err) {
212+
if (err) {
213+
err.transport = transport;
214+
finish(err);
215+
return next();
216+
}
185217

186-
//
187-
// Respond to the callback
188-
//
189-
function cb(err) {
190-
if (callback) {
191-
if (err) return callback(err);
192-
callback(null, level, msg, meta);
193-
}
194-
callback = null;
195-
if (!err) {
196-
self.emit('logged', level, msg, meta);
197-
}
218+
self.emit('logging', transport, level, msg, meta);
219+
next();
220+
});
198221
}
199222

200-
async.forEach(this._names, emit, cb);
223+
async.forEach(targets, transportLog, finish);
201224
return this;
202225
};
203226

0 commit comments

Comments
 (0)