''); // Track output buffer level at each time mark var $aMarkNotes = array(); // Other notes can be added and output... var $aTimeMarks = array(); // Overall time markers var $curTimeMark = 'Start'; var $nTimeMarks = 0; // Provide an array index for time marks. Stablizes 'current' function var $aGoodQueries = array(); var $aBadQueries = array(); var $scbbcodes = array(); var $scbcount; var $deprecated_funcs = array(); var $aLog = array(); // Generalized debug log (only seen during debug) function e107_db_debug() { global $eTimingStart; $this->aTimeMarks[0]=array( 'Index' => 0, 'What' => 'Start', '%Time' => 0, '%DB Time' => 0, '%DB Count' => 0, 'Time' => ($eTimingStart), 'DB Time' => 0, 'DB Count' => 0, 'Memory' => 0 ); register_shutdown_function('e107_debug_shutdown'); } // // Add your new Show function here so it will display in debug output! // function Show_All() { global $eTraffic; $this->ShowIf('Debug Log', $this->Show_Log()); $this->ShowIf('Traffic Counters', $eTraffic->Display()); $this->ShowIf('Time Analysis', $this->Show_Performance()); $this->ShowIf('SQL Analysis', $this->Show_SQL_Details()); $this->ShowIf('Shortcodes / BBCode',$this->Show_SC_BB()); $this->ShowIf('Paths', $this->Show_PATH()); $this->ShowIf('Deprecated Function Usage', $this->Show_DEPRECATED()); $this->ShowIf('Included Files', $this->Show_Includes()); } function ShowIf($title,$str) { global $ns,$style; $style='debug'; if (!isset($ns)) { echo "Why did ns go away?
"; $ns = new e107table; } if (strlen($str)) { $ns->tablerender($title, $str); } } function Mark_Time($sMarker) { // Should move to traffic_class? $timeNow=microtime(); $nMarks=++$this->nTimeMarks; if (!strlen($sMarker)) { $sMarker = "Mark not set"; } $this->aTimeMarks[$nMarks]=array( 'Index' => ($this->nTimeMarks), 'What' => $sMarker, '%Time' => 0, '%DB Time' => 0, '%DB Count' => 0, 'Time' => $timeNow, 'DB Time' => 0, 'DB Count' => 0, 'Memory' => ((function_exists("memory_get_usage"))? memory_get_usage() : 0) ); $this->aOBMarks[$nMarks]=ob_get_level().'('.ob_get_length().')'; $this->curTimeMark=$sMarker; // Add any desired notes to $aMarkNotes[$nMarks]... e.g. //global $eTimingStart; //$this->aMarkNotes[$nMarks] .= "verify start: ".$eTimingStart."
"; } function Mark_Query($query, $rli, $origQryRes, $aTrace, $mytime, $curtable) { global $sql; // Explain the query, if possible... list($qtype,$args) = explode(" ", ltrim($query), 2); $nFields=0; $bExplained = FALSE; $ExplainText = ''; // Note the subtle bracket in the second comparison! Also, strcasecmp() returns zero on match if (!strcasecmp($qtype,'SELECT') || !strcasecmp($qtype,'(SELECT')) { // It's a SELECT statement - explain it // $rli should always be set by caller $sQryRes = (is_null($rli) ? mysql_query("EXPLAIN {$query}") : mysql_query("EXPLAIN {$query}", $rli)); if ($sQryRes) { // There's something to explain $nFields = mysql_num_fields($sQryRes); $bExplained = TRUE; } } else { // Don't run 'EXPLAIN' on other queries $sQryRes = $origQryRes; // Return from original query could be TRUE or a link resource if success } // Record Basic query info $sCallingFile = $aTrace[1]['file']; $sCallingLine = $aTrace[1]['line']; $t = &$this->aSQLdetails[$sql->db_QueryCount()]; $t['marker'] = $this->curTimeMark; $t['caller'] = "$sCallingFile($sCallingLine)"; $t['query'] = $query; $t['ok'] = $sQryRes ? TRUE : FALSE; $t['error'] = $sQryRes ? '' : mysql_error(); $t['nFields'] = $nFields; $t['time'] = $mytime; if ($bExplained) { $bRowHeaders=FALSE; while ($row = @mysql_fetch_assoc($sQryRes)) { if (!$bRowHeaders) { $bRowHeaders=TRUE; $t['explain']="".implode("", array_keys($row))."\n"; } $t['explain'] .= "".implode(" ", array_values($row))." \n"; } } else { $t['explain'] = $ExplainText; } $this->aTimeMarks[$this->nTimeMarks]['DB Time'] += $mytime; $this->aTimeMarks[$this->nTimeMarks]['DB Count']++; if (array_key_exists($curtable, $this->aDBbyTable)) { $this->aDBbyTable[$curtable]['DB Time'] += $mytime; $this->aDBbyTable[$curtable]['DB Count']++; } else { $this->aDBbyTable[$curtable]['Table']=$curtable; $this->aDBbyTable[$curtable]['%DB Time']=0; // placeholder $this->aDBbyTable[$curtable]['%DB Count']=0; // placeholder $this->aDBbyTable[$curtable]['DB Time']=$mytime; $this->aDBbyTable[$curtable]['DB Count']=1; } } function Show_SQL_Details() { global $sql; // // Show stats from aSQLdetails array // $text=''; $nQueries=$sql->db_QueryCount(); if (!$nQueries) return $text; // // ALWAYS summarize query errors // $badCount=0; $okCount=0; foreach ($this->aSQLdetails as $cQuery) { if ($cQuery['ok']) { $okCount++; } else { $badCount++; } } if ($badCount) { $text .= "\n\n"; $text .= "\n"; $text .= "\n"; foreach ($this->aSQLdetails as $idx => $cQuery) { if (!$cQuery['ok']) { $text .= "\n\n"; } } $text .= "\n
$badCount Query Errors!
IndexQuery / Error
{$idx}  ".$cQuery['query']."
".$cQuery['error']."

\n"; } // // Optionally list good queries // if ($okCount && E107_DBG_SQLQUERIES) { $text .= "\n\n"; $text .= "\n"; $text .= "\n \n "; foreach ($this->aSQLdetails as $idx => $cQuery) { if ($cQuery['ok']) { $text .= "\n"; } } $text .= "\n
{$okCount[TRUE]} Good Queries
IndexQtimeQuery
 (msec) 
{$idx}  ".number_format($cQuery['time'] * 1000.0, 4)." ".$cQuery['query'].'
['.$cQuery['marker']." - ".$cQuery['caller']."]

\n"; } // // Optionally list query details // if (E107_DBG_SQLDETAILS) { foreach ($this->aSQLdetails as $idx => $cQuery) { $text .= "\n\n"; $text .= "\n"; if (isset($cQuery['explain'])) { $text .= $cQuery['explain']; } if (strlen($cQuery['error'])) { $text .= "\n\n"; } $text .= "
".$idx.") Query: [".$cQuery['marker']." - ".$cQuery['caller']."]
".$cQuery['query']."
Error in query:
".$cQuery['error']."
Query time: ".number_format($cQuery['time'] * 1000.0, 4).' (ms)

'."\n"; } } return $text; } function Show_Performance() { // // Stats by Time Marker // global $db_time; global $sql; global $eTimingStart, $eTimingStop, $eTraffic; $this->Mark_Time('Stop'); if (!E107_DBG_TIMEDETAILS) return ''; $totTime=$eTraffic->TimeDelta($eTimingStart, $eTimingStop); $text = "\n\n"; $bRowHeaders=FALSE; reset($this->aTimeMarks); $aSum=$this->aTimeMarks[0]; // create a template from the 'real' array $aSum['Index']=''; $aSum['What']='Total'; $aSum['Time']=0; $aSum['DB Time']=0; $aSum['DB Count']=0; $aSum['Memory']=''; while (list($tKey, $tMarker) = each($this->aTimeMarks)) { if (!$bRowHeaders) { // First time: emit headers $bRowHeaders=TRUE; $text .= "\n"; $aUnits = $tMarker; foreach ($aUnits as $key=>$val) { switch ($key) { case 'DB Time': case 'Time': $aUnits[$key] = '(msec)'; break; default: $aUnits[$key] = ''; break; } } $aUnits['OB Lev'] = 'lev(buf bytes)'; $aUnits['Memory'] = '(kb)'; $text .= "\n"; } $tMem = $tMarker['Memory']; $tMarker['Memory'] = ($tMem ? number_format($tMem/1024.0, 1) : '?'); // display if known if ($tMarker['What'] == 'Stop') { $tMarker['Time']=' '; $tMarker['%Time']=' '; $tMarker['%DB Count']=' '; $tMarker['%DB Time']=' '; $tMarker['DB Time']=' '; $tMarker['OB Lev']=$this->aOBMarks[$tKey]; $tMarker['DB Count']=' '; } else { // Convert from start time to delta time, i.e. from now to next entry $nextMarker=current($this->aTimeMarks); $aNextT=$nextMarker['Time']; $aThisT=$tMarker['Time']; $thisDelta=$eTraffic->TimeDelta($aThisT, $aNextT); $aSum['Time'] += $thisDelta; $aSum['DB Time'] += $tMarker['DB Time']; $aSum['DB Count'] += $tMarker['DB Count']; $tMarker['Time']=number_format($thisDelta*1000.0, 1); $tMarker['%Time']=$totTime ? number_format(100.0 * ($thisDelta / $totTime), 0) : 0; $tMarker['%DB Count']=number_format(100.0 * $tMarker['DB Count'] / $sql->db_QueryCount(), 0); $tMarker['%DB Time']=$db_time ? number_format(100.0 * $tMarker['DB Time'] / $db_time, 0) : 0; $tMarker['DB Time']=number_format($tMarker['DB Time']*1000.0, 1); $tMarker['OB Lev']=$this->aOBMarks[$tKey]; } $text .= "\n"; if (isset($this->aMarkNotes[$tKey])) { $text .= "\n"; } if ($tMarker['What'] == 'Stop') break; } $aSum['%Time']=$totTime ? number_format(100.0 * ($aSum['Time'] / $totTime), 0) : 0; $aSum['%DB Time']=$db_time ? number_format(100.0 * ($aSum['DB Time'] / $db_time), 0) : 0; $aSum['%DB Count']=($sql->db_QueryCount()) ? number_format(100.0 * ($aSum['DB Count'] / ($sql->db_QueryCount())), 0) : 0; $aSum['Time']=number_format($aSum['Time']*1000.0, 1); $aSum['DB Time']=number_format($aSum['DB Time']*1000.0, 1); $text .= "\n"; $text .= "\n
".implode(" ", array_keys($tMarker))." OB Lev 
".implode(" ", $aUnits)." 
".implode(" ", array_values($tMarker))." 
 "; $text .= $this->aMarkNotes[$tKey]."
".implode(" ", $aSum)."  

\n"; // // Stats by Table // $text .= "\n\n"; $bRowHeaders=FALSE; $aSum=$this->aDBbyTable['core']; // create a template from the 'real' array $aSum['Table']='Total'; $aSum['%DB Count']=0; $aSum['%DB Time']=0; $aSum['DB Time']=0; $aSum['DB Count']=0; foreach ($this->aDBbyTable as $curTable) { if (!$bRowHeaders) { $bRowHeaders=TRUE; $text .= "\n"; $aUnits = $curTable; foreach ($aUnits as $key=>$val) { switch ($key) { case 'DB Time': $aUnits[$key] = '(msec)'; break; default: $aUnits[$key] = ''; break; } } $text .= "\n"; } $aSum['DB Time'] += $curTable['DB Time']; $aSum['DB Count'] += $curTable['DB Count']; $curTable['%DB Count']=number_format(100.0 * $curTable['DB Count'] / $sql->db_QueryCount(), 0); $curTable['%DB Time']=number_format(100.0 * $curTable['DB Time'] / $db_time, 0); $curTable['DB Time']=number_format($curTable['DB Time']*1000.0, 1); $text .= "\n"; } $aSum['%DB Time']=$db_time ? number_format(100.0 * ($aSum['DB Time'] / $db_time), 0) : 0; $aSum['%DB Count']=($sql->db_QueryCount()) ? number_format(100.0 * ($aSum['DB Count'] / ($sql->db_QueryCount())), 0) : 0; $aSum['DB Time']=number_format($aSum['DB Time']*1000.0, 1); $text .= "\n"; $text .= "\n
".implode("", array_keys($curTable))."
".implode(" ", $aUnits)." 
".implode(" ", array_values($curTable))." 
".implode(" ", array_values($aSum))." 

\n"; return $text; } function logDeprecated(){ $back_trace = debug_backtrace(); print_r($back_trace); $this->deprecated_funcs[] = array ( 'func' => (isset($back_trace[1]['type']) && ($back_trace[1]['type'] == '::' || $back_trace[1]['type'] == '->') ? $back_trace[1]['class'].$back_trace[1]['type'].$back_trace[1]['function'] : $back_trace[1]['function']), 'file' => $back_trace[1]['file'], 'line' => $back_trace[1]['line'] ); } function logCode($type, $code, $parm, $postID) { if (!E107_DBG_BBSC) { return FALSE; } $this -> scbbcodes[$this -> scbcount]['type'] = $type; $this -> scbbcodes[$this -> scbcount]['code'] = $code; $this -> scbbcodes[$this -> scbcount]['parm'] = $parm; $this -> scbbcodes[$this -> scbcount]['postID'] = $postID; $this -> scbcount ++; } function Show_SC_BB() { if (!E107_DBG_BBSC) { return FALSE; } $text = "\n"; foreach($this -> scbbcodes as $codes) { $text .= "\n"; } $text .= "
Shortcode / BBCode
Type Code Parm Post ID
".($codes['type'] == 1 ? "BBCode" : "Shortcode")." ".(isset($codes['code']) ? $codes['code'] : " ")." ".($codes['parm'] ? $codes['parm'] : " ")." ".($codes['postID'] ? $codes['postID'] : " ")."
"; return $text; } function Show_PATH() { if (!E107_DBG_PATH) { return FALSE; } global $e107; $text = "
Paths
\n"; $text .= "e_HTTP: '".e_HTTP."'
"; $text .= "e_BASE: '".e_BASE."'
"; $text .= "\$_SERVER['PHP_SELF']: '".$_SERVER['PHP_SELF']."'
"; $text .= "\$_SERVER['DOCUMENT_ROOT']: '".$_SERVER['DOCUMENT_ROOT']."'
"; $text .= "\$_SERVER['HTTP_HOST']: '".$_SERVER['HTTP_HOST']."'
"; $text .= "
";
        $text .= htmlspecialchars(print_r($e107,TRUE));
	  	$text .= "
"; $text .= "
"; return $text; } function Show_DEPRECATED(){ if (!E107_DBG_DEPRECATED){ return FALSE; } else { $text = "\n"; foreach($this->deprecated_funcs as $funcs) { $text .= "\n"; } $text .= "
The following deprecated functions were used:
Function File Line
{$funcs['func']}() {$funcs['file']} {$funcs['line']}
"; return $text; } } // // Simple debug-level 'console' log // Record a "nice" debug message with // $db_debug->log("message"); // function log($message,$TraceLev=1) { if (!E107_DBG_BASIC){ return FALSE; } if ($TraceLev) { $bt = debug_backtrace(); $this->aLog[] = array ( 'Message' => $message, 'Function' => (isset($bt[$TraceLev]['type']) && ($bt[$TraceLev]['type'] == '::' || $bt[$TraceLev]['type'] == '->') ? $bt[$TraceLev]['class'].$bt[$TraceLev]['type'].$bt[$TraceLev]['function'].'()' : $bt[$TraceLev]['function']).'()', 'File' => $bt[$TraceLev]['file'], 'Line' => $bt[$TraceLev]['line'] ); } else { $this->aLog[] = array ( 'Message' => $message, 'Function' => '', 'File' => '', 'Line' => '' ); } } function Show_Log(){ if (!E107_DBG_BASIC || !count($this->aLog)){ return FALSE; } // // Dump the debug log // $text .= "\n\n"; $bRowHeaders=FALSE; foreach ($this->aLog as $curLog) { if (!$bRowHeaders) { $bRowHeaders=TRUE; $text .= "\n"; } $text .= "\n"; } $text .= "
".implode("", array_keys($curLog))."
".implode(" ", array_values($curLog))." 

\n"; return $text; } function Show_Includes() { if (!E107_DBG_INCLUDES) return FALSE; $aIncList = get_included_files(); $text = "\n"; $text .= "\n\n"; $text .= "
". implode(" 
", $aIncList). " 
\n"; return $text; } } // // Helper functions (not part of the class) // function e107_debug_shutdown() { global $error_handler,$e107_Clean_Exit,$In_e107_Footer,$ADMIN_DIRECTORY; if (isset($e107_Clean_Exit)) return; if (!isset($In_e107_Footer)) { if (defset('ADMIN_AREA')) { $filewanted=realpath(dirname(__FILE__)).'/../'.$ADMIN_DIRECTORY.'footer.php'; require_once($filewanted); } else if (defset('USER_AREA')) { $filewanted=realpath(dirname(__FILE__)).'/../'.FOOTERF; require_once($filewanted); } } // // Error while in the footer, or during startup, or during above processing // if (isset($e107_Clean_Exit)) return; // We've now sent a footer... // echo isset($In_e107_Footer) ? "In footer" : "In startup".'
'; while (ob_get_level() > 0) { ob_end_flush(); } if (isset($error_handler)) { echo "

PHP Errors:


".$error_handler->return_errors()."
\n"; } else { echo "e107 Shutdown while no error_handler available!"; } echo ""; } ?>