首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我如何包装sails-mongo db方法来进行性能分析?

我如何包装sails-mongo db方法来进行性能分析?
EN

Stack Overflow用户
提问于 2016-09-13 12:14:35
回答 1查看 126关注 0票数 0

我正在尝试用miniprofiler设置一个船帆钩子来帮助分析mongo的使用情况。我正在为如何将db方法包装在一个将执行概要文件的函数中而苦苦挣扎。我正在尝试通过一个用户钩子来实现这一点:

代码语言:javascript
复制
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);
  };
}

这会导致抛出以下错误:

代码语言:javascript
复制
TypeError: Cannot read property 'collections' of undefined
    at Object.module.exports.adapter.find (/Users/jgeurts/dev/platform/node_modules/sails-mongo/lib/adapter.js:349:40)
    at Object.profiledMongoCommand [as find] (/Users/jgeurts/dev/platform/config/http.js:234:37)

任何帮助都将不胜感激。我试图将方法包装在mongodb包中,但似乎也不起作用。:/

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-15 11:24:38

我通过包装waterline查询方法实现了这一点。不过,还有改进的空间。

代码语言:javascript
复制
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;

        for (const modelName of _.keys(sails.models)) {
          for (const dbOperation of dbOperations) {
            const model = sails.models[modelName];
            if (!model[dbOperation]) {
              continue;
            }

            if (!waterlineMethodByModels[modelName]) {
              waterlineMethodByModels[modelName] = {};
            }

            // Prevent wrapping a method more than 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, the callstack is kind of useless to us for these profiles
                // The model/db method is more useful in the 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 is a Deferred object type, then the query method will be profiled above when the deferred is executed (with a callback)
              // So we only care to log this if the methodResult is not a deferred object
              if (!isDeferred) {
                sails.log.warn(`Was not able to profile mongo::${modelAndMethod}. Maybe its a promise? query: ${JSON.stringify(query)}`);
              }

              return methodResult;
            };
          }
        }

        next();
      },
    };
  };

  miniprofiler.express.for(miniprofilerWaterline())(req, res, next);
},

如果您想在自己的项目中贡献/使用代码,可以使用miniprofiler-waterline格式的代码

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39462132

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档