Skip to content

Commit e6b6fbc

Browse files
committed
feat: Cache parsed SQL in Event class
This reduces the number of times we need to parse the SQL, which is expensive, and improves sequence diagram load times by ~24%
1 parent f0ede48 commit e6b6fbc

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

packages/models/src/event.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable */
12
import { addHiddenProperty, hasProp, transformToJSON } from './util';
23
import analyzeSQL, { abstractSqlAstJSON } from './sql/analyze';
34
import normalizeSQL from './sql/normalize';
@@ -19,6 +20,8 @@ function alias(obj, prop, alias) {
1920
// This class supercedes `CallTree` and `CallNode`. Events are stored in a flat
2021
// array and can also be traversed like a tree via `parent` and `children`.
2122
export default class Event {
23+
static parsedSqlCache = {};
24+
2225
static contentType(...messages) {
2326
const msg = messages.find((message) => (message?.headers || {})['Content-Type']);
2427
if (!msg) {
@@ -526,10 +529,19 @@ export default class Event {
526529

527530
let properties;
528531
if (sqlQuery) {
529-
const sqlNormalized = abstractSqlAstJSON(sqlQuery, this.sql.database_type)
530-
// Collapse repeated variable literals and parameter tokens (e.g. '?, ?' in an IN clause)
531-
.split(/{"type":"variable"}(?:,{"type":"variable"})*/g)
532-
.join(`{"type":"variable"}`);
532+
let sqlNormalized;
533+
const cacheKey = `${this.sql.database_type}:${sqlQuery}`;
534+
if (!Event.parsedSqlCache[cacheKey]) {
535+
sqlNormalized = abstractSqlAstJSON(sqlQuery, this.sql.database_type)
536+
// Collapse repeated variable literals and parameter tokens (e.g. '?, ?' in an IN clause)
537+
.split(/{"type":"variable"}(?:,{"type":"variable"})*/g)
538+
.join(`{"type":"variable"}`);
539+
540+
Event.parsedSqlCache[cacheKey] = sqlNormalized;
541+
} else {
542+
sqlNormalized = Event.parsedSqlCache[cacheKey];
543+
}
544+
533545
properties = {
534546
event_type: 'sql',
535547
sql_normalized: sqlNormalized,

packages/models/tests/unit/event.spec.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,21 @@ describe('Event', () => {
101101
});
102102
});
103103
describe('stableProperties', () => {
104-
it('sql_normalized', () => {
104+
it('sql_normalized and cached', () => {
105+
const expectedSqlNormalized =
106+
'{"type":"statement","variant":"list","statement":[{"type":"statement","variant":"select","result":[{"type":"function","name":{"type":"identifier","variant":"function","name":"count"},"args":{"type":"identifier","variant":"star","name":"*"}}],"from":{"type":"identifier","variant":"table","name":"spree_stores"}}]}';
107+
105108
verifyJSON(sqlEvent.gatherStableProperties(), {
106109
event_type: 'sql',
107-
sql_normalized:
108-
'{"type":"statement","variant":"list","statement":[{"type":"statement","variant":"select","result":[{"type":"function","name":{"type":"identifier","variant":"function","name":"count"},"args":{"type":"identifier","variant":"star","name":"*"}}],"from":{"type":"identifier","variant":"table","name":"spree_stores"}}]}',
110+
sql_normalized: expectedSqlNormalized,
109111
});
112+
113+
const expectedSqlKey = `${sqlEvent.sql.database_type}:${sqlEvent.sqlQuery}`;
114+
const expectedSqlCache = {
115+
[expectedSqlKey]: expectedSqlNormalized,
116+
};
117+
118+
expect(Event.parsedSqlCache).toEqual(expectedSqlCache);
110119
});
111120
it('sql_normalized with query parameters', () => {
112121
const sql = {

0 commit comments

Comments
 (0)