Skip to content

Commit e31d840

Browse files
committed
refactor(logger): non-debug query profiling
Use less precise query profiling (script based, rather than sql server based). Re-enables slow query warning, and reduces overhead when ui is enabled.
1 parent d0683b7 commit e31d840

File tree

4 files changed

+30
-14
lines changed

4 files changed

+30
-14
lines changed

src/database/rawExecute.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { logError, profileBatchStatements, runProfiler } from '../logger';
1+
import { logError, logQuery, profileBatchStatements, runProfiler } from '../logger';
22
import { CFXCallback, CFXParameters, QueryType } from '../types';
33
import { parseResponse } from '../utils/parseResponse';
44
import { executeType, parseExecute } from '../utils/parseExecute';
55
import { getPoolConnection } from './connection';
66
import { setCallback } from '../utils/setCallback';
7+
import { performance } from 'perf_hooks';
78

89
export const rawExecute = async (
910
invokingResource: string,
@@ -44,6 +45,7 @@ export const rawExecute = async (
4445
}
4546
}
4647

48+
const startTime = !hasProfiler && performance.now();
4749
const [result] = await connection.execute(query, values);
4850

4951
if (cb) {
@@ -56,6 +58,8 @@ export const rawExecute = async (
5658

5759
if (hasProfiler && ((index > 0 && index % 100 === 0) || index === parametersLength - 1)) {
5860
await profileBatchStatements(connection, invokingResource, query, parameters, index < 100 ? 0 : index);
61+
} else if (startTime) {
62+
logQuery(invokingResource, query, performance.now() - startTime, values);
5963
}
6064
}
6165

src/database/rawQuery.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { CFXCallback, CFXParameters } from '../types';
66
import type { QueryType } from '../types';
77
import { getPoolConnection } from './connection';
88
import { RowDataPacket } from 'mysql2';
9+
import { performance } from 'perf_hooks';
910

1011
export const rawQuery = async (
1112
type: QueryType,
@@ -28,14 +29,17 @@ export const rawQuery = async (
2829

2930
try {
3031
const hasProfiler = await runProfiler(connection, invokingResource);
32+
const startTime = !hasProfiler && performance.now();
3133
const [result] = await connection.query(query, parameters);
3234

3335
if (hasProfiler) {
3436
const [profiler] = <RowDataPacket[]>(
3537
await connection.query('SELECT FORMAT(SUM(DURATION) * 1000, 4) AS `duration` FROM INFORMATION_SCHEMA.PROFILING')
3638
);
3739

38-
if (profiler[0]) logQuery(invokingResource, query, profiler[0].duration, parameters);
40+
if (profiler[0]) logQuery(invokingResource, query, parseFloat(profiler[0].duration), parameters);
41+
} else if (startTime) {
42+
logQuery(invokingResource, query, performance.now() - startTime, parameters);
3943
}
4044

4145
if (cb)

src/database/rawTransaction.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { getPoolConnection } from './connection';
2-
import { logError, profileBatchStatements, runProfiler } from '../logger';
2+
import { logError, logQuery, profileBatchStatements, runProfiler } from '../logger';
33
import { CFXCallback, CFXParameters, TransactionQuery } from '../types';
44
import { parseTransaction } from '../utils/parseTransaction';
55
import { setCallback } from '../utils/setCallback';
6+
import { performance } from 'perf_hooks';
67

78
const transactionError = (queries: { query: string; params?: CFXParameters }[], parameters: CFXParameters) => {
89
`${queries.map((query) => `${query.query} ${JSON.stringify(query.params || [])}`).join('\n')}\n${JSON.stringify(
@@ -39,11 +40,13 @@ export const rawTransaction = async (
3940

4041
for (let i = 0; i < transactionsLength; i++) {
4142
const transaction = transactions[i];
42-
43+
const startTime = !hasProfiler && performance.now();
4344
await connection.query(transaction.query, transaction.params);
4445

4546
if (hasProfiler && ((i > 0 && i % 100 === 0) || i === transactionsLength - 1)) {
4647
await profileBatchStatements(connection, invokingResource, transactions, null, i < 100 ? 0 : i);
48+
} else if (startTime) {
49+
logQuery(invokingResource, transaction.query, performance.now() - startTime, transaction.params);
4750
}
4851
}
4952

src/logger/index.ts

+15-10
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ export function logError(
1010
err: any,
1111
query?: string,
1212
parameters?: CFXParameters,
13-
includeParameters?: boolean,
13+
includeParameters?: boolean
1414
) {
15-
const message = `${invokingResource} was unable to execute a query!${query ? `\n${`Query: ${query}`}` : ''}${includeParameters ? `\n${JSON.stringify(parameters)}` : ''}\n${err.message}`;
15+
const message = `${invokingResource} was unable to execute a query!${query ? `\n${`Query: ${query}`}` : ''}${
16+
includeParameters ? `\n${JSON.stringify(parameters)}` : ''
17+
}\n${err.message}`;
1618

1719
TriggerEvent('oxmysql:error', {
1820
query: query,
@@ -34,9 +36,13 @@ export const profilerStatements = [
3436
'SET profiling = 1',
3537
];
3638

39+
/**
40+
* Executes MySQL queries to fetch accurate query profiling results when `mysql_debug` is enabled.
41+
*/
3742
export async function runProfiler(connection: PoolConnection, invokingResource: string) {
38-
if (!mysql_debug && !mysql_ui) return;
39-
if (!mysql_ui && mysql_debug && Array.isArray(mysql_debug) && !mysql_debug.includes(invokingResource)) return;
43+
if (!mysql_debug) return;
44+
45+
if (Array.isArray(mysql_debug) && !mysql_debug.includes(invokingResource)) return;
4046

4147
for (const statement of profilerStatements) await connection.query(statement);
4248

@@ -62,12 +68,13 @@ export async function profileBatchStatements(
6268

6369
if (typeof query === 'string' && parameters)
6470
for (let i = 0; i < profiler.length; i++) {
65-
logQuery(invokingResource, query, profiler[i].duration, parameters[offset + i]);
71+
logQuery(invokingResource, query, parseFloat(profiler[i].duration), parameters[offset + i]);
6672
}
6773
else if (typeof query === 'object')
6874
for (let i = 0; i < profiler.length; i++) {
6975
const transaction = query[offset + i];
70-
if (transaction) logQuery(invokingResource, transaction.query, profiler[i].duration, transaction.params);
76+
if (transaction)
77+
logQuery(invokingResource, transaction.query, parseFloat(profiler[i].duration), transaction.params);
7178
else break;
7279
}
7380
}
@@ -86,17 +93,15 @@ const logStorage: QueryLog = {};
8693
export const logQuery = (
8794
invokingResource: string,
8895
query: string,
89-
executionTime: string | number,
96+
executionTime: number,
9097
parameters?: CFXParameters
9198
) => {
92-
executionTime = parseFloat(executionTime as string);
93-
9499
if (
95100
executionTime >= mysql_slow_query_warning ||
96101
(mysql_debug && (!Array.isArray(mysql_debug) || mysql_debug.includes(invokingResource)))
97102
) {
98103
console.log(
99-
`${dbVersion} ^3${invokingResource} took ${executionTime}ms to execute a query!\n${query}${
104+
`${dbVersion} ^3${invokingResource} took ${executionTime.toFixed(4)}ms to execute a query!\n${query}${
100105
parameters ? ` ${JSON.stringify(parameters)}` : ''
101106
}^0`
102107
);

0 commit comments

Comments
 (0)