Tracking DB querying time - Bookshelf/knex

ぃ、小莉子 提交于 2019-12-01 12:38:35

I just wrote some small test code how to trace transaction duration with 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);
}

The same king of approach should work also for query timing. To prevent timer bookkeeping from leaking memory you should add some cleanup code though.

Query duration timer should be started in query event and stopped in query-response or query-error depending which one triggers first.

To be able to match query - query-response pair querySpec.__knexQueryUid attribute can be used.

Based on Mikael Lepistö snippet I came up with this :

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

And I then call the function when I start the server - I am working with Hapijs.

EDIT: sdc is a statsd client, I use it to send the DB time :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!