diff --git a/packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts b/packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts index 395cfeed..7e03be77 100644 --- a/packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts +++ b/packages/web/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts @@ -53,7 +53,32 @@ export class WASQLiteDBAdapter extends BaseObserver implement const start = performance.now(); try { const r = await originalExecute(sql, bindings); - performance.measure(`[SQL] ${sql}`, { start }); + const end = performance.now(); + performance.measure(`[SQL] ${sql}`, { start, end }); + const duration = end - start; + if (duration >= 10) { + const rw = await originalExecute(`EXPLAIN QUERY PLAN ${sql}`, bindings); + const explain = rw.rows?._array ?? []; + const sqlMessage = sql.trim(); + const newline = sqlMessage.indexOf('\n'); + const firstLine = newline >= 0 ? sqlMessage.substring(0, newline) + '...' : sqlMessage; + console.groupCollapsed( + '%c[SQL] %c%s %c%s', + 'color: grey; font-weight: normal', + durationStyle(duration), + `[${duration.toFixed(1)}ms]`, + 'color: grey; font-weight: normal', + firstLine + ); + if (newline >= 0) { + console.log('%c%s', 'color: grey', sqlMessage); + } + if (explain.length > 0) { + const emessage = explain.map((r) => ` ${r.detail}`).join('\n'); + console.log('%c%s\n%c%s', 'color: blue', '[EXPLAIN QUERY PLAN]', 'color: grey', emessage); + } + console.groupEnd(); + } return r; } catch (e: any) { performance.measure(`[SQL] [ERROR: ${e.message}] ${sql}`, { start }); @@ -263,3 +288,13 @@ export class WASQLiteDBAdapter extends BaseObserver implement }; } } + +function durationStyle(duration: number) { + if (duration < 30) { + return 'color: grey; font-weight: normal'; + } else if (duration < 300) { + return 'color: blue; font-weight: normal'; + } else { + return 'color: red; font-weight: normal'; + } +}