forge-sql-orm 2.1.3 → 2.1.5
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 +291 -0
- package/dist/ForgeSQLORM.js +713 -12
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +716 -15
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts +23 -0
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +36 -5
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/ForgeSQLSelectOperations.d.ts.map +1 -1
- package/dist/core/SystemTables.d.ts +5039 -0
- package/dist/core/SystemTables.d.ts.map +1 -1
- 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 +21 -0
- 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/sqlUtils.d.ts.map +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.d.ts +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/index.d.ts +1 -0
- package/dist/webtriggers/index.d.ts.map +1 -1
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts +89 -0
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts.map +1 -0
- package/package.json +4 -3
- package/src/core/ForgeSQLCrudOperations.ts +3 -0
- package/src/core/ForgeSQLORM.ts +119 -51
- package/src/core/ForgeSQLQueryBuilder.ts +51 -17
- package/src/core/ForgeSQLSelectOperations.ts +2 -0
- package/src/core/SystemTables.ts +313 -1
- package/src/lib/drizzle/extensions/additionalActions.ts +2 -0
- package/src/utils/cacheContextUtils.ts +4 -2
- package/src/utils/cacheUtils.ts +20 -8
- package/src/utils/forgeDriver.ts +22 -1
- package/src/utils/forgeDriverProxy.ts +2 -0
- package/src/utils/metadataContextUtils.ts +24 -0
- package/src/utils/sqlUtils.ts +1 -0
- package/src/webtriggers/applyMigrationsWebTrigger.ts +10 -5
- 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/index.ts +1 -0
- package/src/webtriggers/topSlowestStatementLastHourTrigger.ts +360 -0
package/README.md
CHANGED
|
@@ -19,10 +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
|
+
- ✅ **Memory Usage Monitoring**: Automated detection of memory-intensive queries with configurable thresholds (essential for Atlassian's 16 MiB per query limit)
|
|
22
23
|
- ✅ **Type-Safe Query Building**: Write SQL queries with full TypeScript support
|
|
23
24
|
- ✅ **Supports complex SQL queries** with joins and filtering using Drizzle ORM
|
|
24
25
|
- ✅ **Advanced Query Methods**: `selectFrom()`, `selectDistinctFrom()`, `selectCacheableFrom()`, `selectDistinctCacheableFrom()` for all-column queries with field aliasing
|
|
25
26
|
- ✅ **Raw SQL Execution**: `execute()` and `executeCacheable()` methods for direct SQL queries with local and global caching
|
|
27
|
+
- ✅ **Query Execution with Metadata**: `executeWithMetadata()` method for capturing detailed execution metrics including database execution time, response size, and Forge SQL metadata
|
|
26
28
|
- ✅ **Common Table Expressions (CTEs)**: `with()` method for complex queries with subqueries
|
|
27
29
|
- ✅ **Schema migration support**, allowing automatic schema evolution
|
|
28
30
|
- ✅ **Automatic entity generation** from MySQL/tidb databases
|
|
@@ -63,6 +65,7 @@
|
|
|
63
65
|
### 🔒 Advanced Features
|
|
64
66
|
- [Optimistic Locking](#optimistic-locking)
|
|
65
67
|
- [Query Analysis and Performance Optimization](#query-analysis-and-performance-optimization)
|
|
68
|
+
- [Memory Usage Monitoring](#memory-usage-monitoring)
|
|
66
69
|
- [Date and Time Types](#date-and-time-types)
|
|
67
70
|
|
|
68
71
|
### 🛠️ Development Tools
|
|
@@ -79,6 +82,7 @@
|
|
|
79
82
|
- [Query Analysis Example](examples/forge-sql-orm-example-query-analyses)
|
|
80
83
|
- [Organization Tracker Example](examples/forge-sql-orm-example-org-tracker)
|
|
81
84
|
- [Checklist Example](examples/forge-sql-orm-example-checklist)
|
|
85
|
+
- [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching capabilities with `topSlowestStatementLastHourTrigger` memory monitoring
|
|
82
86
|
|
|
83
87
|
### 📚 Reference
|
|
84
88
|
- [ForgeSqlOrmOptions](#forgesqlormoptions)
|
|
@@ -95,6 +99,7 @@
|
|
|
95
99
|
- [Global Cache System (Level 2)](#global-cache-system-level-2) - Cross-invocation persistent caching
|
|
96
100
|
- [Local Cache System (Level 1)](#local-cache-operations-level-1) - In-memory invocation caching
|
|
97
101
|
- [Optimistic Locking](#optimistic-locking) - Data consistency
|
|
102
|
+
- [Memory Usage Monitoring](#memory-usage-monitoring) - Memory-intensive query detection
|
|
98
103
|
- [Migration Tools](#web-triggers-for-migrations) - Database migrations
|
|
99
104
|
- [Query Analysis](#query-analysis-and-performance-optimization) - Performance optimization
|
|
100
105
|
|
|
@@ -103,6 +108,7 @@
|
|
|
103
108
|
- [Optimistic Locking Example](examples/forge-sql-orm-example-optimistic-locking) - Real-world conflict handling
|
|
104
109
|
- [Organization Tracker Example](examples/forge-sql-orm-example-org-tracker) - Complex relationships
|
|
105
110
|
- [Checklist Example](examples/forge-sql-orm-example-checklist) - Jira integration
|
|
111
|
+
- [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching with memory monitoring
|
|
106
112
|
|
|
107
113
|
## Usage Approaches
|
|
108
114
|
|
|
@@ -328,6 +334,16 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
|
|
|
328
334
|
300
|
|
329
335
|
);
|
|
330
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
|
+
|
|
331
347
|
// Common Table Expressions (CTEs)
|
|
332
348
|
const userStats = await forgeSQL
|
|
333
349
|
.with(
|
|
@@ -401,6 +417,16 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
|
|
|
401
417
|
[true],
|
|
402
418
|
300
|
|
403
419
|
);
|
|
420
|
+
|
|
421
|
+
// Raw SQL with execution metadata
|
|
422
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
423
|
+
async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
|
|
424
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
425
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
426
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
427
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
428
|
+
}
|
|
429
|
+
);
|
|
404
430
|
```
|
|
405
431
|
|
|
406
432
|
## Setting Up Caching with @forge/kvs (Optional)
|
|
@@ -772,6 +798,7 @@ const optimizedData = await forgeSQL.executeWithLocalCacheContextAndReturnValue(
|
|
|
772
798
|
| `selectDistinctCacheableFrom()` | Distinct all-column queries with field aliasing and caching | ❌ No | Local + Global Cache |
|
|
773
799
|
| `execute()` | Raw SQL queries with local caching | ❌ No | Local Cache |
|
|
774
800
|
| `executeCacheable()` | Raw SQL queries with local and global caching | ❌ No | Local + Global Cache |
|
|
801
|
+
| `executeWithMetadata()` | Raw SQL queries with execution metrics capture | ❌ No | Local Cache |
|
|
775
802
|
| `with()` | Common Table Expressions (CTEs) | ❌ No | Local Cache |
|
|
776
803
|
where Cache context - allows you to batch cache invalidation events and bypass cache reads for affected tables.
|
|
777
804
|
|
|
@@ -1158,6 +1185,17 @@ const users = await forgeSQL
|
|
|
1158
1185
|
const users = await forgeSQL
|
|
1159
1186
|
.executeCacheable("SELECT * FROM users WHERE active = ?", [true], 300);
|
|
1160
1187
|
|
|
1188
|
+
// Using executeWithMetadata() for capturing execution metrics
|
|
1189
|
+
const usersWithMetadata = await forgeSQL
|
|
1190
|
+
.executeWithMetadata(
|
|
1191
|
+
async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
|
|
1192
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
1193
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
1194
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
1195
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
1196
|
+
}
|
|
1197
|
+
);
|
|
1198
|
+
|
|
1161
1199
|
// Using execute() with complex queries
|
|
1162
1200
|
const userStats = await forgeSQL
|
|
1163
1201
|
.execute(`
|
|
@@ -1473,6 +1511,16 @@ await forgeSQL.executeWithLocalContext(async () => {
|
|
|
1473
1511
|
[true]
|
|
1474
1512
|
);
|
|
1475
1513
|
|
|
1514
|
+
// Raw SQL with execution metadata and local caching
|
|
1515
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
1516
|
+
async () => await forgeSQL.execute("SELECT id, name FROM users WHERE active = ?", [true]),
|
|
1517
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
1518
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
1519
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
1520
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
1521
|
+
}
|
|
1522
|
+
);
|
|
1523
|
+
|
|
1476
1524
|
// Insert operation - evicts local cache for users table
|
|
1477
1525
|
await forgeSQL.insert(users).values({ name: 'New User', active: true });
|
|
1478
1526
|
|
|
@@ -1641,6 +1689,16 @@ const userStats = await forgeSQL
|
|
|
1641
1689
|
})
|
|
1642
1690
|
.from(sql`activeUsers au`)
|
|
1643
1691
|
.leftJoin(sql`completedOrders co`, eq(sql`au.id`, sql`co.userId`));
|
|
1692
|
+
|
|
1693
|
+
// Using executeWithMetadata() for capturing execution metrics with caching
|
|
1694
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
1695
|
+
async () => await forgeSQL.executeCacheable("SELECT * FROM users WHERE active = ?", [true], 300),
|
|
1696
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
1697
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
1698
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
1699
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
1700
|
+
}
|
|
1701
|
+
);
|
|
1644
1702
|
```
|
|
1645
1703
|
|
|
1646
1704
|
### Manual Cache Management
|
|
@@ -1716,6 +1774,7 @@ The `ForgeSqlOrmOptions` object allows customization of ORM behavior:
|
|
|
1716
1774
|
| Option | Type | Description |
|
|
1717
1775
|
| -------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1718
1776
|
| `logRawSqlQuery` | `boolean` | Enables logging of raw SQL queries in the Atlassian Forge Developer Console. Useful for debugging and monitoring. Defaults to `false`. |
|
|
1777
|
+
| `logCache` | `boolean` | Enables logging of cache operations (hits, misses, evictions) in the Atlassian Forge Developer Console. Useful for debugging caching issues. Defaults to `false`. |
|
|
1719
1778
|
| `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. |
|
|
1720
1779
|
| `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. |
|
|
1721
1780
|
| `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"`. |
|
|
@@ -2015,6 +2074,228 @@ This analysis provides insights into:
|
|
|
2015
2074
|
- Resource usage at each step
|
|
2016
2075
|
- Performance optimization opportunities
|
|
2017
2076
|
|
|
2077
|
+
## Memory Usage Monitoring
|
|
2078
|
+
|
|
2079
|
+
[↑ Back to Top](#table-of-contents)
|
|
2080
|
+
|
|
2081
|
+
Forge-SQL-ORM provides automated memory usage 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.
|
|
2082
|
+
|
|
2083
|
+
### Why Memory Monitoring is Critical
|
|
2084
|
+
|
|
2085
|
+
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:
|
|
2086
|
+
|
|
2087
|
+
- **Detecting memory-intensive queries** before they hit the 16 MiB limit
|
|
2088
|
+
- **Providing detailed memory metrics** including average and maximum memory usage
|
|
2089
|
+
- **Showing execution plans** to help optimize memory consumption
|
|
2090
|
+
- **Configurable thresholds** to match your application's memory requirements
|
|
2091
|
+
- **Scheduled monitoring** via Forge scheduler triggers
|
|
2092
|
+
|
|
2093
|
+
### Overview
|
|
2094
|
+
|
|
2095
|
+
The memory monitoring system:
|
|
2096
|
+
- **Automatically detects memory-intensive queries** based on configurable memory thresholds
|
|
2097
|
+
- **Provides detailed memory metrics** including execution time, memory usage, and execution plans
|
|
2098
|
+
- **Logs memory issues** to the Forge Developer Console for easy debugging
|
|
2099
|
+
- **Supports scheduled monitoring** via Forge scheduler triggers
|
|
2100
|
+
- **Filters out system queries** to focus on your application's performance
|
|
2101
|
+
|
|
2102
|
+
### Key Features
|
|
2103
|
+
|
|
2104
|
+
- **Memory-Focused Monitoring**: Primary focus on memory usage with configurable thresholds
|
|
2105
|
+
- **Atlassian 16 MiB Limit Awareness**: Designed specifically for Forge SQL's memory constraints
|
|
2106
|
+
- **Execution Plan Analysis**: Shows detailed query plans to help optimize memory consumption
|
|
2107
|
+
- **Configurable Thresholds**: Set custom memory usage thresholds (default: 4MB warning)
|
|
2108
|
+
- **Automatic Filtering**: Excludes system queries (`Use`, `Set`, `Show`) and empty queries
|
|
2109
|
+
- **Scheduled Monitoring**: Run automatically on configurable intervals
|
|
2110
|
+
|
|
2111
|
+
### Basic Usage
|
|
2112
|
+
|
|
2113
|
+
#### 1. Import the Trigger
|
|
2114
|
+
|
|
2115
|
+
```typescript
|
|
2116
|
+
import ForgeSQL, { topSlowestStatementLastHourTrigger } from "forge-sql-orm";
|
|
2117
|
+
```
|
|
2118
|
+
|
|
2119
|
+
#### 2. Create a Scheduler Function
|
|
2120
|
+
|
|
2121
|
+
```typescript
|
|
2122
|
+
import ForgeSQL, { topSlowestStatementLastHourTrigger } from 'forge-sql-orm';
|
|
2123
|
+
|
|
2124
|
+
// Initialize ForgeSQL ORM instance
|
|
2125
|
+
const forgeSQL = new ForgeSQL();
|
|
2126
|
+
|
|
2127
|
+
// Basic usage with default thresholds (300ms latency, 8MB memory warning)
|
|
2128
|
+
export const memoryUsageTrigger = () =>
|
|
2129
|
+
topSlowestStatementLastHourTrigger(forgeSQL);
|
|
2130
|
+
|
|
2131
|
+
// Conservative memory monitoring: 4MB warning (well below 16MB limit)
|
|
2132
|
+
export const conservativeMemoryTrigger = () =>
|
|
2133
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { memoryThresholdBytes: 4 * 1024 * 1024 });
|
|
2134
|
+
|
|
2135
|
+
// Aggressive memory monitoring: 12MB warning (75% of 16MB limit)
|
|
2136
|
+
export const aggressiveMemoryTrigger = () =>
|
|
2137
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { memoryThresholdBytes: 12 * 1024 * 1024 });
|
|
2138
|
+
|
|
2139
|
+
// Memory-only monitoring: Only trigger on memory usage (latency effectively disabled)
|
|
2140
|
+
export const memoryOnlyTrigger = () =>
|
|
2141
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { warnThresholdMs: 10000, memoryThresholdBytes: 4 * 1024 * 1024 });
|
|
2142
|
+
|
|
2143
|
+
// Latency-only monitoring: Only trigger on slow queries (memory effectively disabled)
|
|
2144
|
+
export const latencyOnlyTrigger = () =>
|
|
2145
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { warnThresholdMs: 500, memoryThresholdBytes: 16 * 1024 * 1024 });
|
|
2146
|
+
|
|
2147
|
+
// With execution plan in logs
|
|
2148
|
+
export const withPlanTrigger = () =>
|
|
2149
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { showPlan: true });
|
|
2150
|
+
|
|
2151
|
+
// With cache logging enabled
|
|
2152
|
+
export const withCacheLoggingTrigger = () =>
|
|
2153
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { logCache: true });
|
|
2154
|
+
|
|
2155
|
+
// With both execution plan and cache logging
|
|
2156
|
+
export const withFullLoggingTrigger = () =>
|
|
2157
|
+
topSlowestStatementLastHourTrigger(forgeSQL, { showPlan: true, logCache: true });
|
|
2158
|
+
|
|
2159
|
+
// With custom ORM options for debugging
|
|
2160
|
+
const forgeSQL = new ForgeSQL({
|
|
2161
|
+
logRawSqlQuery: true,
|
|
2162
|
+
logCache: true,
|
|
2163
|
+
cacheEntityName: "cache"
|
|
2164
|
+
});
|
|
2165
|
+
|
|
2166
|
+
|
|
2167
|
+
#### 3. Configure in manifest.yml
|
|
2168
|
+
|
|
2169
|
+
**As Scheduler Trigger (Recommended for Production):**
|
|
2170
|
+
```yaml
|
|
2171
|
+
scheduledTrigger:
|
|
2172
|
+
- key: memory-usage-trigger
|
|
2173
|
+
function: memoryUsageTrigger
|
|
2174
|
+
interval: hour # Required: only hour interval is supported
|
|
2175
|
+
|
|
2176
|
+
function:
|
|
2177
|
+
- key: memoryUsageTrigger
|
|
2178
|
+
handler: index.memoryUsageTrigger
|
|
2179
|
+
```
|
|
2180
|
+
|
|
2181
|
+
**As Web Trigger (Development Only):**
|
|
2182
|
+
```yaml
|
|
2183
|
+
webtrigger:
|
|
2184
|
+
- key: print-slowest-queries
|
|
2185
|
+
function: memoryUsageTrigger
|
|
2186
|
+
|
|
2187
|
+
function:
|
|
2188
|
+
- key: memoryUsageTrigger
|
|
2189
|
+
handler: index.memoryUsageTrigger
|
|
2190
|
+
```
|
|
2191
|
+
|
|
2192
|
+
> **⚠️ Important**: Web triggers are not recommended for production as they violate the "run-on-atlassian" principle. Use scheduler triggers for production monitoring.
|
|
2193
|
+
|
|
2194
|
+
### How It Works
|
|
2195
|
+
|
|
2196
|
+
The memory monitoring trigger works differently depending on how it's configured:
|
|
2197
|
+
|
|
2198
|
+
#### Scheduler Trigger Mode (Production)
|
|
2199
|
+
|
|
2200
|
+
When used as a **scheduler trigger**, the system:
|
|
2201
|
+
- **Runs automatically** on the configured interval (hour only)
|
|
2202
|
+
- **Logs to Forge Developer Console** only when thresholds are exceeded
|
|
2203
|
+
- **No HTTP response** - operates silently in the background
|
|
2204
|
+
- **Perfect for production** monitoring without violating "run-on-atlassian"
|
|
2205
|
+
|
|
2206
|
+
**Example Console Log Output:**
|
|
2207
|
+
```
|
|
2208
|
+
1. Select avg=3006.03ms max=3006.03ms mem≈0.08MB(max 0.08MB) exec=1
|
|
2209
|
+
digest=28344800f90f6c929484e83337404df7e55a660c5f4ce922c4b298ab5e90c425
|
|
2210
|
+
sql=select `demo_users` . `id` as `a_userid_id` , `demo_users` . `name` as `a_username_name` , `demo_orders` . `product` as `a_product_product` , `demo_orders` . `id` as `a_productid_id` , `sleep` ( ? ) from `demo_users` inner join `demo_orders` on `demo_orders` . `user_id` = `demo_users` . `id`
|
|
2211
|
+
|
|
2212
|
+
full plan:
|
|
2213
|
+
id task estRows operator info actRows execution info memory disk
|
|
2214
|
+
Projection_7 root 2.50 forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_users.id, forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_users.name, forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_orders.product, forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_orders.id, sleep(?)->Column#7 3 time:3s, loops:2, Concurrency:OFF 1.98 KB N/A
|
|
2215
|
+
└─IndexHashJoin_14 root 2.50 inner join, inner:IndexLookUp_11, outer key:forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_users.id, inner key:forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_orders.user_id, equal cond:eq(forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_users.id, forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_orders.user_id) 3 time:2.11ms, loops:2, inner:{total:1.31ms, concurrency:5, task:1, construct:6.62µs, fetch:1.3ms, build:4.68µs, join:6.14µs} 57.9 KB N/A
|
|
2216
|
+
```
|
|
2217
|
+
|
|
2218
|
+
#### Web Trigger Mode (Development)
|
|
2219
|
+
|
|
2220
|
+
When used as a **web trigger**, the system:
|
|
2221
|
+
- **Runs on-demand** when the web endpoint is called
|
|
2222
|
+
- **Returns JSON response** with detailed metrics
|
|
2223
|
+
- **Logs to console** AND provides structured data
|
|
2224
|
+
- **Useful for development** and debugging
|
|
2225
|
+
|
|
2226
|
+
**Example JSON Response:**
|
|
2227
|
+
```json
|
|
2228
|
+
{
|
|
2229
|
+
"success": true,
|
|
2230
|
+
"window": "last_1h",
|
|
2231
|
+
"top": 1,
|
|
2232
|
+
"warnThresholdMs": 300,
|
|
2233
|
+
"memoryThresholdBytes": 8388608,
|
|
2234
|
+
"rows": [
|
|
2235
|
+
{
|
|
2236
|
+
"rank": 1,
|
|
2237
|
+
"digest": "abc123...",
|
|
2238
|
+
"stmtType": "Select",
|
|
2239
|
+
"schemaName": "myapp",
|
|
2240
|
+
"execCount": 150,
|
|
2241
|
+
"avgLatencyMs": 450.25,
|
|
2242
|
+
"maxLatencyMs": 1200.50,
|
|
2243
|
+
"minLatencyMs": 200.10,
|
|
2244
|
+
"avgProcessTimeMs": 400.20,
|
|
2245
|
+
"avgWaitTimeMs": 50.05,
|
|
2246
|
+
"avgBackoffTimeMs": 0.00,
|
|
2247
|
+
"avgMemMB": 2.5,
|
|
2248
|
+
"maxMemMB": 8.2,
|
|
2249
|
+
"avgMemBytes": 2621440,
|
|
2250
|
+
"maxMemBytes": 8598323,
|
|
2251
|
+
"avgTotalKeys": 1000,
|
|
2252
|
+
"firstSeen": "2024-01-15 10:30:00",
|
|
2253
|
+
"lastSeen": "2024-01-15 11:30:00",
|
|
2254
|
+
"planInCache": true,
|
|
2255
|
+
"planCacheHits": 120,
|
|
2256
|
+
"digestText": "SELECT * FROM users WHERE active = ?",
|
|
2257
|
+
"plan": "IndexScan(users, idx_active)..."
|
|
2258
|
+
}
|
|
2259
|
+
],
|
|
2260
|
+
"generatedAt": "2024-01-15T11:30:00.000Z"
|
|
2261
|
+
}
|
|
2262
|
+
```
|
|
2263
|
+
|
|
2264
|
+
### Configuration Options
|
|
2265
|
+
|
|
2266
|
+
#### Threshold Parameters
|
|
2267
|
+
|
|
2268
|
+
| Parameter | Type | Default | Description |
|
|
2269
|
+
|-----------|------|---------|-------------|
|
|
2270
|
+
| `warnThresholdMs` | `number` | `300` | Latency threshold in milliseconds (secondary) |
|
|
2271
|
+
| `memoryThresholdBytes` | `number` | `8 * 1024 * 1024` | **Memory usage threshold in bytes (primary focus)** |
|
|
2272
|
+
| `showPlan` | `boolean` | `false` | Whether to include execution plan in logs |
|
|
2273
|
+
| `logCache` | `boolean` | `false` | Whether to log cache operations |
|
|
2274
|
+
|
|
2275
|
+
**⚠️ Important: OR Logic**
|
|
2276
|
+
The monitoring uses **OR logic** - if **either** threshold is exceeded, the query will be logged/returned:
|
|
2277
|
+
- Query exceeds `warnThresholdMs` **OR** `memoryThresholdBytes` → Included in results
|
|
2278
|
+
- This means you can set different thresholds for different monitoring priorities
|
|
2279
|
+
- No need to exceed both thresholds simultaneously
|
|
2280
|
+
|
|
2281
|
+
**💡 Pro Tips:**
|
|
2282
|
+
- **Memory-only monitoring**: Set `warnThresholdMs` to a very high value (e.g., 10000ms) to trigger only on memory usage
|
|
2283
|
+
- **Latency-only monitoring**: Set `memoryThresholdBytes` to 16MB (16 * 1024 * 1024) to trigger only on latency
|
|
2284
|
+
- **Combined monitoring**: Use both thresholds for comprehensive monitoring
|
|
2285
|
+
- **Execution plan analysis**: Set `showPlan: true` to include detailed execution plans in logs (useful for debugging)
|
|
2286
|
+
- **Cache debugging**: Set `logCache: true` to log cache operations and debug caching issues
|
|
2287
|
+
|
|
2288
|
+
**Memory Threshold Guidelines:**
|
|
2289
|
+
- **Conservative**: 4MB (25% of 16MB limit)
|
|
2290
|
+
- **Default**: 8MB (50% of 16MB limit)
|
|
2291
|
+
- **Aggressive**: 12MB (75% of 16MB limit)
|
|
2292
|
+
- **Critical**: 14MB (87.5% of 16MB limit)
|
|
2293
|
+
|
|
2294
|
+
#### Available Intervals
|
|
2295
|
+
|
|
2296
|
+
- `hour` - **Every hour (Required)** - Statistics are available for approximately 12 hours
|
|
2297
|
+
|
|
2298
|
+
> **⚠️ Important**: Due to Forge SQL's statistics retention policy (approximately 12 hours), **only `hour` interval is supported**. Using `day` or `week` intervals will result in incomplete or missing data.
|
|
2018
2299
|
|
|
2019
2300
|
## Migration Guide
|
|
2020
2301
|
|
|
@@ -2107,6 +2388,16 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
|
|
|
2107
2388
|
300
|
|
2108
2389
|
);
|
|
2109
2390
|
|
|
2391
|
+
// ✅ Raw SQL execution with metadata capture
|
|
2392
|
+
const usersWithMetadata = await forgeSQL.executeWithMetadata(
|
|
2393
|
+
async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
|
|
2394
|
+
(totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
|
|
2395
|
+
console.log(`DB execution time: ${totalDbExecutionTime}ms`);
|
|
2396
|
+
console.log(`Response size: ${totalResponseSize} bytes`);
|
|
2397
|
+
console.log('Forge metadata:', forgeMetadata);
|
|
2398
|
+
}
|
|
2399
|
+
);
|
|
2400
|
+
|
|
2110
2401
|
// ✅ Common Table Expressions (CTEs)
|
|
2111
2402
|
const userStats = await forgeSQL
|
|
2112
2403
|
.with(
|