Compare commits

..

5 Commits

Author SHA1 Message Date
Rahul Padigela e8f924be64 remove arguments usage 2016-04-28 21:10:17 -07:00
Rahul Padigela 081d94ac1e add v8 optimization [ci skip] 2016-04-28 20:34:59 -07:00
Rahul Padigela 9eed64874d FT: add time field
Normally node-bunyan automatically adds this field if it's omitted,
but it uses lodash to generate the timestamp, which in turn uses
a costly regex to figure out if the date method is available in an
env. That particular call was consuming a lot of cpu ticks, sitting
up top on the profiler log.
2016-04-28 19:46:31 -07:00
Rahul Padigela ba5ca5f6a1 perf: remove hrtime field
Stringifying hrtime proved to be expensive as it was consuming a
lot of cpu ticks in the profiler log.
2016-04-28 19:44:47 -07:00
Rahul Padigela b891f48e30 perf: replace Object.assign with vanilla looping
Object.assign is currently not very performant, replacing it with
standard looping.
2016-04-28 19:44:18 -07:00
3 changed files with 62 additions and 13 deletions

View File

@ -6,6 +6,7 @@ const LogLevel = require('./LogLevel.js');
const Utils = require('./Utils.js'); const Utils = require('./Utils.js');
const serializeUids = Utils.serializeUids; const serializeUids = Utils.serializeUids;
const generateUid = Utils.generateUid; const generateUid = Utils.generateUid;
const objectCopy = Utils.objectCopy;
function ensureUidValidity(uid) { function ensureUidValidity(uid) {
if (uid.indexOf(':') !== -1) { if (uid.indexOf(':') !== -1) {
@ -26,7 +27,7 @@ class EndLogger {
+ ' once.'); + ' once.');
// We can alter current instance, as it won't be usable after this // We can alter current instance, as it won't be usable after this
// call. // call.
this.fields = Object.assign(this.fields, data || {}); this.fields = objectCopy(this.fields, data || {});
return this.logger.log(level, msg, this.fields, true); return this.logger.log(level, msg, this.fields, true);
} }
@ -45,7 +46,7 @@ class EndLogger {
*/ */
addDefaultFields(fields) { addDefaultFields(fields) {
const oldFields = this.fields; const oldFields = this.fields;
this.fields = Object.assign({}, this.fields, fields); this.fields = objectCopy({}, this.fields, fields);
return oldFields; return oldFields;
} }
@ -248,7 +249,7 @@ class RequestLogger {
*/ */
addDefaultFields(fields) { addDefaultFields(fields) {
const oldFields = this.fields; const oldFields = this.fields;
this.fields = Object.assign({}, this.fields, fields); this.fields = objectCopy({}, this.fields, fields);
return oldFields; return oldFields;
} }
@ -433,17 +434,16 @@ class RequestLogger {
}); });
return; return;
} }
const fields = Object.assign({}, logFields || {}); const fields = objectCopy({}, logFields || {});
const endFlag = isEnd || false; const endFlag = isEnd || false;
const hr = process.hrtime();
/* /*
* Here, Stringify hrtime for it to stay within a one-liner when piping * Even though this is added automatically by bunyan, it uses an
* the output through bunyan's cli tool. * expensive regex to figure out the native Date function. By adding
* Then prepend the fields to the argument Array we're preparing for * timestamp here avoids that expensive call.
* bunyan
*/ */
fields.hrtime = JSON.stringify(hr); if (fields.time === undefined) {
fields.time = new Date();
}
fields.req_id = serializeUids(this.uids); fields.req_id = serializeUids(this.uids);
if (endFlag) { if (endFlag) {
this.elapsedTime = process.hrtime(this.startTime); this.elapsedTime = process.hrtime(this.startTime);
@ -483,7 +483,7 @@ class RequestLogger {
* @returns {undefined} * @returns {undefined}
*/ */
doLogIO(logEntry) { doLogIO(logEntry) {
const fields = Object.assign({}, this.fields, logEntry.fields); const fields = objectCopy({}, this.fields, logEntry.fields);
switch (logEntry.level) { switch (logEntry.level) {
case 'trace': case 'trace':

View File

@ -40,8 +40,34 @@ function unserializeUids(stringdata) {
return stringdata.split(':'); return stringdata.split(':');
} }
/**
* This function copies the properties from the source object to the target object
* @param {...object} target - object to be copied to
* @returns {object} - target object
*/
function objectCopy(target, source1, source2) {
const result = target;
if (source1) {
Object.keys(source1).forEach( f => result[f] = source1[f]);
}
if (source2) {
Object.keys(source2).forEach( f => result[f] = source2[f]);
}
// let source;
// function copy(f) {
// result[f] = source[f];
// }
// for (let i = 1; i < arguments.length; i++) {
// source = arguments[i];
// Object.keys(source).forEach(copy);
// }
return result;
}
module.exports = { module.exports = {
generateUid, generateUid,
serializeUids, serializeUids,
unserializeUids, unserializeUids,
objectCopy,
}; };

View File

@ -5,6 +5,7 @@ const Utils = require('../../lib/Utils.js');
const generateUid = Utils.generateUid; const generateUid = Utils.generateUid;
const serializeUids = Utils.serializeUids; const serializeUids = Utils.serializeUids;
const unserializeUids = Utils.unserializeUids; const unserializeUids = Utils.unserializeUids;
const objectCopy = Utils.objectCopy;
describe('Utils: generateUid', () => { describe('Utils: generateUid', () => {
it('generates a string-typed ID', (done) => { it('generates a string-typed ID', (done) => {
@ -42,3 +43,25 @@ describe('Utils: serializeUids', () => {
done(); done();
}); });
}); });
describe('Utils: objectCopy', () => {
it('copies all the properties from source to target object', (done) => {
const target = { foo: 'bar' };
const source = { id: 1, name: 'demo', value: { a: 1, b: 2, c: 3 } };
const result = { foo: 'bar', id: 1, name: 'demo', value: { a: 1, b: 2, c: 3 } };
objectCopy(target, source);
assert.deepStrictEqual(target, result, 'target should have the same properties as source');
done();
});
it('copies all the properties from multiple sources to target object', (done) => {
const target = { foo: 'bar' };
const source1 = { id: 1, name: 'demo1', value: { a: 1, b: 2, c: 3 } };
const source2 = { req_id: 2, method: 'test', err: { code: 'error', msg: 'test' } };
const result = { foo: 'bar', id: 1, name: 'demo1', value: { a: 1, b: 2, c: 3 },
req_id: 2, method: 'test', err: { code: 'error', msg: 'test' }};
objectCopy(target, source1, source2);
assert.deepStrictEqual(target, result, 'target should have the same properties as source');
done();
});
});