@@ -146,7 +146,7 @@ suiteDescribe('runtimeMetrics', () => {
146146 }
147147 }
148148
149- setImmediate = globalThis . setImmediate
149+ setImmediate = require ( 'timers/promises' ) . setImmediate
150150 clock = sinon . useFakeTimers ( )
151151
152152 runtimeMetrics . start ( config )
@@ -188,79 +188,97 @@ suiteDescribe('runtimeMetrics', () => {
188188 } )
189189 } )
190190
191- it ( 'should start collecting runtimeMetrics every 10 seconds' , ( done ) => {
191+ it ( 'should start collecting runtimeMetrics every 10 seconds' , async ( ) => {
192192 runtimeMetrics . stop ( )
193193 runtimeMetrics . start ( config )
194194
195195 global . gc ( )
196196
197- setImmediate ( ( ) => setImmediate ( ( ) => { // Wait for GC observer to trigger.
198- clock . tick ( 10000 )
197+ // Wait for GC observer to trigger.
198+ await setImmediate ( )
199+ await setImmediate ( )
200+
201+ clock . tick ( 10000 )
202+
203+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.cpu.user' )
204+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.cpu.system' )
205+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.cpu.total' )
206+
207+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.mem.rss' )
208+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.mem.heap_total' )
209+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.mem.heap_used' )
210+
211+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.process.uptime' )
212+
213+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_heap_size' )
214+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_heap_size_executable' )
215+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_physical_size' )
216+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_available_size' )
217+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_heap_size' )
218+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.heap_size_limit' )
219+
220+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.malloced_memory' )
221+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.peak_malloced_memory' )
222+
223+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.max' , sinon . match . number )
224+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.min' , sinon . match . number )
225+ expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.sum' , sinon . match . number )
226+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.avg' , sinon . match . number )
227+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.median' , sinon . match . number )
228+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.95percentile' , sinon . match . number )
229+ expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.count' , sinon . match . number )
230+
231+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.utilization' )
232+
233+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.max' , sinon . match . number )
234+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.min' , sinon . match . number )
235+ expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.gc.pause.sum' , sinon . match . number )
236+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.avg' , sinon . match . number )
237+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.median' , sinon . match . number )
238+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.95percentile' , sinon . match . number )
239+ expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.gc.pause.count' , sinon . match . number )
240+
241+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.max' , sinon . match . number )
242+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.min' , sinon . match . number )
243+ expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.sum' , sinon . match . number )
244+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.avg' , sinon . match . number )
245+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.median' , sinon . match . number )
246+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.95percentile' , sinon . match . number )
247+ expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.count' , sinon . match . number )
248+ expect ( client . increment ) . to . have . been . calledWith (
249+ 'runtime.node.gc.pause.by.type.count' , sinon . match . any , sinon . match ( val => {
250+ return val && / ^ g c _ t y p e : [ a - z _ ] + $ / . test ( val [ 0 ] )
251+ } )
252+ )
253+
254+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.size.by.space' )
255+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.used_size.by.space' )
256+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.available_size.by.space' )
257+ expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.physical_size.by.space' )
258+
259+ expect ( client . flush ) . to . have . been . called
260+ } )
261+
262+ it ( 'should collect individual metrics only once every 10 seconds' , async ( ) => {
263+ runtimeMetrics . stop ( )
264+ runtimeMetrics . start ( config )
265+
266+ global . gc ( )
267+
268+ // Wait for GC observer to trigger.
269+ await setImmediate ( )
270+ await setImmediate ( )
271+
272+ clock . tick ( 60 * 60 * 1000 )
199273
200- try {
201- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.cpu.user' )
202- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.cpu.system' )
203- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.cpu.total' )
204-
205- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.mem.rss' )
206- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.mem.heap_total' )
207- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.mem.heap_used' )
208-
209- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.process.uptime' )
210-
211- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_heap_size' )
212- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_heap_size_executable' )
213- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_physical_size' )
214- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_available_size' )
215- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.total_heap_size' )
216- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.heap_size_limit' )
217-
218- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.malloced_memory' )
219- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.peak_malloced_memory' )
220-
221- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.max' , sinon . match . number )
222- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.min' , sinon . match . number )
223- expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.sum' , sinon . match . number )
224- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.avg' , sinon . match . number )
225- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.median' , sinon . match . number )
226- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.95percentile' , sinon . match . number )
227- expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.event_loop.delay.count' , sinon . match . number )
228-
229- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.event_loop.utilization' )
230-
231- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.max' , sinon . match . number )
232- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.min' , sinon . match . number )
233- expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.gc.pause.sum' , sinon . match . number )
234- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.avg' , sinon . match . number )
235- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.median' , sinon . match . number )
236- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.95percentile' , sinon . match . number )
237- expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.gc.pause.count' , sinon . match . number )
238-
239- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.max' , sinon . match . number )
240- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.min' , sinon . match . number )
241- expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.sum' , sinon . match . number )
242- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.avg' , sinon . match . number )
243- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.median' , sinon . match . number )
244- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.95percentile' , sinon . match . number )
245- expect ( client . increment ) . to . have . been . calledWith ( 'runtime.node.gc.pause.by.type.count' , sinon . match . number )
246- expect ( client . increment ) . to . have . been . calledWith (
247- 'runtime.node.gc.pause.by.type.count' , sinon . match . any , sinon . match ( val => {
248- return val && / ^ g c _ t y p e : [ a - z _ ] + $ / . test ( val [ 0 ] )
249- } )
250- )
251-
252- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.size.by.space' )
253- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.used_size.by.space' )
254- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.available_size.by.space' )
255- expect ( client . gauge ) . to . have . been . calledWith ( 'runtime.node.heap.physical_size.by.space' )
256-
257- expect ( client . flush ) . to . have . been . called
258-
259- done ( )
260- } catch ( e ) {
261- done ( e )
262- }
263- } ) )
274+ // If a metric is leaking, it will leak expontentially because it will
275+ // be sent one more time each flush, in addition to the previous
276+ // flushes that also had the metric multiple times in them, so after
277+ // 1 hour even if a single metric is leaking it would get over
278+ // 64980 calls on its own without any other metric. A slightly lower
279+ // value is used here to be on the safer side.
280+ expect ( client . gauge . callCount ) . to . be . lt ( 60000 )
281+ expect ( client . increment . callCount ) . to . be . lt ( 60000 )
264282 } )
265283 } )
266284
0 commit comments