跟踪数据库查询时间 - Bookshelf/knex
Tracking DB querying time - Bookshelf/knex
我想监控 API 的数据库上的查询所用的时间。我使用 Bookshelf 插件 bookshelf-signals 创建了以下函数。 :
bookshelf.on('fetching', () => {
server.app.fetching = new Date().valueOf();
});
bookshelf.on('counting', () => {
server.app.fetching = new Date().valueOf();
});
bookshelf.on('fetched', () => {
server.statsd.gauge('db_query', new Date().valueOf() - server.app.fetching);
});
... 这样我就可以检索 fetch/count 之前和之后的时间;我对删除-删除和保存-保存做了同样的事情。
我想我无法理解的是什么时候应该触发获取和获取...当我试图查看何时触发获取和获取时,基本上它以这个结束:
'fetching event A'
'fetching event B'
'fetching event C'
'fetched event C'
'fetched event B'
'fetched event A'
导致定时器不知不觉地返回错误值,你有没有lead/clue?
我还看到有人可以在 Knex 上触发 'query' 事件,并想到将其用作替代解决方案。但是,它似乎只有在我指定查询的 table 时才有效,即:
knex('whatever_table').on('query', () => {///});
在我想在每个模型上应用事件处理程序的情况下变得不切实际...
我认为我应该坚持使用 Bookshelf,但是我该如何处理事件的处理方式呢?
提前致谢!
我刚刚写了一些小测试代码如何使用 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-response
或 query-error
中停止,具体取决于哪个先触发。
为了能够匹配 query
- query-response
对 querySpec.__knexQueryUid
属性可以使用。
基于 Mikael Lepistö 片段我想到了这个:
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 客户端,我用它来发送数据库时间 :)
我想监控 API 的数据库上的查询所用的时间。我使用 Bookshelf 插件 bookshelf-signals 创建了以下函数。 :
bookshelf.on('fetching', () => {
server.app.fetching = new Date().valueOf();
});
bookshelf.on('counting', () => {
server.app.fetching = new Date().valueOf();
});
bookshelf.on('fetched', () => {
server.statsd.gauge('db_query', new Date().valueOf() - server.app.fetching);
});
... 这样我就可以检索 fetch/count 之前和之后的时间;我对删除-删除和保存-保存做了同样的事情。
我想我无法理解的是什么时候应该触发获取和获取...当我试图查看何时触发获取和获取时,基本上它以这个结束:
'fetching event A'
'fetching event B'
'fetching event C'
'fetched event C'
'fetched event B'
'fetched event A'
导致定时器不知不觉地返回错误值,你有没有lead/clue?
我还看到有人可以在 Knex 上触发 'query' 事件,并想到将其用作替代解决方案。但是,它似乎只有在我指定查询的 table 时才有效,即:
knex('whatever_table').on('query', () => {///});
在我想在每个模型上应用事件处理程序的情况下变得不切实际... 我认为我应该坚持使用 Bookshelf,但是我该如何处理事件的处理方式呢?
提前致谢!
我刚刚写了一些小测试代码如何使用 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-response
或 query-error
中停止,具体取决于哪个先触发。
为了能够匹配 query
- query-response
对 querySpec.__knexQueryUid
属性可以使用。
基于 Mikael Lepistö 片段我想到了这个:
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 客户端,我用它来发送数据库时间 :)