<?php /** * Debug logging during a client request. * * @author hahn */ class logger { protected $aMessages=array(); protected $bShowDebug=true; protected $_iMemStart = false; /** * constuctor * @param string $sInitMessage init message * @return boolean */ public function __construct($sInitMessage="Logger was initialized.") { $this->_iMemStart=memory_get_usage(); $this->add($sInitMessage); return true; } /** * enable / disable debugging * @param type $bEnable * @return type */ public function enableDebug($bEnable=false){ return $this->bShowDebug=$bEnable; } /** * enable client debugging by a given array of allowed ip addresses * @param array $aIpArray * @return boolean */ public function enableDebugByIp($aIpArray){ $this->enableDebug(false); if (!$_SERVER || !is_array($_SERVER) || !array_key_exists("REMOTE_ADDR", $_SERVER)){ return false; } if (array_search($_SERVER['REMOTE_ADDR'], $aIpArray)!==false){ $this->enableDebug(true); } } /** * add a logging message * @param type $sMessage * @param type $sLevel * @return boolean */ public function add($sMessage, $sLevel="info"){ if (!$this->bShowDebug){ return false; } global $aCfg; $this->aMessages[]=array( 'time'=>microtime(true), 'message'=>$sMessage, 'level'=>$sLevel ); if ($sLevel=="MAIL"){ mail($aCfg["emailDeveloper"], "studmed - booking tool - Logmessage", $sMessage); } return true; } /** * render output of all logging messages */ public function render(){ if (!$this->bShowDebug){ return false; } $sOut=''; $iMem=memory_get_usage(); $this->add('<hr>'); $this->add('Memory on start: ' . number_format($this->_iMemStart, 0, '.', ',') . " bytes"); $this->add('Memory on end: ' . number_format($iMem, 0, '.', ',') . " bytes"); $this->add('Memory peak: ' . number_format(memory_get_peak_usage(), 0, '.', ',') . " bytes"); $sStarttime=$this->aMessages[0]["time"]; $iCounter=0; $sMaxRowId=false; $iMaxtime=-1; $sWarnings=false; $iLasttime=$sStarttime; foreach ($this->aMessages as $aLogentry){ $iCounter++; $sTrId='debugTableRow'.$iCounter; $iDelta=$aLogentry["time"]-$iLasttime; if ($iDelta > $iMaxtime){ $iMaxtime=$iDelta; $sMaxRowId=$sTrId; } $sStyle=($iDelta > 1)?'color: #f82;':''; if (($iDelta > 1)){ $sWarnings.='<a href="#'.$sTrId.'" title="'.sprintf("%01.4f", $iDelta).' s">'.$iCounter.'</a> '; } $sOut.='<tr class="'.$aLogentry["level"].'" id="'.$sTrId.'" style="'.$sStyle.'">'. '<td>'.$iCounter.'</td>'. '<td>'.sprintf("%01.3f", $aLogentry["time"]-$sStarttime).'</td>'. '<td>'.sprintf("%01.3f", $iDelta).'</td>'. '<td>'.$aLogentry["level"].'</td>'. '<td>'.$aLogentry["message"].'</td>'. '</tr>'; $iLasttime=$aLogentry["time"]; } $iTotal=$iLasttime-$sStarttime; if ($sWarnings){ $sWarnings='<br>warnings: '.$sWarnings; } if ($sOut) $sOut=' <div style="position: fixed; right: 1em; top: 6em; background: rgba(255,80,80, 0.1); padding: 0.5em;"> <span style="font-size: 130%;">total: '.sprintf("%01.3f", $iTotal).' s</span><br> <span>longest action: <a href="#'.$sMaxRowId.'">'.sprintf("%01.3f", $iMaxtime).' s</a></span> <span>'.$sWarnings.'</span> </div> <br> <br> <br> <br> <br> <h3>DEBUG</h3><br> <table class="datatable table table-striped debugtable"> <thead> <tr> <th>#</th> <th>delta to start time</th> <th>delta to previuos</th> <th>level</th> <th>message</th> </tr></thead><tbody> '.$sOut.'</tbody></table>' . '<script>$(\'#'.$sMaxRowId.'\').css(\'color\', \'#f00\');</script>'; return $sOut; } /** * render output of all logging messages for cli output * @return string */ public function renderCli(){ if (!$this->bShowDebug){ return false; } $sOut=''; $sStarttime=$this->aMessages[0]["time"]; $iCounter=0; $sMaxRowId=false; $iMaxtime=-1; $sWarnings=false; $iLasttime=$sStarttime; foreach ($this->aMessages as $aLogentry){ $iCounter++; $iDelta=$aLogentry["time"]-$iLasttime; $sOut.=$aLogentry["level"].' ' . $iCounter.' ' .sprintf("%01.3f", $aLogentry["time"]-$sStarttime).' ' .sprintf("%01.3f", $iDelta).' ' .$aLogentry["level"].' ' .$aLogentry["message"].' ' . "\n" ; $iLasttime=$aLogentry["time"]; } // $iTotal=$iLasttime-$sStarttime; return $sOut; } }