@@ -317,6 +317,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
317317 const pageId = query . page ;
318318 const debuggerRelativeBaseUrl =
319319 getBaseUrlFromRequest ( req ) ?? this . #serverBaseUrl;
320+ const appId = this . #devices. get ( deviceId ) ?. getApp ( ) || 'unknown' ;
320321
321322 if ( deviceId == null || pageId == null ) {
322323 throw new Error ( 'Incorrect URL - must provide device and page IDs' ) ;
@@ -329,7 +330,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
329330
330331 this . #logger?. info ( 'Connection to DevTools established.' ) ;
331332
332- this . #startHeartbeat( socket , DEBUGGER_HEARTBEAT_INTERVAL_MS ) ;
333+ this . #startHeartbeat( socket , DEBUGGER_HEARTBEAT_INTERVAL_MS , appId ) ;
333334
334335 device . handleDebuggerConnection ( socket , pageId , {
335336 debuggerRelativeBaseUrl,
@@ -357,9 +358,10 @@ export default class InspectorProxy implements InspectorProxyQueries {
357358 // where proxies may drop idle connections (e.g., VS Code tunnels).
358359 //
359360 // https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2
360- #startHeartbeat( socket : WS , intervalMs : number ) {
361+ #startHeartbeat( socket : WS , intervalMs : number , appId : string ) {
361362 let shouldSetTerminateTimeout = false ;
362363 let terminateTimeout = null ;
364+ let latestPingMs = Date . now ( ) ;
363365
364366 const pingTimeout : Timeout = setTimeout ( ( ) => {
365367 if ( socket . readyState !== WS . OPEN ) {
@@ -369,6 +371,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
369371 }
370372
371373 shouldSetTerminateTimeout = true ;
374+ latestPingMs = Date . now ( ) ;
372375 socket . ping ( ( ) => {
373376 if ( ! shouldSetTerminateTimeout ) {
374377 // Sometimes, this `sent` callback fires later than
@@ -394,6 +397,11 @@ export default class InspectorProxy implements InspectorProxyQueries {
394397 this . #logger?. error (
395398 `Connection terminated with DevTools after not responding for ${ MAX_PONG_LATENCY_MS / 1000 } seconds.` ,
396399 ) ;
400+ this . #eventReporter?. logEvent ( {
401+ type : 'debugger_timeout' ,
402+ duration : MAX_PONG_LATENCY_MS ,
403+ appId,
404+ } ) ;
397405 } , MAX_PONG_LATENCY_MS ) . unref ( ) ;
398406 } ) ;
399407 } , intervalMs ) . unref ( ) ;
@@ -404,8 +412,17 @@ export default class InspectorProxy implements InspectorProxyQueries {
404412 pingTimeout . refresh ( ) ;
405413 } ;
406414
407- socket . on ( 'pong' , onAnyMessageFromDebugger ) ;
408- socket . on ( 'message' , onAnyMessageFromDebugger ) ;
415+ socket . on ( 'pong' , ( ) => {
416+ onAnyMessageFromDebugger ( ) ;
417+ this . #eventReporter?. logEvent ( {
418+ type : 'debugger_heartbeat' ,
419+ duration : Date . now ( ) - latestPingMs ,
420+ appId,
421+ } ) ;
422+ } ) ;
423+ socket . on ( 'message' , ( ) => {
424+ onAnyMessageFromDebugger ( ) ;
425+ } ) ;
409426
410427 socket . on ( 'close' , ( code : number , reason : string ) => {
411428 this . #logger?. info (
0 commit comments