Log query stats during backup import

This commit is contained in:
trevor-signal 2024-10-28 13:11:19 -04:00 committed by GitHub
parent 251ffc289f
commit f5a170818b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 44 additions and 10 deletions

View file

@ -1066,6 +1066,14 @@ ipc.on('show-window', () => {
showWindow(); showWindow();
}); });
ipc.on('start-tracking-query-stats', () => {
sql.startTrackingQueryStats();
});
ipc.on('stop-tracking-query-stats', (_event, options) => {
sql.stopTrackingQueryStats(options);
});
ipc.on('title-bar-double-click', () => { ipc.on('title-bar-double-click', () => {
if (!mainWindow) { if (!mainWindow) {
return; return;
@ -2109,7 +2117,7 @@ app.on('ready', async () => {
innerLogger.info('Processed count:', processedCount); innerLogger.info('Processed count:', processedCount);
innerLogger.info('Messages per second:', messagesPerSec); innerLogger.info('Messages per second:', messagesPerSec);
sql.stopTrackingQueryStats(); sql.stopTrackingQueryStats({ epochName: 'App Load' });
event.sender.send('ci:event', 'app-loaded', { event.sender.send('ci:event', 'app-loaded', {
loadTime, loadTime,

View file

@ -268,6 +268,8 @@ export class BackupsService {
): Promise<void> { ): Promise<void> {
strictAssert(!this.isRunning, 'BackupService is already running'); strictAssert(!this.isRunning, 'BackupService is already running');
window.IPC.startTrackingQueryStats();
log.info(`importBackup: starting ${backupType}...`); log.info(`importBackup: starting ${backupType}...`);
this.isRunning = true; this.isRunning = true;
@ -354,7 +356,7 @@ export class BackupsService {
throw error; throw error;
} finally { } finally {
this.isRunning = false; this.isRunning = false;
window.IPC.stopTrackingQueryStats({ epochName: 'Backup Import' });
if (window.SignalCI) { if (window.SignalCI) {
window.SignalCI.handleEvent('backupImportComplete', null); window.SignalCI.handleEvent('backupImportComplete', null);
} }

View file

@ -110,6 +110,11 @@ type QueryStatsType = {
max: number; max: number;
}; };
export type QueryStatsOptions = {
maxQueriesToLog?: number;
epochName?: string;
};
export class MainSQL { export class MainSQL {
private readonly pool = new Array<PoolEntry>(); private readonly pool = new Array<PoolEntry>();
@ -302,15 +307,16 @@ export class MainSQL {
public startTrackingQueryStats(): void { public startTrackingQueryStats(): void {
if (this.shouldTrackQueryStats) { if (this.shouldTrackQueryStats) {
this.logQueryStats(); this.logQueryStats({});
this.logger?.info('Resetting query stats');
} }
this.resetQueryStats(); this.resetQueryStats();
this.shouldTrackQueryStats = true; this.shouldTrackQueryStats = true;
} }
public stopTrackingQueryStats(): void { public stopTrackingQueryStats(options: QueryStatsOptions): void {
if (this.shouldTrackQueryStats) { if (this.shouldTrackQueryStats) {
this.logQueryStats(); this.logQueryStats(options);
} }
this.queryStats = undefined; this.queryStats = undefined;
this.shouldTrackQueryStats = false; this.shouldTrackQueryStats = false;
@ -391,18 +397,26 @@ export class MainSQL {
return Math.round(100 * duration) / 100; return Math.round(100 * duration) / 100;
} }
private logQueryStats(numberToLog: number = 10) { private logQueryStats({
maxQueriesToLog = 10,
epochName,
}: QueryStatsOptions) {
if (!this.queryStats) { if (!this.queryStats) {
return; return;
} }
const duration = Date.now() - this.queryStats.start; const epochDuration = Date.now() - this.queryStats.start;
const sortedByCumulativeDuration = [ const sortedByCumulativeDuration = [
...this.queryStats.statsByQuery.values(), ...this.queryStats.statsByQuery.values(),
].sort((a, b) => (b.cumulative ?? 0) - (a.cumulative ?? 0)); ].sort((a, b) => (b.cumulative ?? 0) - (a.cumulative ?? 0));
const cumulativeDuration = sortedByCumulativeDuration.reduce(
(sum, stats) => sum + stats.cumulative,
0
);
this.logger?.info( this.logger?.info(
`Top ${numberToLog} queries by cumulative duration (ms) over last ${duration}ms: ` + `Top ${maxQueriesToLog} queries by cumulative duration (ms) over last ${epochDuration}ms` +
`${epochName ? ` during '${epochName}'` : ''}: ` +
`${sortedByCumulativeDuration `${sortedByCumulativeDuration
.slice(0, numberToLog) .slice(0, maxQueriesToLog)
.map(stats => { .map(stats => {
return ( return (
`${stats.queryName}: cumulative ${this.roundDuration(stats.cumulative)} | ` + `${stats.queryName}: cumulative ${this.roundDuration(stats.cumulative)} | ` +
@ -411,7 +425,8 @@ export class MainSQL {
`count: ${stats.count}` `count: ${stats.count}`
); );
}) })
.join(' ||| ')}` .join(' ||| ')}` +
`; Total cumulative duration of all SQL queries during this epoch: ${this.roundDuration(cumulativeDuration)}ms`
); );
} }

3
ts/window.d.ts vendored
View file

@ -52,6 +52,7 @@ import type { initializeMigrations } from './signal';
import type { RetryPlaceholders } from './util/retryPlaceholders'; import type { RetryPlaceholders } from './util/retryPlaceholders';
import type { PropsPreloadType as PreferencesPropsType } from './components/Preferences'; import type { PropsPreloadType as PreferencesPropsType } from './components/Preferences';
import type { WindowsNotificationData } from './services/notifications'; import type { WindowsNotificationData } from './services/notifications';
import type { QueryStatsOptions } from './sql/main';
export { Long } from 'long'; export { Long } from 'long';
@ -87,6 +88,8 @@ export type IPCType = {
showWindow: () => void; showWindow: () => void;
showWindowsNotification: (data: WindowsNotificationData) => Promise<void>; showWindowsNotification: (data: WindowsNotificationData) => Promise<void>;
shutdown: () => void; shutdown: () => void;
startTrackingQueryStats: () => void;
stopTrackingQueryStats: (options?: QueryStatsOptions) => void;
titleBarDoubleClick: () => void; titleBarDoubleClick: () => void;
updateTrayIcon: (count: number) => void; updateTrayIcon: (count: number) => void;
}; };

View file

@ -126,6 +126,12 @@ const IPC: IPCType = {
log.info('shutdown'); log.info('shutdown');
ipc.send('shutdown'); ipc.send('shutdown');
}, },
startTrackingQueryStats: () => {
ipc.send('start-tracking-query-stats');
},
stopTrackingQueryStats: options => {
ipc.send('stop-tracking-query-stats', options);
},
titleBarDoubleClick: () => { titleBarDoubleClick: () => {
ipc.send('title-bar-double-click'); ipc.send('title-bar-double-click');
}, },