Skip to content

Commit 5d6f222

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 5d6f222

2 files changed

Lines changed: 27 additions & 7 deletions

File tree

packages/models/src/event.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ function alias(obj, prop, alias) {
1919
// This class supercedes `CallTree` and `CallNode`. Events are stored in a flat
2020
// array and can also be traversed like a tree via `parent` and `children`.
2121
export default class Event {
22+
static parsedSqlCache = {};
23+
2224
static contentType(...messages) {
2325
const msg = messages.find((message) => (message?.headers || {})['Content-Type']);
2426
if (!msg) {
@@ -526,10 +528,19 @@ export default class Event {
526528

527529
let properties;
528530
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"}`);
531+
let sqlNormalized;
532+
const cacheKey = `${this.sql.database_type}:${sqlQuery}`;
533+
if (!Event.parsedSqlCache[cacheKey]) {
534+
sqlNormalized = abstractSqlAstJSON(sqlQuery, this.sql.database_type)
535+
// Collapse repeated variable literals and parameter tokens (e.g. '?, ?' in an IN clause)
536+
.split(/{"type":"variable"}(?:,{"type":"variable"})*/g)
537+
.join(`{"type":"variable"}`);
538+
539+
Event.parsedSqlCache[cacheKey] = sqlNormalized;
540+
} else {
541+
sqlNormalized = Event.parsedSqlCache[cacheKey];
542+
}
543+
533544
properties = {
534545
event_type: 'sql',
535546
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)