@@ -1632,6 +1632,158 @@ export default class DBSQLClient extends EventEmitter implements IDBSQLClient, I
16321632
16331633---
16341634
1635+ ## 6.5 Telemetry Export Lifecycle
1636+
1637+ This section clarifies ** when** telemetry logs are exported during different lifecycle events.
1638+
1639+ ### Export Triggers
1640+
1641+ Telemetry export can be triggered by:
1642+ 1 . ** Batch size threshold** - When pending metrics reach configured batch size (default: 100)
1643+ 2 . ** Periodic timer** - Every flush interval (default: 5 seconds)
1644+ 3 . ** Statement close** - Completes statement aggregation, may trigger batch export if batch full
1645+ 4 . ** Connection close** - Final flush of all pending metrics
1646+ 5 . ** Terminal error** - Immediate flush for non-retryable errors
1647+
1648+ ### Statement Close (DBSQLOperation.close())
1649+
1650+ ** What happens:**
1651+ ``` typescript
1652+ // In DBSQLOperation.close()
1653+ try {
1654+ // 1. Emit statement.complete event with latency and metrics
1655+ this .telemetryEmitter .emitStatementComplete ({
1656+ statementId: this .statementId ,
1657+ sessionId: this .sessionId ,
1658+ latencyMs: Date .now () - this .startTime ,
1659+ resultFormat: this .resultFormat ,
1660+ chunkCount: this .chunkCount ,
1661+ bytesDownloaded: this .bytesDownloaded ,
1662+ pollCount: this .pollCount ,
1663+ });
1664+
1665+ // 2. Mark statement complete in aggregator
1666+ this .telemetryAggregator .completeStatement (this .statementId );
1667+ } catch (error : any ) {
1668+ // All exceptions swallowed
1669+ logger .log (LogLevel .debug , ` Error in telemetry: ${error .message } ` );
1670+ }
1671+ ```
1672+
1673+ ** Export behavior:**
1674+ - Statement metrics are ** aggregated and added to pending batch**
1675+ - Export happens ** ONLY if batch size threshold is reached**
1676+ - Otherwise, metrics remain buffered until next timer flush or connection close
1677+ - ** Does NOT automatically export** - just completes the aggregation
1678+
1679+ ### Connection Close (DBSQLClient.close())
1680+
1681+ ** What happens:**
1682+ ``` typescript
1683+ // In DBSQLClient.close()
1684+ try {
1685+ // 1. Close aggregator (stops timer, completes statements, final flush)
1686+ if (this .telemetryAggregator ) {
1687+ this .telemetryAggregator .close ();
1688+ }
1689+
1690+ // 2. Release telemetry client (decrements ref count, closes if last)
1691+ if (this .telemetryClientProvider ) {
1692+ await this .telemetryClientProvider .releaseClient (this .host );
1693+ }
1694+
1695+ // 3. Release feature flag context (decrements ref count)
1696+ if (this .featureFlagCache ) {
1697+ this .featureFlagCache .releaseContext (this .host );
1698+ }
1699+ } catch (error : any ) {
1700+ logger .log (LogLevel .debug , ` Telemetry cleanup error: ${error .message } ` );
1701+ }
1702+ ```
1703+
1704+ ** Export behavior:**
1705+ - ** ALWAYS exports** all pending metrics via ` aggregator.close() `
1706+ - Stops the periodic flush timer
1707+ - Completes any incomplete statements in the aggregation map
1708+ - Performs final flush to ensure no metrics are lost
1709+ - ** Guarantees export** of all buffered telemetry before connection closes
1710+
1711+ ** Aggregator.close() implementation:**
1712+ ``` typescript
1713+ // In MetricsAggregator.close()
1714+ close (): void {
1715+ const logger = this .context .getLogger ();
1716+
1717+ try {
1718+ // Step 1: Stop flush timer
1719+ if (this .flushTimer ) {
1720+ clearInterval (this .flushTimer );
1721+ this .flushTimer = null ;
1722+ }
1723+
1724+ // Step 2: Complete any remaining statements
1725+ for (const statementId of this .statementMetrics .keys ()) {
1726+ this .completeStatement (statementId );
1727+ }
1728+
1729+ // Step 3: Final flush
1730+ this .flush ();
1731+ } catch (error : any ) {
1732+ logger .log (LogLevel .debug , ` MetricsAggregator.close error: ${error .message } ` );
1733+ }
1734+ }
1735+ ```
1736+
1737+ ### Process Exit (Node.js shutdown)
1738+
1739+ ** What happens:**
1740+ - ** NO automatic export** if ` DBSQLClient.close() ` was not called
1741+ - Telemetry is lost if process exits without proper cleanup
1742+ - ** Best practice** : Always call ` client.close() ` before exit
1743+
1744+ ** Recommended pattern:**
1745+ ``` typescript
1746+ const client = new DBSQLClient ();
1747+
1748+ // Register cleanup on process exit
1749+ process .on (' SIGINT' , async () => {
1750+ await client .close (); // Ensures final telemetry flush
1751+ process .exit (0 );
1752+ });
1753+
1754+ process .on (' SIGTERM' , async () => {
1755+ await client .close (); // Ensures final telemetry flush
1756+ process .exit (0 );
1757+ });
1758+ ```
1759+
1760+ ### Summary Table
1761+
1762+ | Event | Statement Aggregated | Export Triggered | Notes |
1763+ | -------| ---------------------| ------------------| -------|
1764+ | ** Statement Close** | ✅ Yes | ⚠️ Only if batch full | Metrics buffered, not immediately exported |
1765+ | ** Batch Size Reached** | N/A | ✅ Yes | Automatic export when 100 metrics buffered |
1766+ | ** Periodic Timer** | N/A | ✅ Yes | Every 5 seconds (configurable) |
1767+ | ** Connection Close** | ✅ Yes (incomplete) | ✅ Yes (guaranteed) | Completes all statements, flushes all metrics |
1768+ | ** Process Exit** | ❌ No | ❌ No | Lost unless ` close() ` was called first |
1769+ | ** Terminal Error** | N/A | ✅ Yes (immediate) | Auth errors, 4xx errors flushed right away |
1770+
1771+ ### Key Differences from JDBC
1772+
1773+ ** Node.js behavior:**
1774+ - Statement close does ** not** automatically export (buffered until batch/timer/connection-close)
1775+ - Connection close ** always** exports all pending metrics
1776+ - Process exit does ** not** guarantee export (must call ` close() ` explicitly)
1777+
1778+ ** JDBC behavior:**
1779+ - Similar buffering and batch export strategy
1780+ - JVM shutdown hooks provide more automatic cleanup
1781+ - Connection close behavior is the same (guaranteed flush)
1782+
1783+ ** Recommendation** : Always call ` client.close() ` in a ` finally ` block or using ` try-finally ` to ensure telemetry is exported before the process exits.
1784+
1785+ ---
1786+
16351787## 7. Privacy & Compliance
16361788
16371789### 7.1 Data Privacy
0 commit comments