MAX_TIME && !defined('TIME_EXCEPTION')) { $Reason[] = number_format($Micro, 3).' ms'; } $Errors = count($this->get_errors()); if ($Errors > MAX_ERRORS && !defined('ERROR_EXCEPTION')) { $Reason[] = $Errors.' PHP Errors'; } /* $Queries = count($this->get_queries()); if ($Queries > MAX_QUERIES && !defined('QUERY_EXCEPTION')) { $Reason[] = $Queries.' Queries'; } */ $Ram = memory_get_usage(true); if ($Ram > MAX_MEMORY && !defined('MEMORY_EXCEPTION')) { $Reason[] = Format::get_size($Ram).' Ram Used'; } if (isset($_REQUEST['profile'])) { global $LoggedUser; $Reason[] = 'Requested by '.$LoggedUser['Username']; } $this->Perf['Memory usage'] = (($Ram>>10)/1024).' MB'; $this->Perf['Page process time'] = number_format($Micro / 1000, 3).' s'; $this->Perf['CPU time'] = number_format($this->get_cpu_time() / 1000000, 3).' s'; if (isset($Reason[0])) { $this->analysis(implode(', ', $Reason)); return true; } return false; } public function analysis($Message, $Report='', $Time=43200) { global $Cache, $Document; if (empty($Report)) { $Report = $Message; } $Identifier = Users::make_secret(5); $Cache->cache_value( 'analysis_'.$Identifier, array( 'url' => $_SERVER['REQUEST_URI'], 'message' => $Report, 'errors' => $this->get_errors(true), 'queries' => $this->get_queries(), 'flags' => $this->get_flags(), 'includes' => $this->get_includes(), 'cache' => $this->get_cache_keys(), 'vars' => $this->get_logged_vars(), 'perf' => $this->get_perf() ), $Time ); send_irc('PRIVMSG '.LAB_CHAN.' :'.$Message.' '.$Document.' '.' https://'.SSL_SITE_URL.'/tools.php?action=analysis&case='.$Identifier.' https://'.SSL_SITE_URL.$_SERVER['REQUEST_URI']); } public function get_cpu_time() { if (!defined('PHP_WINDOWS_VERSION_MAJOR')) { global $CPUTimeStart; $RUsage = getrusage(); $CPUTime = $RUsage['ru_utime.tv_sec']*1000000 + $RUsage['ru_utime.tv_usec'] - $CPUTimeStart; return $CPUTime; } return false; } public function log_var($Var, $VarName = FALSE) { $BackTrace = debug_backtrace(); $ID = uniqid(); if(!$VarName) { $VarName = $ID; } $File = array('path' => substr($BackTrace[0]['file'], strlen(SERVER_ROOT)), 'line' => $BackTrace[0]['line']); $this->LoggedVars[$ID] = array($VarName => array('bt' => $File, 'data' => $Var)); } public function set_flag($Event) { global $ScriptStartTime; $this->Flags[] = array($Event, (microtime(true)-$ScriptStartTime)*1000, memory_get_usage(true), $this->get_cpu_time()); } //This isn't in the constructor because $this is not available, and the function cannot be made static public function handle_errors() { //error_reporting(E_ALL ^ E_STRICT | E_WARNING | E_DEPRECATED | E_ERROR | E_PARSE); //E_STRICT disabled error_reporting(E_WARNING | E_ERROR | E_PARSE); set_error_handler(array($this, 'php_error_handler')); } protected function format_args($Array) { $LastKey = -1; $Return = array(); foreach ($Array as $Key => $Val) { $Return[$Key] = ''; if (!is_int($Key) || $Key != $LastKey+1) { $Return[$Key] .= "'$Key' => "; } if ($Val === true) { $Return[$Key] .= "true"; } elseif ($Val === false) { $Return[$Key] .= "false"; } elseif (is_string($Val)) { $Return[$Key] .= "'$Val'"; } elseif (is_int($Val)) { $Return[$Key] .= $Val; } elseif (is_object($Val)) { $Return[$Key] .= get_class($Val); } elseif (is_array($Val)) { $Return[$Key] .= 'array('.$this->format_args($Val).')'; } $LastKey = $Key; } return implode(', ', $Return); } public function php_error_handler($Level, $Error, $File, $Line) { //Who added this, it's still something to pay attention to... if (stripos('Undefined index', $Error) !== false) { //return true; } $Steps = 1; //Steps to go up in backtrace, default one $Call = ''; $Args = ''; $Tracer = debug_backtrace(); //This is in case something in this function goes wrong and we get stuck with an infinite loop if (isset($Tracer[$Steps]['function'], $Tracer[$Steps]['class']) && $Tracer[$Steps]['function'] == 'php_error_handler' && $Tracer[$Steps]['class'] == 'DEBUG') { return true; } //If this error was thrown, we return the function which threw it if (isset($Tracer[$Steps]['function']) && $Tracer[$Steps]['function'] == 'trigger_error') { $Steps++; $File = $Tracer[$Steps]['file']; $Line = $Tracer[$Steps]['line']; } //At this time ONLY Array strict typing is fully supported. //Allow us to abuse strict typing (IE: function test(Array)) if (preg_match('/^Argument (\d+) passed to \S+ must be an (array), (array|string|integer|double|object) given, called in (\S+) on line (\d+) and defined$/', $Error, $Matches)) { $Error = 'Type hinting failed on arg '.$Matches[1]. ', expected '.$Matches[2].' but found '.$Matches[3]; $File = $Matches[4]; $Line = $Matches[5]; } //Lets not be repetative if (($Tracer[$Steps]['function'] == 'include' || $Tracer[$Steps]['function'] == 'require' ) && isset($Tracer[$Steps]['args'][0]) && $Tracer[$Steps]['args'][0] == $File) { unset($Tracer[$Steps]['args']); } //Class if (isset($Tracer[$Steps]['class'])) { $Call .= $Tracer[$Steps]['class'].'::'; } //Function & args if (isset($Tracer[$Steps]['function'])) { $Call .= $Tracer[$Steps]['function']; if (isset($Tracer[$Steps]['args'][0])) { $Args = $this->format_args($Tracer[$Steps]['args']); } } //Shorten the path & we're done $File = str_replace(SERVER_ROOT, '', $File); $Error = str_replace(SERVER_ROOT, '', $Error); /* //Hiding "session_start(): Server 10.10.0.1 (tcp 11211) failed with: No route to host (113)" errors if($Call != "session_start") { $this->Errors[] = array($Error, $File.':'.$Line, $Call, $Args); } */ return true; } /* Data wrappers */ public function get_perf() { if (empty($this->Perf)) { global $ScriptStartTime; $PageTime = (microtime(true) - $ScriptStartTime); $CPUTime = $this->get_cpu_time(); $Perf = array( 'Memory usage' => Format::get_size(memory_get_usage(true)), 'Page process time' => number_format($PageTime, 3).' s'); if ($CPUTime) { $Perf['CPU time'] = number_format($CPUTime / 1000000, 3).' s'; } return $Perf; } return $this->Perf; } public function get_flags() { return $this->Flags; } public function get_errors($Light=false) { //Because the cache can't take some of these variables if ($Light) { foreach ($this->Errors as $Key => $Value) { $this->Errors[$Key][3] = ''; } } return $this->Errors; } public function get_constants() { return get_defined_constants(true); } public function get_classes() { foreach (get_declared_classes() as $Class) { $Classes[$Class]['Vars'] = get_class_vars($Class); $Classes[$Class]['Functions'] = get_class_methods($Class); } return $Classes; } public function get_extensions() { foreach (get_loaded_extensions() as $Extension) { $Extensions[$Extension]['Functions'] = get_extension_funcs($Extension); } return $Extensions; } public function get_includes() { return get_included_files(); } public function get_cache_time() { global $Cache; return $Cache->Time; } public function get_cache_keys() { global $Cache; return array_keys($Cache->CacheHits); } public function get_sphinx_queries() { global $SS; return $SS->Queries; } public function get_sphinx_time() { global $SS; return $SS->Time; } public function get_sphinxql_queries() { if(class_exists('Sphinxql')) { return Sphinxql::$Queries; } } public function get_sphinxql_time() { if(class_exists('Sphinxql')) { return Sphinxql::$Time; } } public function get_queries() { global $DB; return $DB->Queries; } public function get_query_time() { global $DB; return $DB->Time; } public function get_logged_vars() { return $this->LoggedVars; } /* Output Formatting */ public function perf_table($Perf=false) { if (!is_array($Perf)) { $Perf = $this->get_perf(); } if (empty($Perf)) { return; } ?>
(View) Performance stats:
$Value) { ?> get_includes(); } ?>
(View) Includes:
get_classes(); } ?>
(View) Classes:
(View) Extensions:
get_flags(); } if (empty($Flags)) { return; } ?>
(View) Flags:
get_constants(); } ?>
(View) Constants:
get_cache_keys(); $Header .= ' ('.number_format($this->get_cache_time(), 5).' ms)'; } if (empty($CacheKeys)) { return; } $Header = ' '.number_format(count($CacheKeys)).' '.$Header.':'; ?>
(View)
get_errors(); } if (empty($Errors)) { return; } ?>
(View) Errors:
get_queries(); $Header .= ' ('.number_format($this->get_query_time(), 5).' ms)'; } if (empty($Queries)) { return; } $Header = ' '.number_format(count($Queries)).' '.$Header.':'; ?>
(View)
get_sphinx_queries(); if($QueriesQL = $this->get_sphinxql_queries()) { $Queries = array_merge($Queries, $QueriesQL); } $Header .= ' ('.number_format($this->get_sphinx_time()+$this->get_sphinxql_time(), 5).' ms)'; } if (empty($Queries)) { return; } $Header = ' '.number_format(count($Queries)).' '.$Header.':'; ?>
(View)
LoggedVars)) { return; } $Vars = $this->LoggedVars; } $Header = ' '.number_format(count($Vars)).' '.$Header.':'; ?>
(View)
$Var) { list($Key, $Data) = each($Var); $Size = count($Data['data']); ?>