forge-sql-orm 2.1.4 → 2.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +195 -27
- package/dist/ForgeSQLORM.js +632 -192
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +632 -192
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts +114 -3
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +125 -7
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/ForgeSQLSelectOperations.d.ts.map +1 -1
- package/dist/core/SystemTables.d.ts +3654 -0
- package/dist/core/SystemTables.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.d.ts +2 -2
- package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
- package/dist/utils/cacheContextUtils.d.ts.map +1 -1
- package/dist/utils/cacheUtils.d.ts.map +1 -1
- package/dist/utils/forgeDriver.d.ts +71 -3
- package/dist/utils/forgeDriver.d.ts.map +1 -1
- package/dist/utils/forgeDriverProxy.d.ts.map +1 -1
- package/dist/utils/metadataContextUtils.d.ts +11 -0
- package/dist/utils/metadataContextUtils.d.ts.map +1 -0
- package/dist/utils/requestTypeContextUtils.d.ts +8 -0
- package/dist/utils/requestTypeContextUtils.d.ts.map +1 -0
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/clearCacheSchedulerTrigger.d.ts.map +1 -1
- package/dist/webtriggers/dropMigrationWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/dropTablesMigrationWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/fetchSchemaWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts +85 -43
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/core/ForgeSQLCrudOperations.ts +3 -0
- package/src/core/ForgeSQLORM.ts +287 -9
- package/src/core/ForgeSQLQueryBuilder.ts +138 -8
- package/src/core/ForgeSQLSelectOperations.ts +2 -0
- package/src/core/SystemTables.ts +16 -0
- package/src/lib/drizzle/extensions/additionalActions.ts +10 -12
- package/src/utils/cacheContextUtils.ts +4 -2
- package/src/utils/cacheUtils.ts +20 -8
- package/src/utils/forgeDriver.ts +223 -23
- package/src/utils/forgeDriverProxy.ts +2 -0
- package/src/utils/metadataContextUtils.ts +22 -0
- package/src/utils/requestTypeContextUtils.ts +11 -0
- package/src/utils/sqlUtils.ts +1 -0
- package/src/webtriggers/applyMigrationsWebTrigger.ts +9 -6
- package/src/webtriggers/clearCacheSchedulerTrigger.ts +1 -0
- package/src/webtriggers/dropMigrationWebTrigger.ts +2 -0
- package/src/webtriggers/dropTablesMigrationWebTrigger.ts +2 -0
- package/src/webtriggers/fetchSchemaWebTrigger.ts +1 -0
- package/src/webtriggers/topSlowestStatementLastHourTrigger.ts +515 -257
package/README.md
CHANGED
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
- ✅ **Custom Drizzle Driver** for direct integration with @forge/sql
|
|
20
20
|
- ✅ **Local Cache System (Level 1)** for in-memory query optimization within single resolver invocation scope
|
|
21
21
|
- ✅ **Global Cache System (Level 2)** with cross-invocation caching, automatic cache invalidation and context-aware operations (using [@forge/kvs](https://developer.atlassian.com/platform/forge/storage-reference/storage-api-custom-entities/) )
|
|
22
|
-
- ✅ **
|
|
22
|
+
- ✅ **Performance Monitoring**: Automated detection of memory-intensive queries with configurable thresholds (essential for Atlassian's 16 MiB per query limit)
|
|
23
23
|
- ✅ **Type-Safe Query Building**: Write SQL queries with full TypeScript support
|
|
24
24
|
- ✅ **Supports complex SQL queries** with joins and filtering using Drizzle ORM
|
|
25
25
|
- ✅ **Advanced Query Methods**: `selectFrom()`, `selectDistinctFrom()`, `selectCacheableFrom()`, `selectDistinctCacheableFrom()` for all-column queries with field aliasing
|
|
26
|
-
- ✅ **
|
|
26
|
+
- ✅ **Query Execution with Metadata**: `executeWithMetadata()` method for capturing detailed execution metrics including database execution time, response size, and Forge SQL metadata
|
|
27
|
+
- ✅ **Raw SQL Execution**: `execute()`, `executeCacheable()`, `executeDDL()`, and `executeDDLActions()` methods for direct SQL queries with local and global caching
|
|
27
28
|
- ✅ **Common Table Expressions (CTEs)**: `with()` method for complex queries with subqueries
|
|
28
29
|
- ✅ **Schema migration support**, allowing automatic schema evolution
|
|
29
30
|
- ✅ **Automatic entity generation** from MySQL/tidb databases
|
|
@@ -64,7 +65,7 @@
|
|
|
64
65
|
### 🔒 Advanced Features
|
|
65
66
|
- [Optimistic Locking](#optimistic-locking)
|
|
66
67
|
- [Query Analysis and Performance Optimization](#query-analysis-and-performance-optimization)
|
|
67
|
-
- [
|
|
68
|
+
- [Performance Monitoring](#performance-monitoring)
|
|
68
69
|
- [Date and Time Types](#date-and-time-types)
|
|
69
70
|
|
|
70
71
|
### 🛠️ Development Tools
|
|
@@ -81,7 +82,7 @@
|
|
|
81
82
|
- [Query Analysis Example](examples/forge-sql-orm-example-query-analyses)
|
|
82
83
|
- [Organization Tracker Example](examples/forge-sql-orm-example-org-tracker)
|
|
83
84
|
- [Checklist Example](examples/forge-sql-orm-example-checklist)
|
|
84
|
-
- [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching capabilities with `topSlowestStatementLastHourTrigger`
|
|
85
|
+
- [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching capabilities with `topSlowestStatementLastHourTrigger` performance monitoring
|
|
85
86
|
|
|
86
87
|
### 📚 Reference
|
|
87
88
|
- [ForgeSqlOrmOptions](#forgesqlormoptions)
|
|
@@ -333,6 +334,42 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
|
|
|
333
334
|
300
|
|
334
335
|
);
|
|
335
336
|
|
|
337
|
+
// Raw SQL with execution metadata
|
|
338
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
339
|
+
async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
|
|
340
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
341
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
342
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
343
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
344
|
+
}
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
// DDL operations for schema modifications
|
|
348
|
+
await forgeSQL.executeDDL(`
|
|
349
|
+
CREATE TABLE users (
|
|
350
|
+
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
351
|
+
name VARCHAR(255) NOT NULL,
|
|
352
|
+
email VARCHAR(255) UNIQUE
|
|
353
|
+
)
|
|
354
|
+
`);
|
|
355
|
+
|
|
356
|
+
// Execute regular SQL queries in DDL context for performance monitoring
|
|
357
|
+
await forgeSQL.executeDDLActions(async () => {
|
|
358
|
+
// Execute regular SQL queries in DDL context for monitoring
|
|
359
|
+
const slowQueries = await forgeSQL.execute(`
|
|
360
|
+
SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
|
|
361
|
+
WHERE AVG_LATENCY > 1000000
|
|
362
|
+
`);
|
|
363
|
+
|
|
364
|
+
// Execute complex analysis queries in DDL context
|
|
365
|
+
const performanceData = await forgeSQL.execute(`
|
|
366
|
+
SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
|
|
367
|
+
WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
|
|
368
|
+
`);
|
|
369
|
+
|
|
370
|
+
return { slowQueries, performanceData };
|
|
371
|
+
});
|
|
372
|
+
|
|
336
373
|
// Common Table Expressions (CTEs)
|
|
337
374
|
const userStats = await forgeSQL
|
|
338
375
|
.with(
|
|
@@ -406,6 +443,16 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
|
|
|
406
443
|
[true],
|
|
407
444
|
300
|
|
408
445
|
);
|
|
446
|
+
|
|
447
|
+
// Raw SQL with execution metadata
|
|
448
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
449
|
+
async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
|
|
450
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
451
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
452
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
453
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
454
|
+
}
|
|
455
|
+
);
|
|
409
456
|
```
|
|
410
457
|
|
|
411
458
|
## Setting Up Caching with @forge/kvs (Optional)
|
|
@@ -757,6 +804,8 @@ const optimizedData = await forgeSQL.executeWithLocalCacheContextAndReturnValue(
|
|
|
757
804
|
| `selectDistinctCacheableFrom()` | Distinct all-column queries with field aliasing and caching | ❌ No | Local + Global Cache |
|
|
758
805
|
| `execute()` | Raw SQL queries with local caching | ❌ No | Local Cache |
|
|
759
806
|
| `executeCacheable()` | Raw SQL queries with local and global caching | ❌ No | Local + Global Cache |
|
|
807
|
+
| `executeDDL()` | DDL operations (CREATE, ALTER, DROP, etc.) | ❌ No | No Caching |
|
|
808
|
+
| `executeDDLActions()` | Execute regular SQL queries in DDL operation context | ❌ No | No Caching |
|
|
760
809
|
| `with()` | Common Table Expressions (CTEs) | ❌ No | Local Cache |
|
|
761
810
|
|
|
762
811
|
|
|
@@ -777,6 +826,9 @@ const optimizedData = await forgeSQL.executeWithLocalCacheContextAndReturnValue(
|
|
|
777
826
|
| `selectDistinctCacheableFrom()` | Distinct all-column queries with field aliasing and caching | ❌ No | Local + Global Cache |
|
|
778
827
|
| `execute()` | Raw SQL queries with local caching | ❌ No | Local Cache |
|
|
779
828
|
| `executeCacheable()` | Raw SQL queries with local and global caching | ❌ No | Local + Global Cache |
|
|
829
|
+
| `executeWithMetadata()` | Raw SQL queries with execution metrics capture | ❌ No | Local Cache |
|
|
830
|
+
| `executeDDL()` | DDL operations (CREATE, ALTER, DROP, etc.) | ❌ No | No Caching |
|
|
831
|
+
| `executeDDLActions()` | Execute regular SQL queries in DDL operation context | ❌ No | No Caching |
|
|
780
832
|
| `with()` | Common Table Expressions (CTEs) | ❌ No | Local Cache |
|
|
781
833
|
where Cache context - allows you to batch cache invalidation events and bypass cache reads for affected tables.
|
|
782
834
|
|
|
@@ -1163,6 +1215,51 @@ const users = await forgeSQL
|
|
|
1163
1215
|
const users = await forgeSQL
|
|
1164
1216
|
.executeCacheable("SELECT * FROM users WHERE active = ?", [true], 300);
|
|
1165
1217
|
|
|
1218
|
+
// Using executeWithMetadata() for capturing execution metrics
|
|
1219
|
+
const usersWithMetadata = await forgeSQL
|
|
1220
|
+
.executeWithMetadata(
|
|
1221
|
+
async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
|
|
1222
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
1223
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
1224
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
1225
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
1226
|
+
}
|
|
1227
|
+
);
|
|
1228
|
+
|
|
1229
|
+
// Using executeDDL() for DDL operations (CREATE, ALTER, DROP, etc.)
|
|
1230
|
+
await forgeSQL.executeDDL(`
|
|
1231
|
+
CREATE TABLE users (
|
|
1232
|
+
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
1233
|
+
name VARCHAR(255) NOT NULL,
|
|
1234
|
+
email VARCHAR(255) UNIQUE
|
|
1235
|
+
)
|
|
1236
|
+
`);
|
|
1237
|
+
|
|
1238
|
+
await forgeSQL.executeDDL(sql`
|
|
1239
|
+
ALTER TABLE users
|
|
1240
|
+
ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
1241
|
+
`);
|
|
1242
|
+
|
|
1243
|
+
await forgeSQL.executeDDL("DROP TABLE IF EXISTS old_users");
|
|
1244
|
+
|
|
1245
|
+
// Using executeDDLActions() for executing regular SQL queries in DDL context
|
|
1246
|
+
// This method executes a series of actions within a DDL operation context for monitoring
|
|
1247
|
+
await forgeSQL.executeDDLActions(async () => {
|
|
1248
|
+
// Execute regular SQL queries in DDL context for performance monitoring
|
|
1249
|
+
const slowQueries = await forgeSQL.execute(`
|
|
1250
|
+
SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
|
|
1251
|
+
WHERE AVG_LATENCY > 1000000
|
|
1252
|
+
`);
|
|
1253
|
+
|
|
1254
|
+
// Execute complex analysis queries in DDL context
|
|
1255
|
+
const performanceData = await forgeSQL.execute(`
|
|
1256
|
+
SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
|
|
1257
|
+
WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
|
|
1258
|
+
`);
|
|
1259
|
+
|
|
1260
|
+
return { slowQueries, performanceData };
|
|
1261
|
+
});
|
|
1262
|
+
|
|
1166
1263
|
// Using execute() with complex queries
|
|
1167
1264
|
const userStats = await forgeSQL
|
|
1168
1265
|
.execute(`
|
|
@@ -1478,6 +1575,16 @@ await forgeSQL.executeWithLocalContext(async () => {
|
|
|
1478
1575
|
[true]
|
|
1479
1576
|
);
|
|
1480
1577
|
|
|
1578
|
+
// Raw SQL with execution metadata and local caching
|
|
1579
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
1580
|
+
async () => await forgeSQL.execute("SELECT id, name FROM users WHERE active = ?", [true]),
|
|
1581
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
1582
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
1583
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
1584
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
1585
|
+
}
|
|
1586
|
+
);
|
|
1587
|
+
|
|
1481
1588
|
// Insert operation - evicts local cache for users table
|
|
1482
1589
|
await forgeSQL.insert(users).values({ name: 'New User', active: true });
|
|
1483
1590
|
|
|
@@ -1646,6 +1753,16 @@ const userStats = await forgeSQL
|
|
|
1646
1753
|
})
|
|
1647
1754
|
.from(sql`activeUsers au`)
|
|
1648
1755
|
.leftJoin(sql`completedOrders co`, eq(sql`au.id`, sql`co.userId`));
|
|
1756
|
+
|
|
1757
|
+
// Using executeWithMetadata() for capturing execution metrics with caching
|
|
1758
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
1759
|
+
async () => await forgeSQL.executeCacheable("SELECT * FROM users WHERE active = ?", [true], 300),
|
|
1760
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
1761
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
1762
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
1763
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
1764
|
+
}
|
|
1765
|
+
);
|
|
1649
1766
|
```
|
|
1650
1767
|
|
|
1651
1768
|
### Manual Cache Management
|
|
@@ -1721,6 +1838,7 @@ The `ForgeSqlOrmOptions` object allows customization of ORM behavior:
|
|
|
1721
1838
|
| Option | Type | Description |
|
|
1722
1839
|
| -------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1723
1840
|
| `logRawSqlQuery` | `boolean` | Enables logging of raw SQL queries in the Atlassian Forge Developer Console. Useful for debugging and monitoring. Defaults to `false`. |
|
|
1841
|
+
| `logCache` | `boolean` | Enables logging of cache operations (hits, misses, evictions) in the Atlassian Forge Developer Console. Useful for debugging caching issues. Defaults to `false`. |
|
|
1724
1842
|
| `disableOptimisticLocking` | `boolean` | Disables optimistic locking. When set to `true`, no additional condition (e.g., a version check) is added during record updates, which can improve performance. However, this may lead to conflicts when multiple transactions attempt to update the same record concurrently. |
|
|
1725
1843
|
| `additionalMetadata` | `object` | Allows adding custom metadata to all entities. This is useful for tracking common fields across all tables (e.g., `createdAt`, `updatedAt`, `createdBy`, etc.). The metadata will be automatically added to all generated entities. |
|
|
1726
1844
|
| `cacheEntityName` | `string` | KVS Custom entity name for cache storage. Must match the `name` in your `manifest.yml` storage entities configuration. Required for caching functionality. Defaults to `"cache"`. |
|
|
@@ -2020,13 +2138,13 @@ This analysis provides insights into:
|
|
|
2020
2138
|
- Resource usage at each step
|
|
2021
2139
|
- Performance optimization opportunities
|
|
2022
2140
|
|
|
2023
|
-
##
|
|
2141
|
+
## Performance Monitoring
|
|
2024
2142
|
|
|
2025
2143
|
[↑ Back to Top](#table-of-contents)
|
|
2026
2144
|
|
|
2027
|
-
Forge-SQL-ORM provides automated
|
|
2145
|
+
Forge-SQL-ORM provides automated performance monitoring capabilities to help you identify and track memory-intensive queries in your Forge SQL instance. This feature is **essential for Atlassian Forge applications** as it helps you stay within the **16 MiB per query memory limit** and provides detailed insights for optimization.
|
|
2028
2146
|
|
|
2029
|
-
### Why
|
|
2147
|
+
### Why Performance Monitoring is Critical
|
|
2030
2148
|
|
|
2031
2149
|
Atlassian Forge SQL has a strict **16 MiB memory limit per query**. Unlike slow query detection (which is available in the Forge Developer Console), there's **no built-in way to monitor memory usage** of your queries. This monitoring system fills that gap by:
|
|
2032
2150
|
|
|
@@ -2038,7 +2156,7 @@ Atlassian Forge SQL has a strict **16 MiB memory limit per query**. Unlike slow
|
|
|
2038
2156
|
|
|
2039
2157
|
### Overview
|
|
2040
2158
|
|
|
2041
|
-
The
|
|
2159
|
+
The performance monitoring system:
|
|
2042
2160
|
- **Automatically detects memory-intensive queries** based on configurable memory thresholds
|
|
2043
2161
|
- **Provides detailed memory metrics** including execution time, memory usage, and execution plans
|
|
2044
2162
|
- **Logs memory issues** to the Forge Developer Console for easy debugging
|
|
@@ -2047,7 +2165,7 @@ The memory monitoring system:
|
|
|
2047
2165
|
|
|
2048
2166
|
### Key Features
|
|
2049
2167
|
|
|
2050
|
-
- **Memory-Focused Monitoring**: Primary focus on memory usage with configurable thresholds
|
|
2168
|
+
- **Memory-Focused Performance Monitoring**: Primary focus on memory usage with configurable thresholds
|
|
2051
2169
|
- **Atlassian 16 MiB Limit Awareness**: Designed specifically for Forge SQL's memory constraints
|
|
2052
2170
|
- **Execution Plan Analysis**: Shows detailed query plans to help optimize memory consumption
|
|
2053
2171
|
- **Configurable Thresholds**: Set custom memory usage thresholds (default: 4MB warning)
|
|
@@ -2071,56 +2189,60 @@ import ForgeSQL, { topSlowestStatementLastHourTrigger } from 'forge-sql-orm';
|
|
|
2071
2189
|
const forgeSQL = new ForgeSQL();
|
|
2072
2190
|
|
|
2073
2191
|
// Basic usage with default thresholds (300ms latency, 8MB memory warning)
|
|
2074
|
-
export const
|
|
2192
|
+
export const performanceTrigger = () =>
|
|
2075
2193
|
topSlowestStatementLastHourTrigger(forgeSQL);
|
|
2076
2194
|
|
|
2077
|
-
// Conservative
|
|
2195
|
+
// Conservative performance monitoring: 4MB warning (well below 16MB limit)
|
|
2078
2196
|
export const conservativeMemoryTrigger = () =>
|
|
2079
|
-
topSlowestStatementLastHourTrigger(forgeSQL,
|
|
2197
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { memoryThresholdBytes: 4 * 1024 * 1024 });
|
|
2080
2198
|
|
|
2081
|
-
// Aggressive
|
|
2199
|
+
// Aggressive performance monitoring: 12MB warning (75% of 16MB limit)
|
|
2082
2200
|
export const aggressiveMemoryTrigger = () =>
|
|
2083
|
-
topSlowestStatementLastHourTrigger(forgeSQL,
|
|
2201
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { memoryThresholdBytes: 12 * 1024 * 1024 });
|
|
2084
2202
|
|
|
2085
|
-
// Memory-only monitoring: Only trigger on memory usage (latency effectively disabled)
|
|
2203
|
+
// Memory-only performance monitoring: Only trigger on memory usage (latency effectively disabled)
|
|
2086
2204
|
export const memoryOnlyTrigger = () =>
|
|
2087
|
-
topSlowestStatementLastHourTrigger(forgeSQL, 10000, 4 * 1024 * 1024);
|
|
2205
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { warnThresholdMs: 10000, memoryThresholdBytes: 4 * 1024 * 1024 });
|
|
2088
2206
|
|
|
2089
2207
|
// Latency-only monitoring: Only trigger on slow queries (memory effectively disabled)
|
|
2090
2208
|
export const latencyOnlyTrigger = () =>
|
|
2091
|
-
topSlowestStatementLastHourTrigger(forgeSQL, 500, 16 * 1024 * 1024);
|
|
2209
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { warnThresholdMs: 500, memoryThresholdBytes: 16 * 1024 * 1024 });
|
|
2092
2210
|
|
|
2211
|
+
// With execution plan in logs
|
|
2212
|
+
export const performanceWithPlanTrigger = () =>
|
|
2213
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { showPlan: true });
|
|
2214
|
+
```
|
|
2093
2215
|
|
|
2094
2216
|
#### 3. Configure in manifest.yml
|
|
2095
2217
|
|
|
2096
2218
|
**As Scheduler Trigger (Recommended for Production):**
|
|
2097
2219
|
```yaml
|
|
2098
2220
|
scheduledTrigger:
|
|
2099
|
-
- key:
|
|
2100
|
-
function:
|
|
2221
|
+
- key: performance-trigger
|
|
2222
|
+
function: perfTrigger
|
|
2101
2223
|
interval: hour # Required: only hour interval is supported
|
|
2102
2224
|
|
|
2103
2225
|
function:
|
|
2104
|
-
- key:
|
|
2105
|
-
handler: index.
|
|
2226
|
+
- key: perfTrigger
|
|
2227
|
+
handler: index.performanceTrigger
|
|
2106
2228
|
```
|
|
2107
2229
|
|
|
2108
2230
|
**As Web Trigger (Development Only):**
|
|
2109
2231
|
```yaml
|
|
2110
2232
|
webtrigger:
|
|
2111
2233
|
- key: print-slowest-queries
|
|
2112
|
-
function:
|
|
2234
|
+
function: perfTrigger
|
|
2113
2235
|
|
|
2114
2236
|
function:
|
|
2115
|
-
- key:
|
|
2116
|
-
handler: index.
|
|
2237
|
+
- key: perfTrigger
|
|
2238
|
+
handler: index.performanceTrigger
|
|
2117
2239
|
```
|
|
2118
2240
|
|
|
2119
2241
|
> **⚠️ Important**: Web triggers are not recommended for production as they violate the "run-on-atlassian" principle. Use scheduler triggers for production monitoring.
|
|
2120
2242
|
|
|
2121
2243
|
### How It Works
|
|
2122
2244
|
|
|
2123
|
-
The
|
|
2245
|
+
The performance monitoring trigger works differently depending on how it's configured:
|
|
2124
2246
|
|
|
2125
2247
|
#### Scheduler Trigger Mode (Production)
|
|
2126
2248
|
|
|
@@ -2196,7 +2318,8 @@ When used as a **web trigger**, the system:
|
|
|
2196
2318
|
|-----------|------|---------|-------------|
|
|
2197
2319
|
| `warnThresholdMs` | `number` | `300` | Latency threshold in milliseconds (secondary) |
|
|
2198
2320
|
| `memoryThresholdBytes` | `number` | `8 * 1024 * 1024` | **Memory usage threshold in bytes (primary focus)** |
|
|
2199
|
-
| `
|
|
2321
|
+
| `showPlan` | `boolean` | `false` | Whether to include execution plan in logs |
|
|
2322
|
+
| `logCache` | `boolean` | `false` | Whether to log cache operations |
|
|
2200
2323
|
|
|
2201
2324
|
**⚠️ Important: OR Logic**
|
|
2202
2325
|
The monitoring uses **OR logic** - if **either** threshold is exceeded, the query will be logged/returned:
|
|
@@ -2205,9 +2328,11 @@ The monitoring uses **OR logic** - if **either** threshold is exceeded, the quer
|
|
|
2205
2328
|
- No need to exceed both thresholds simultaneously
|
|
2206
2329
|
|
|
2207
2330
|
**💡 Pro Tips:**
|
|
2208
|
-
- **Memory-only monitoring**: Set `warnThresholdMs` to a very high value (e.g., 10000ms) to trigger only on memory usage
|
|
2331
|
+
- **Memory-only performance monitoring**: Set `warnThresholdMs` to a very high value (e.g., 10000ms) to trigger only on memory usage
|
|
2209
2332
|
- **Latency-only monitoring**: Set `memoryThresholdBytes` to 16MB (16 * 1024 * 1024) to trigger only on latency
|
|
2210
2333
|
- **Combined monitoring**: Use both thresholds for comprehensive monitoring
|
|
2334
|
+
- **Execution plan analysis**: Set `showPlan: true` to include detailed execution plans in logs (useful for debugging)
|
|
2335
|
+
- **Cache debugging**: Set `logCache: true` to log cache operations and debug caching issues
|
|
2211
2336
|
|
|
2212
2337
|
**Memory Threshold Guidelines:**
|
|
2213
2338
|
- **Conservative**: 4MB (25% of 16MB limit)
|
|
@@ -2276,6 +2401,8 @@ This section covers the breaking changes introduced in version 2.1.x and how to
|
|
|
2276
2401
|
- `forgeSQL.selectDistinctCacheableFrom()` - Distinct all-column queries with field aliasing and caching
|
|
2277
2402
|
- `forgeSQL.execute()` - Raw SQL queries with local caching
|
|
2278
2403
|
- `forgeSQL.executeCacheable()` - Raw SQL queries with local and global caching
|
|
2404
|
+
- `forgeSQL.executeDDL()` - DDL operations (CREATE, ALTER, DROP, etc.)
|
|
2405
|
+
- `forgeSQL.executeDDLActions()` - Execute actions within DDL operation context
|
|
2279
2406
|
- `forgeSQL.with()` - Common Table Expressions (CTEs)
|
|
2280
2407
|
|
|
2281
2408
|
**Optional Migration:**
|
|
@@ -2312,6 +2439,47 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
|
|
|
2312
2439
|
300
|
|
2313
2440
|
);
|
|
2314
2441
|
|
|
2442
|
+
// ✅ Raw SQL execution with metadata capture
|
|
2443
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
2444
|
+
async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
|
|
2445
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
2446
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
2447
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
2448
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
2449
|
+
}
|
|
2450
|
+
);
|
|
2451
|
+
|
|
2452
|
+
// ✅ DDL operations for schema modifications
|
|
2453
|
+
await forgeSQL.executeDDL(`
|
|
2454
|
+
CREATE TABLE users (
|
|
2455
|
+
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
2456
|
+
name VARCHAR(255) NOT NULL,
|
|
2457
|
+
email VARCHAR(255) UNIQUE
|
|
2458
|
+
)
|
|
2459
|
+
`);
|
|
2460
|
+
|
|
2461
|
+
await forgeSQL.executeDDL(sql`
|
|
2462
|
+
ALTER TABLE users
|
|
2463
|
+
ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
2464
|
+
`);
|
|
2465
|
+
|
|
2466
|
+
// ✅ Execute regular SQL queries in DDL context for performance monitoring
|
|
2467
|
+
await forgeSQL.executeDDLActions(async () => {
|
|
2468
|
+
// Execute regular SQL queries in DDL context for monitoring
|
|
2469
|
+
const slowQueries = await forgeSQL.execute(`
|
|
2470
|
+
SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
|
|
2471
|
+
WHERE AVG_LATENCY > 1000000
|
|
2472
|
+
`);
|
|
2473
|
+
|
|
2474
|
+
// Execute complex analysis queries in DDL context
|
|
2475
|
+
const performanceData = await forgeSQL.execute(`
|
|
2476
|
+
SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
|
|
2477
|
+
WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
|
|
2478
|
+
`);
|
|
2479
|
+
|
|
2480
|
+
return { slowQueries, performanceData };
|
|
2481
|
+
});
|
|
2482
|
+
|
|
2315
2483
|
// ✅ Common Table Expressions (CTEs)
|
|
2316
2484
|
const userStats = await forgeSQL
|
|
2317
2485
|
.with(
|