@ -1,15 +1,23 @@ 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  Prometheus  =  require ( 'prom-client' ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  https  =  require ( 'https' ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  dayjs  =  require ( "dayjs" ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  utc  =  require ( 'dayjs/plugin/utc' )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					var  timezone  =  require ( 'dayjs/plugin/timezone' )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					dayjs . extend ( utc )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					dayjs . extend ( timezone )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  axios  =  require ( "axios" ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  { tcping ,  ping }  =  require ( "../util-server" ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  { debug ,  UP ,  DOWN ,  PENDING }  =  require ( "../util" ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  { tcping ,  ping ,  checkCertificate }  =  require ( "../util-server" ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  { R }  =  require ( "redbean-node" ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  { BeanModel }  =  require ( "redbean-node/dist/bean-model" ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  { Notification }  =  require ( "../notification" )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//  Use Custom agent to disable session reuse
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//  https://github.com/nodejs/node/issues/3940
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  customAgent  =  new  https . Agent ( {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    maxCachedSessions :  0  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  commonLabels  =  [  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    'monitor_name' ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    'monitor_type' ,  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -18,24 +26,24 @@ const commonLabels = [ 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    'monitor_port' ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					]  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  monitor_response_time  =  new  Prometheus . Gauge ( {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    name :  'monitor_response_time' ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    help :  'Monitor Response Time (ms)' ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    labelNames :  commonLabels  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					const  monitor_status  =  new  Prometheus . Gauge ( {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    name :  'monitor_status' ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    help :  'Monitor Status (1 = UP, 0= DOWN)' ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    labelNames :  commonLabels  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					} ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					/ * *  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					 *  status :  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					 *       0  =  DOWN  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					 *       1  =  UP  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					 * /  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					class  Monitor  extends  BeanModel  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    async  toJSON ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        let  notificationIDList  =  { } ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -54,6 +62,7 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            url :  this . url ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            hostname :  this . hostname ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            port :  this . port ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            maxretries :  this . maxretries ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            weight :  this . weight ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            active :  this . active ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            type :  this . type ,  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -65,6 +74,7 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    start ( io )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        let  previousBeat  =  null ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        let  retries  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        const  monitorLabelValues  =  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                monitor_name :  this . name ,  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -74,21 +84,23 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                monitor_port :  this . port  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        const  beat  =  async  ( )  =>  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( !  previousBeat )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                previousBeat  =  await  R . findOne ( "heartbeat" ,  " monitor_id = ? ORDER BY time DESC" ,  [  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    this . id  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                ] )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            const  isFirstBeat  =  ! previousBeat ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            let  bean  =  R . dispense ( "heartbeat" )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            bean . monitor_id  =  this . id ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            bean . time  =  R . isoDateTime ( dayjs . utc ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            bean . status  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            bean . status  =  DOWN ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Duration
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( previous Beat)  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( !  isFirst Beat)  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                bean . duration  =  dayjs ( bean . time ) . diff ( dayjs ( previousBeat . time ) ,  'second' ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                bean . duration  =  0 ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -98,13 +110,27 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( this . type  ===  "http"  ||  this . type  ===  "keyword" )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    let  startTime  =  dayjs ( ) . valueOf ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    let  res  =  await  axios . get ( this . url ,  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        headers :  {  'User-Agent' : 'Uptime-Kuma'  }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    } )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        headers :  {  "User-Agent" :  "Uptime-Kuma"  } ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        httpsAgent :  customAgent ,  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    } ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . msg  =  ` ${ res . status }  -  ${ res . statusText } `  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . ping  =  dayjs ( ) . valueOf ( )  -  startTime ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Check certificate if https is used
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    let  certInfoStartTime  =  dayjs ( ) . valueOf ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( this . getUrl ( ) ? . protocol  ===  "https:" )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        try  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            await  this . updateTlsInfo ( checkCertificate ( res ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  catch  ( e )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            console . error ( e . message )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    debug ( "Cert Info Query Time: "  +  ( dayjs ( ) . valueOf ( )  -  certInfoStartTime )  +  "ms" )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( this . type  ===  "http" )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        bean . status  =  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        bean . status  =  UP ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        let  data  =  res . data ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -116,7 +142,7 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( data . includes ( this . keyword ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            bean . msg  +=  ", keyword is found"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            bean . status  =  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            bean . status  =  UP ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            throw  new  Error ( bean . msg  +  ", but keyword is not found" )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -127,30 +153,52 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  else  if  ( this . type  ===  "port" )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . ping  =  await  tcping ( this . hostname ,  this . port ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . msg  =  ""  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . status  =  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . status  =  UP ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  else  if  ( this . type  ===  "ping" )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . ping  =  await  ping ( this . hostname ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . msg  =  ""  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . status  =  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . status  =  UP ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                retries  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  catch  ( error )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( ( this . maxretries  >  0 )  &&  ( retries  <  this . maxretries ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    retries ++ ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    bean . status  =  PENDING ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                bean . msg  =  error . message ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Mark as important if status changed
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( !  previousBeat  ||  previousBeat . status  !==  bean . status )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // * ? -> ANY STATUS = important [isFirstBeat]
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // UP -> PENDING = not important
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // * UP -> DOWN = important
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // UP -> UP = not important
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // PENDING -> PENDING = not important
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // * PENDING -> DOWN = important
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // PENDING -> UP = not important
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // DOWN -> PENDING = this case not exists
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // DOWN -> DOWN = not important
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // * DOWN -> UP = important
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            let  isImportant  =  isFirstBeat  ||  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                ( previousBeat . status  ===  UP  &&  bean . status  ===  DOWN )  ||  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                ( previousBeat . status  ===  DOWN  &&  bean . status  ===  UP )  ||  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                ( previousBeat . status  ===  PENDING  &&  bean . status  ===  DOWN ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Mark as important if status changed, ignore pending pings,
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Don't notify if disrupted changes to up
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( isImportant )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                bean . important  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Do not send if first beat is UP
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( previousBeat  ||  bean . status  !==  1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Send only if the first beat is DOWN 
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( ! isFirst Beat  ||  bean . status  ===  DOWN )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    let  notificationList  =  await  R . getAll ( ` SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id  ` ,  [  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        this . id  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    ] )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    let  text ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( bean . status  ===  1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( bean . status  ===  UP )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        text  =  "✅ Up"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        text  =  "🔴 Down"  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -171,11 +219,12 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                bean . important  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            monitor_status . set ( monitorLabelValues ,  bean . status )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( bean . status  ===  1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( bean . status  ===  UP )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                console . info ( ` Monitor # ${ this . id }  ' ${ this . name } ': Successful Response:  ${ bean . ping }  ms | Interval:  ${ this . interval }  seconds | Type:  ${ this . type } ` )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  else  if  ( bean . status  ===  PENDING )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                console . warn ( ` Monitor # ${ this . id }  ' ${ this . name } ': Pending:  ${ bean . msg }  | Type:  ${ this . type } ` )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                console . warn ( ` Monitor # ${ this . id }  ' ${ this . name } ': Failing:  ${ bean . msg }  | Type:  ${ this . type } ` )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -198,10 +247,35 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        clearInterval ( this . heartbeatInterval )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    // Helper Method:
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    // returns URL object for further usage
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    // returns null if url is invalid
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    getUrl ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        try  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  new  URL ( this . url ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  catch  ( _ )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  null ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    // Store TLS info to database
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    async  updateTlsInfo ( checkCertificateResult )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        let  tls_info_bean  =  await  R . findOne ( "monitor_tls_info" ,  "monitor_id = ?" ,  [  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this . id  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        if  ( tls_info_bean  ==  null )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            tls_info_bean  =  R . dispense ( "monitor_tls_info" ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            tls_info_bean . monitor_id  =  this . id ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        tls_info_bean . info_json  =  JSON . stringify ( checkCertificateResult ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        await  R . store ( tls_info_bean ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    static  async  sendStats ( io ,  monitorID ,  userID )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        Monitor . sendAvgPing ( 24 ,  io ,  monitorID ,  userID ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        Monitor . sendUptime ( 24 ,  io ,  monitorID ,  userID ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        Monitor . sendUptime ( 24  *  30 ,  io ,  monitorID ,  userID ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        Monitor . sendCertInfo ( io ,  monitorID ,  userID ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    / * *  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -222,6 +296,15 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        io . to ( userID ) . emit ( "avgPing" ,  monitorID ,  avgPing ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    static  async  sendCertInfo ( io ,  monitorID ,  userID )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         let  tls_info  =  await  R . findOne ( "monitor_tls_info" ,  "monitor_id = ?" ,  [  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            monitorID  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        if  ( tls_info  !=  null )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            io . to ( userID ) . emit ( "certInfo" ,  monitorID ,  tls_info . info_json ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    / * *  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     *  Uptime  with  calculation  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					     *  Calculation  based  on :  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				
					@ -270,7 +353,7 @@ class Monitor extends BeanModel { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                total  +=  value ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( row . status  ===  0 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( row . status  ===  0  ||  row . status  ===  2  )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    downtime  +=  value ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }