sails.js - How can I wrap sails-mongo db methods for profiling? -
i'm trying setup sails hook miniprofiler profile mongo usage. i'm struggling how wrap db methods in function execute profile. i'm trying via user hook:
setupminiprofilermongo(req, res, next) { const adapter = sails.hooks.orm.datastores.default.adapter; const adapterprototype = object.getprototypeof(adapter); const originalmethod = adapter.adapter.find; methodprototype.find = function profiledmongocommand(connectionname, collectionname, options, cb) { sails.log.info(`${collectionname}.find`); return originalmethod.call(adapter, connectionname, collectionname, options, cb); }; }
that causes following error thrown:
typeerror: cannot read property 'collections' of undefined @ object.module.exports.adapter.find (/users/jgeurts/dev/platform/node_modules/sails-mongo/lib/adapter.js:349:40) @ object.profiledmongocommand [as find] (/users/jgeurts/dev/platform/config/http.js:234:37)
any appreciated. tried wrap methods on mongodb package, doesn't seem work either. :/
i got working wrapping waterline query methods. there room improvement, though.
setupminiprofilerwaterline(req, res, next) { const dboperations = [ 'count', 'create', 'createeach', 'define', 'describe', 'destroy', 'drop', 'find', 'join', // 'native', // 'registerconnection', 'update', ]; const waterlinemethodbymodels = {}; const miniprofilerwaterline = () => { return { name: 'mongodb', handler(req, res, next) { if (!req.miniprofiler || !req.miniprofiler.enabled) { return next(); } const profiler = req.miniprofiler; (const modelname of _.keys(sails.models)) { (const dboperation of dboperations) { const model = sails.models[modelname]; if (!model[dboperation]) { continue; } if (!waterlinemethodbymodels[modelname]) { waterlinemethodbymodels[modelname] = {}; } // prevent wrapping method more once if (waterlinemethodbymodels[modelname][dboperation]) { continue; } waterlinemethodbymodels[modelname][dboperation] = true; const originalmethod = model[dboperation]; model[dboperation] = function profiledmongocommand(...args) { const query = args && args.length ? args[0] : ''; const lastarg = args && args.length ? args[args.length - 1] : null; const modelandmethod = `${modelname}.${dboperation}`; if (lastarg && typeof lastarg === 'function') { sails.log.debug(`mongo::${modelandmethod} - ${json.stringify(query)}`); const callback = args.pop(); const timing = profiler.starttimequery('mongodb', query ? json.stringify(query || '') : ''); // in general, callstack kind of useless these profiles // model/db method more useful in miniprofiler ui timing.callstack = `\n\nmethod: ${modelandmethod}`; return originalmethod.call(this, ...args, function profiledresult(...results) { profiler.stoptimequery(timing); callback(...results); }); } const methodresult = originalmethod.call(this, ...args); const methodresultprototype = object.getprototypeof(methodresult); const isdeferred = !!methodresultprototype.exec; // if methodresult deferred object type, query method profiled above when deferred executed (with callback) // care log if methodresult not deferred object if (!isdeferred) { sails.log.warn(`was not able profile mongo::${modelandmethod}. maybe promise? query: ${json.stringify(query)}`); } return methodresult; }; } } next(); }, }; }; miniprofiler.express.for(miniprofilerwaterline())(req, res, next); },
the code available miniprofiler-waterline if want contribute/use in own projects
Comments
Post a Comment