@@ -3,10 +3,11 @@ import WebSocket from 'ws';
33const WebSocketServer = ( WebSocket as any ) . Server as typeof import ( 'ws' ) . WebSocketServer ;
44import { Duplex } from 'stream' ;
55import { IncomingMessage } from 'http' ;
6- import { Config , Logger } from '@browserless.io/browserless' ;
6+ import { Config } from '@browserless.io/browserless' ;
77import { Duration , Effect , Exit , FiberSet , Queue , Schedule , Schema , Scope , Stream } from 'effect' ;
88
99import { incCounter , proxyDroppedMessages , wsLifecycle } from './effect-metrics.js' ;
10+ import { runForkInServer } from './otel-runtime.js' ;
1011import { CloudflareConfig } from './shared/cloudflare-detection.js' ;
1112import { CdpSessionId , TargetId } from './shared/cloudflare-detection.js' ;
1213import { BROWSER_WS_PING_INTERVAL , BROWSER_WS_PONG_TIMEOUT_MS } from './session/cf/cf-schedules.js' ;
@@ -114,7 +115,6 @@ export class CDPProxy {
114115 private clientOutbound : Queue . Queue < ClientOutboundMessage > | null = null ;
115116 private isClosing = false ;
116117 private closeRequested = false ;
117- private log = new Logger ( 'cdp-proxy' ) ;
118118 private getTabCount ?: ( ) => number ;
119119 private readonly proxyScope = Scope . makeUnsafe ( ) ;
120120 private readonly fibers = Effect . runSync (
@@ -190,7 +190,7 @@ export class CDPProxy {
190190 const ws = this . browserWs ! ;
191191 const onOpen = ( ) => {
192192 ws . removeListener ( 'error' , onError ) ;
193- this . log . trace ( ` Connected to browser: ${ this . browserWsEndpoint } ` ) ;
193+ runForkInServer ( Effect . logDebug ( ' Connected to browser' ) . pipe ( Effect . annotateLogs ( { endpoint : this . browserWsEndpoint } ) ) ) ;
194194 resume ( Effect . void ) ;
195195 } ;
196196 const onError = ( err : Error ) => {
@@ -222,7 +222,7 @@ export class CDPProxy {
222222 // Setup AFTER successful upgrade
223223 this . clientWs = clientWs ;
224224 Effect . runSync ( incCounter ( wsLifecycle , { type : 'proxy_client' , action : 'create' } ) ) ;
225- this . log . trace ( 'Client WebSocket upgraded' ) ;
225+ runForkInServer ( Effect . logDebug ( 'Client WebSocket upgraded' ) ) ;
226226
227227 // Scope-bound outbound queue: all client WS sends go through here.
228228 this . clientOutbound = Effect . runSync ( Queue . unbounded < ClientOutboundMessage > ( ) ) ;
@@ -254,12 +254,12 @@ export class CDPProxy {
254254 const sessionId = this . browserWsEndpoint . split ( '/' ) . pop ( ) || '' ;
255255 if ( sessionId ) {
256256 this . emitClientEvent ( 'Browserless.sessionInfo' , { sessionId } ) . catch ( ( e ) => {
257- this . log . debug ( ` Failed to emit sessionInfo: ${ e instanceof Error ? e . message : String ( e ) } ` ) ;
257+ runForkInServer ( Effect . logDebug ( ' Failed to emit sessionInfo' ) . pipe ( Effect . annotateLogs ( { error : e instanceof Error ? e . message : String ( e ) } ) ) ) ;
258258 } ) ;
259259 }
260260
261261 clientWs . on ( 'error' , ( err : Error ) => {
262- this . log . warn ( ` Client WebSocket error: ${ err . message } ` ) ;
262+ runForkInServer ( Effect . logWarning ( ' Client WebSocket error' ) . pipe ( Effect . annotateLogs ( { error : err . message } ) ) ) ;
263263 this . handleClose ( ) ;
264264 } ) ;
265265 } ) ( ) ,
@@ -366,7 +366,7 @@ export class CDPProxy {
366366 // Sync check — fast path when CdpSession is tracking targets
367367 const count = this . getTabCount ( ) ;
368368 if ( count >= limit ) {
369- this . log . warn ( ` Tab limit reached ( ${ count } / ${ limit } ), rejecting Target.createTarget` ) ;
369+ runForkInServer ( Effect . logWarning ( ' Tab limit reached, rejecting Target.createTarget' ) . pipe ( Effect . annotateLogs ( { count : String ( count ) , limit : String ( limit ) } ) ) ) ;
370370 void this . sendClientError ( msg . id , - 32000 , `Tab limit exceeded (${ count } /${ limit } )` ) ;
371371 return ;
372372 }
@@ -390,9 +390,10 @@ export class CDPProxy {
390390 const clickCount = p ?. clickCount ?? 0 ;
391391 // Full CDP sessionId — maps to a specific target (tab/OOPIF)
392392 const cdpSessionId = msg . sessionId ?? 'page' ;
393- this . log . warn (
394- `[PYDOLL-MOUSE] ${ type } x=${ x } y=${ y } button=${ button } clicks=${ clickCount } cdpSession=${ cdpSessionId } ` ,
395- ) ;
393+ runForkInServer ( Effect . logWarning ( '[PYDOLL-MOUSE] dispatch' ) . pipe ( Effect . annotateLogs ( {
394+ type : String ( type ) , x : String ( x ) , y : String ( y ) , button : String ( button ) ,
395+ clickCount : String ( clickCount ) , cdpSession : String ( cdpSessionId ) ,
396+ } ) ) ) ;
396397 }
397398 } catch {
398399 // ignore parse errors
@@ -407,7 +408,7 @@ export class CDPProxy {
407408 if ( msg . method ) {
408409 const sid = msg . sessionId ? ` [sid=${ msg . sessionId . substring ( 0 , 16 ) } ]` : '' ;
409410 const params = msg . params ? JSON . stringify ( msg . params ) . substring ( 0 , 200 ) : '{}' ;
410- this . log . info ( ` [CDP→Chrome] id= ${ msg . id } ${ msg . method } ${ sid } ${ params } ` ) ;
411+ runForkInServer ( Effect . logInfo ( ' [CDP→Chrome]' ) . pipe ( Effect . annotateLogs ( { id : String ( msg . id ) , method : msg . method , sid : sid . trim ( ) , params } ) ) ) ;
411412 }
412413 } catch { /* ignore */ }
413414 }
@@ -431,7 +432,7 @@ export class CDPProxy {
431432 if ( this . cdpDebug && msg . method ) {
432433 const sid = msg . sessionId ? ` [sid=${ msg . sessionId . substring ( 0 , 16 ) } ]` : '' ;
433434 const params = msg . params ? JSON . stringify ( msg . params ) . substring ( 0 , 150 ) : '{}' ;
434- this . log . info ( ` [Chrome→CDP] ${ msg . method } ${ sid } ${ params } ` ) ;
435+ runForkInServer ( Effect . logInfo ( ' [Chrome→CDP]' ) . pipe ( Effect . annotateLogs ( { method : msg . method , sid : sid . trim ( ) , params } ) ) ) ;
435436 }
436437 }
437438 } catch { /* ignore parse errors */ }
@@ -443,12 +444,12 @@ export class CDPProxy {
443444
444445 // Handle close from either side
445446 this . clientWs . on ( 'close' , ( ) => {
446- this . log . trace ( 'Client WebSocket closed' ) ;
447+ runForkInServer ( Effect . logDebug ( 'Client WebSocket closed' ) ) ;
447448 this . handleClose ( ) ;
448449 } ) ;
449450
450451 this . browserWs . on ( 'close' , ( ) => {
451- this . log . trace ( 'Browser WebSocket closed' ) ;
452+ runForkInServer ( Effect . logDebug ( 'Browser WebSocket closed' ) ) ;
452453 this . handleClose ( ) ;
453454 } ) ;
454455
@@ -469,7 +470,7 @@ export class CDPProxy {
469470 Effect . tryPromise ( ( ) => this . onBeforeClose ! ( ) ) . pipe (
470471 Effect . timeout ( Duration . millis ( ON_BEFORE_CLOSE_TIMEOUT_MS ) ) ,
471472 Effect . catch ( ( e ) => Effect . sync ( ( ) => {
472- this . log . warn ( ` onBeforeClose failed: ${ e instanceof Error ? e . message : String ( e ) } ` ) ;
473+ runForkInServer ( Effect . logWarning ( ' onBeforeClose failed' ) . pipe ( Effect . annotateLogs ( { error : e instanceof Error ? e . message : String ( e ) } ) ) ) ;
473474 } ) ) ,
474475 ) ,
475476 ) ;
@@ -490,7 +491,7 @@ export class CDPProxy {
490491 if ( ! Queue . offerUnsafe ( this . clientOutbound ! , {
491492 data : message ,
492493 onSent : resolve ,
493- onError : ( err ) => { this . log . warn ( ` Failed to send CDP response id= ${ id } : ${ err . message } ` ) ; reject ( err ) ; } ,
494+ onError : ( err ) => { runForkInServer ( Effect . logWarning ( ' Failed to send CDP response' ) . pipe ( Effect . annotateLogs ( { id : String ( id ) , error : err . message } ) ) ) ; reject ( err ) ; } ,
494495 } ) ) {
495496 Effect . runSync ( incCounter ( proxyDroppedMessages , { direction : 'client' } ) ) ;
496497 resolve ( ) ;
@@ -505,7 +506,7 @@ export class CDPProxy {
505506 if ( ! Queue . offerUnsafe ( this . clientOutbound ! , {
506507 data : payload ,
507508 onSent : resolve ,
508- onError : ( err ) => { this . log . warn ( ` Failed to send CDP error id= ${ id } : ${ err . message } ` ) ; reject ( err ) ; } ,
509+ onError : ( err ) => { runForkInServer ( Effect . logWarning ( ' Failed to send CDP error' ) . pipe ( Effect . annotateLogs ( { id : String ( id ) , error : err . message } ) ) ) ; reject ( err ) ; } ,
509510 } ) ) {
510511 Effect . runSync ( incCounter ( proxyDroppedMessages , { direction : 'client' } ) ) ;
511512 resolve ( ) ;
@@ -528,13 +529,13 @@ export class CDPProxy {
528529 const targets : Array < { type : string } > = result ?. targetInfos ?? [ ] ;
529530 const count = targets . filter ( t => t . type === 'page' ) . length ;
530531 if ( count >= limit ) {
531- this . log . warn ( ` Tab limit reached ( ${ count } / ${ limit } ), rejecting Target.createTarget` ) ;
532+ runForkInServer ( Effect . logWarning ( ' Tab limit reached, rejecting Target.createTarget' ) . pipe ( Effect . annotateLogs ( { count : String ( count ) , limit : String ( limit ) } ) ) ) ;
532533 void this . sendClientError ( msgId , - 32000 , `Tab limit exceeded (${ count } /${ limit } )` ) ;
533534 return ;
534535 }
535536 } catch ( e ) {
536537 // If we can't determine tab count, allow the request through
537- this . log . debug ( ` Tab count check failed, allowing Target.createTarget: ${ e instanceof Error ? e . message : String ( e ) } ` ) ;
538+ runForkInServer ( Effect . logDebug ( ' Tab count check failed, allowing Target.createTarget' ) . pipe ( Effect . annotateLogs ( { error : e instanceof Error ? e . message : String ( e ) } ) ) ) ;
538539 }
539540 // Under limit or check failed — forward to browser
540541 this . sendToBrowser ( data , isBinary ) ;
@@ -549,15 +550,15 @@ export class CDPProxy {
549550 */
550551 async emitClientEvent ( method : string , params : object ) : Promise < void > {
551552 if ( ! this . clientOutbound ) {
552- this . log . warn ( ` Cannot inject event ${ method } : queue not initialized` ) ;
553+ runForkInServer ( Effect . logWarning ( ' Cannot inject event: queue not initialized' ) . pipe ( Effect . annotateLogs ( { method } ) ) ) ;
553554 return ;
554555 }
555556 const message = JSON . stringify ( { method, params } ) ;
556557 return new Promise < void > ( ( resolve , reject ) => {
557558 const offered = Queue . offerUnsafe ( this . clientOutbound ! , {
558559 data : message ,
559- onSent : ( ) => { this . log . trace ( ` Injected CDP event: ${ method } ` ) ; resolve ( ) ; } ,
560- onError : ( err ) => { this . log . warn ( ` Failed to inject CDP event ${ method } : ${ err . message } ` ) ; reject ( err ) ; } ,
560+ onSent : ( ) => { runForkInServer ( Effect . logDebug ( ' Injected CDP event' ) . pipe ( Effect . annotateLogs ( { method } ) ) ) ; resolve ( ) ; } ,
561+ onError : ( err ) => { runForkInServer ( Effect . logWarning ( ' Failed to inject CDP event' ) . pipe ( Effect . annotateLogs ( { method, error : err . message } ) ) ) ; reject ( err ) ; } ,
561562 } ) ;
562563 if ( ! offered ) {
563564 Effect . runSync ( incCounter ( proxyDroppedMessages , { direction : 'client' } ) ) ;
@@ -590,7 +591,7 @@ export class CDPProxy {
590591 if ( this . cdpDebug ) {
591592 const sid = sessionId ? ` [sid=${ sessionId . substring ( 0 , 16 ) } ]` : '' ;
592593 const p = JSON . stringify ( params ) . substring ( 0 , 200 ) ;
593- this . log . info ( ` [SOLVER→Chrome] ${ method } ${ sid } ${ p } ` ) ;
594+ runForkInServer ( Effect . logInfo ( ' [SOLVER→Chrome]' ) . pipe ( Effect . annotateLogs ( { method, sid : sid . trim ( ) , params : p } ) ) ) ;
594595 }
595596
596597 return conn . sendPromise ( method , params , sessionId , timeoutMs ) ;
@@ -678,12 +679,12 @@ export class CDPProxy {
678679 */
679680 async sendReplayComplete ( metadata : ReplayCompleteParams ) : Promise < void > {
680681 await this . emitClientEvent ( 'Browserless.replayComplete' , metadata ) ;
681- this . log . info ( ` Sent replay complete event: ${ metadata . id } ` ) ;
682+ runForkInServer ( Effect . logInfo ( ' Sent replay complete event' ) . pipe ( Effect . annotateLogs ( { replay_id : metadata . id } ) ) ) ;
682683 }
683684
684685 async sendTabReplayComplete ( metadata : TabReplayCompleteParams ) : Promise < void > {
685686 await this . emitClientEvent ( 'Browserless.tabReplayComplete' , metadata ) ;
686- this . log . info ( ` Sent tab replay complete event: targetId= ${ metadata . targetId } ` ) ;
687+ runForkInServer ( Effect . logInfo ( ' Sent tab replay complete event' ) . pipe ( Effect . annotateLogs ( { targetId : metadata . targetId } ) ) ) ;
687688 }
688689
689690 /**
@@ -732,15 +733,15 @@ export class CDPProxy {
732733 } ) ;
733734
734735 if ( ! gotPong ) {
735- this . log . warn ( 'Browser WS heartbeat timeout — Chrome not responding, closing session' ) ;
736+ runForkInServer ( Effect . logWarning ( 'Browser WS heartbeat timeout — Chrome not responding, closing session' ) ) ;
736737 this . handleClose ( ) ;
737738 }
738739 } ) ;
739740
740741 this . forkManaged (
741742 tick ( ) . pipe (
742743 Effect . catch ( ( e ) => Effect . sync ( ( ) => {
743- this . log . warn ( ` Browser WS ping failed, closing session: ${ e instanceof Error ? e . message : String ( e ) } ` ) ;
744+ runForkInServer ( Effect . logWarning ( ' Browser WS ping failed, closing session' ) . pipe ( Effect . annotateLogs ( { error : e instanceof Error ? e . message : String ( e ) } ) ) ) ;
744745 this . handleClose ( ) ;
745746 } ) ) ,
746747 Effect . repeat ( Schedule . fixed ( BROWSER_WS_PING_INTERVAL ) ) ,
@@ -779,10 +780,10 @@ export class CDPProxy {
779780
780781 const clientState = this . clientWs ?. readyState ;
781782 const browserState = this . browserWs ?. readyState ;
782- this . log . info (
783- `CDPProxy closing: clientWs= ${ clientState === WebSocket . OPEN ? 'OPEN' : clientState } ` +
784- ` browserWs= ${ browserState === WebSocket . OPEN ? 'OPEN' : browserState } `
785- ) ;
783+ runForkInServer ( Effect . logInfo ( 'CDPProxy closing' ) . pipe ( Effect . annotateLogs ( {
784+ clientWs : clientState === WebSocket . OPEN ? 'OPEN' : String ( clientState ) ,
785+ browserWs : browserState === WebSocket . OPEN ? 'OPEN' : String ( browserState ) ,
786+ } ) ) ) ;
786787
787788 // Await scope close so all acquireRelease finalizers fire before onClose
788789 this . closePromise = Effect . runPromise ( Scope . close ( this . proxyScope , Exit . void ) )
0 commit comments