import type { Destroyable } from '../destroyable/Destroyable' ; import LogLevel from '../logger/LogLevel' ; import MeetingSessionConfiguration from '../meetingsession/MeetingSessionConfiguration' ; import IntervalScheduler from '../scheduler/IntervalScheduler' ; import Log from './Log' ; /**
 * `MeetingSessionPOSTLogger` publishes log messages in batches to a URL
 * supplied during its construction.
 *
 * Be sure to call  MeetingSessionPOSTLogger . destroy when you're done
 * with the logger in order to avoid leaks.
  export default class MeetingSessionPOSTLogger implements Destroyable { private logCapture : Log [ ] = [ ] ; private sequenceNumber : number = 0 ; private lock = false ; private intervalScheduler : IntervalScheduler ; private eventListener : undefined | ( ( ) => void ) ; constructor ( private name , private configuration , private batchSize , private intervalMs , private url , private level = LogLevel . WARN , private headers ? ) { this . startLogPublishScheduler ( this . batchSize ) ; this . eventListener = ( ) => { this . stop ( ) ; } ; this . addEventListener ( ) ; } addEventListener ( ) { if ( ! this . eventListener || ! ( 'window' in global ) || ! window . addEventListener ) { return ; } window . addEventListener ( 'unload' , this . eventListener ) ; } removeEventListener ( ) { if ( ! this . eventListener || ! ( 'window' in global ) || ! window . removeEventListener ) { return ; } window . removeEventListener ( 'unload' , this . eventListener ) ; } debug ( debugFunction ) { if ( LogLevel . DEBUG < this . level ) { return ; } if ( typeof debugFunction === 'string' ) { this . log ( LogLevel . DEBUG , debugFunction ) ; } else if ( debugFunction ) { this . log ( LogLevel . DEBUG , debugFunction ( ) ) ; } else { this . log ( LogLevel . DEBUG , '' + debugFunction ) ; } } info ( msg ) { this . log ( LogLevel . INFO , msg ) ; } warn ( msg ) { this . log ( LogLevel . WARN , msg ) ; } error ( msg ) { this . log ( LogLevel . ERROR , msg ) ; } setLogLevel ( level ) { this . level = level ; } getLogLevel ( ) { return this . level ; } getLogCaptureSize ( ) { return this . logCapture . length ; } startLogPublishScheduler ( batchSize ) { this . addEventListener ( ) ; this . intervalScheduler ?. stop ( ) ; this . intervalScheduler = new IntervalScheduler ( this . intervalMs ) ; this . intervalScheduler . start ( async ( ) => { if ( this . lock === true || this . getLogCaptureSize ( ) === 0 ) { return ; } this . lock = true ; const batch = this . logCapture . slice ( 0 , batchSize ) ; const body = this . makeRequestBody ( batch ) ; try { const response = await fetch ( this . url , { method : 'POST' , body , ... ( this . headers ? { headers : this . headers , } : { } ) , } ) ; if ( response . status === 200 ) { this . logCapture = this . logCapture . slice ( batch . length ) ; } } catch ( error ) { console . warn ( '[MeetingSessionPOSTLogger] ' + error . message ) ; } finally { this . lock = false ; } } ) ; } stop ( ) { this . intervalScheduler ?. stop ( ) ; this . intervalScheduler = undefined ; this . removeEventListener ( ) ; const body = this . makeRequestBody ( this . logCapture ) ; navigator . sendBeacon ( this . url , body ) ; } /**
     * Permanently clean up the logger. A new logger must be created to
     * resume logging.
     */ async destroy ( ) { this . intervalScheduler ?. stop ( ) ; this . intervalScheduler = undefined ; this . removeEventListener ( ) ; this . configuration = undefined ; this . logCapture = [ ] ; } private makeRequestBody ( batch ) { return JSON . stringify ( { meetingId : this . configuration . meetingId , attendeeId : this . configuration . credentials . attendeeId , appName : this . name , logs : batch , } ) ; } private log ( type , msg ) { if ( type < this . level ) { return ; } const now = Date . now ( ) ; this . logCapture . push ( new Log ( this . sequenceNumber , msg , now , LogLevel [ type ] ) ) ; this . sequenceNumber += 1 ; } }