@@ -296,8 +296,10 @@ export default class MetricsAggregator {
296296
297297 /**
298298 * Flush all pending metrics to exporter. Never throws.
299+ *
300+ * @param resetTimer If true, resets the flush timer after flushing (default: true)
299301 */
300- flush ( ) : void {
302+ flush ( resetTimer : boolean = true ) : void {
301303 const logger = this . context . getLogger ( ) ;
302304
303305 try {
@@ -312,6 +314,12 @@ export default class MetricsAggregator {
312314
313315 // Export metrics (exporter.export never throws)
314316 this . exporter . export ( metricsToExport ) ;
317+
318+ // Reset timer to avoid rapid successive flushes (e.g., batch flush at 25s then timer flush at 30s)
319+ // This ensures consistent spacing between exports and helps avoid rate limiting
320+ if ( resetTimer ) {
321+ this . startFlushTimer ( ) ;
322+ }
315323 } catch ( error : any ) {
316324 // CRITICAL: All exceptions swallowed and logged at debug level ONLY
317325 logger . log ( LogLevel . debug , `MetricsAggregator.flush error: ${ error . message } ` ) ;
@@ -330,7 +338,8 @@ export default class MetricsAggregator {
330338 }
331339
332340 this . flushTimer = setInterval ( ( ) => {
333- this . flush ( ) ;
341+ // Don't reset timer when flush is triggered by the timer itself
342+ this . flush ( false ) ;
334343 } , this . flushIntervalMs ) ;
335344
336345 // Prevent timer from keeping Node.js process alive
@@ -359,8 +368,8 @@ export default class MetricsAggregator {
359368 this . completeStatement ( statementId ) ;
360369 }
361370
362- // Final flush
363- this . flush ( ) ;
371+ // Final flush - don't reset timer since we're closing
372+ this . flush ( false ) ;
364373 } catch ( error : any ) {
365374 // CRITICAL: All exceptions swallowed and logged at debug level ONLY
366375 logger . log ( LogLevel . debug , `MetricsAggregator.close error: ${ error . message } ` ) ;
0 commit comments