跟踪DB查询时间 - Bookshelf / knex

时间:2017-08-01 12:46:04

标签: mysql knex.js bookshelf.js

我想监控查询我的API数据库所花费的时间。我创建了以下函数,使用bookshelf-signals,一个Bookshelf插件。 :

    app.controller('savingsCtrl', ['$scope','tokenFactory','savingsFactory', function($scope,tokenFactory,savingsFactory){

      tokenFactory.getToken()

      .success(function(data) {
        $scope.token = data;
        var token=data.access_token;
        var userId='9c28735e-8a29-401d-b94e-6cc90a087d96';
        alert(token)
        $scope.getGoals=function(){

            savingsFactory.getGoals(userId,token).success(function(data) {
            $scope.goals = data;
                var goal=$scope.goals.goalName;
                alert(goal)
          });
        }
    }])

...这样我就可以在获取/计数之前和之后检索时间;删除已删除并保存已保存。

我认为我无法理解的是,当读取和取出时应该被触发...当我试图查看何时触发取出和取出时,基本上它最终得到了这个:

spark-shell -i script.scala

导致定时器错误地返回错误的值,你有任何线索/线索吗?

我还看到有人可以触发查询'关于Knex的事件,并考虑将其作为替代解决方案。但是,它似乎只有在我指定查询的表时才有效,即:

System.exit(0)

在我想在每个模型上应用事件处理程序的情况下使其变得不切实际...... 我想我应该坚持使用Bookshelf,但是如何处理事件的处理方式呢?

提前谢谢!

2 个答案:

答案 0 :(得分:1)

我刚刚写了一些小测试代码,如何使用knex跟踪事务持续时间。

https://runkit.com/embed/679qu91ylu4w

/**
 * Calculate transaction durations in knex
 * 
 */
require('sqlite3');
var knex = require("knex")({
  client: 'sqlite', 
  connection: ':memory:', 
  pool: { min: 1, max: 10 }
});

function isTransactionStart(querySpec) {
  return querySpec.sql === 'BEGIN;';
}

function isTransactionEnd(querySpec) {
  return querySpec.sql === 'COMMIT;' || querySpec.sql === 'ROLLBACK;';
}

const transactionDurations = {};

knex.on('query', querySpec => {
  console.log('On query', querySpec);

  if (isTransactionStart(querySpec)) {
    if (transactionDurations[querySpec.__knexUid]) {
      console.error('New transaction started, before earlier was ended');
      return;
    }
    transactionDurations[querySpec.__knexUid] = new Date().getTime();
  }

  if (isTransactionEnd(querySpec)) {
    const startTime = transactionDurations[querySpec.__knexUid];
    if (!startTime) {
      console.error('Transaction end detected, but start time not found');
    }
    const endTime = new Date().getTime();
    transactionDurations[querySpec.__knexUid] = null;
    console.log('TRANSACTION DURATION', endTime - startTime);
  }
}); 

// just as an example of other available events to show when they are called
knex.on('query-response', (res, querySpec) => {
  // console.log('On query response', res, querySpec);
}); 

knex.on('query-error', (err, querySpec) => {
  // console.log('On query error', err, querySpec);
}); 

try {
    a = await Promise.all([
      knex.transaction(trx => {
        return trx.raw('select 1');
      }),
      knex.transaction(trx => {
        return trx.raw('select 2');
      }),
      knex.transaction(trx => {
        return trx.raw('error me');
      })
    ]);
} catch (e) {
  console.log('Got ERROR:', e);
}

同样的方法之王也应该用于查询计时。为了防止计时器簿记泄漏内存,你应该添加一些清理代码。

查询持续时间计时器应该在query事件中启动,并在query-responsequery-error中停止,具体取决于哪一个首先触发。

可以使用匹配query - query-responsequerySpec.__knexQueryUid属性。

答案 1 :(得分:0)

根据MikaelLepistö片段,我想出了这个:

const dbEvents = (server, sdc) => {
  knex.on('query', data => {
    server.app[data.__knexQueryUid + ''] = new Date().valueOf();
  });

  knex.on('query-response', (data, obj, builder) => {
    sdc.counter('db_queries_time', new Date().valueOf() - server.app[obj.__knexQueryUid + '']);
    sdc.increment('nr_db_queries');
  });
};

然后我在启动服务器时调用该函数 - 我正在使用Hapijs。

编辑:sdc是一个statsd客户端,我用它来发送数据库时间:))