2016-09-13 3 views
0

私はminiprofilerでセイルフックを設定しようとしています。私は、プロファイルを実行する関数にdbメソッドをラップする方法については苦労しています。プロファイリングのためにsails-mongo dbメソッドをラップする方法はありますか?

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); 
    }; 
} 

次のエラーがスローされます:

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パッケージにメソッドをラップしようとしましたが、どちらもうまくいかないようです。 :/

+0

がどの層ではあなたがプロファイラフックしたいですか、あなた自身のプロジェクトでそれを使用miniprofiler-waterlineとして利用できますか?私はそれがあなたがアプリケーションレベルかセイルモンゴーかネイティブモンゴーnodejsドライバーの中でさえ繋がっても違いがあると思います。そして、あなたのエラーは未定義のコレクションをセーリングしますが、あなたが提供したコードにはコレクションの使用法はありません。 –

+0

@zabwareこの必要性のために、私がセイル・モンゴーまたはネイティブ・モンゴーにフックしているならば、私は無関心です。私は主に、クエリーがどれくらいの時間を要したのか、また、水路が結果を解析するのに要した時間を減らすことを追求しています。 'collections'オブジェクトは、アダプタクロージャの内部で定義されています。残念ながら、簡単なアクセサーを持たないようです。 –

+0

生のmongodb呼び出しをプロファイルすることができれば理想的です。これは、ネイティブクエリーが使用されている場合と、水線構文が使用されている場合を考慮します。水線オブジェクトグラフを介してmongodbアダプターのインスタンスを取得することは私には分かりませんが –

答えて

1

私はウォーターラインのクエリメソッドをラップすることでこれを実現しました。しかし、改善の余地がある。

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); 
}, 

コードは、あなたが貢献したい場合は/

関連する問題