diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2022-05-21 01:45:56 +0300 |
---|---|---|
committer | Evgeny Zinoviev <me@ch1p.io> | 2022-05-21 01:45:56 +0300 |
commit | 6f53e6e997c9f4647a667bd58b11bc622fa3b47f (patch) | |
tree | 226bd65a04576de4f41bf8396af97cd43ca27829 /localwebsite/engine/debug.php | |
parent | 902a3bfbe2c4645e6725fb7583500d1a28026fad (diff) |
move local website to homekit's tree
Diffstat (limited to 'localwebsite/engine/debug.php')
-rw-r--r-- | localwebsite/engine/debug.php | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/localwebsite/engine/debug.php b/localwebsite/engine/debug.php new file mode 100644 index 0000000..b1b959f --- /dev/null +++ b/localwebsite/engine/debug.php @@ -0,0 +1,355 @@ +<?php + +// require_once 'engine/mysql.php'; + +class debug { + + protected static $Types = [ + 1 => 'E_ERROR', + 2 => 'E_WARNING', + 4 => 'E_PARSE', + 8 => 'E_NOTICE', + 16 => 'E_CORE_ERROR', + 32 => 'E_CORE_WARNING', + 64 => 'E_COMPILE_ERROR', + 128 => 'E_COMPILE_WARNING', + 256 => 'E_USER_ERROR', + 512 => 'E_USER_WARNING', + 1024 => 'E_USER_NOTICE', + 2048 => 'E_STRICT', + 4096 => 'E_RECOVERABLE_ERROR', + 8192 => 'E_DEPRECATED', + 16384 => 'E_USER_DEPRECATED', + 32767 => 'E_ALL' + ]; + + const STORE_NONE = -1; + const STORE_MYSQL = 0; + const STORE_FILE = 1; + const STORE_BOTH = 2; + + private static $instance = null; + + protected $enabled = false; + protected $errCounter = 0; + protected $logCounter = 0; + protected $messagesStoreType = self::STORE_NONE; + protected $errorsStoreType = self::STORE_NONE; + protected $filter; + protected $reportRecursionLevel = 0; + protected $overridenDebugFile = null; + protected $silent = false; + protected $prefix; + + private function __construct($filter) { + $this->filter = $filter; + } + + public static function getInstance($filter = null) { + if (is_null(self::$instance)) { + self::$instance = new self($filter); + } + return self::$instance; + } + + public function enable() { + $self = $this; + + set_error_handler(function($no, $str, $file, $line) use ($self) { + if ($self->silent || !$self->enabled) { + return; + } + if ((is_callable($this->filter) && !($this->filter)($no, $file, $line, $str)) || !$self->canReport()) { + return; + } + $self->report(true, $str, $no, $file, $line); + }); + + append_shutdown_function(function() use ($self) { + if (!$self->enabled || !($error = error_get_last())) { + return; + } + if (is_callable($this->filter) + && !($this->filter)($error['type'], $error['file'], $error['line'], $error['message'])) { + return; + } + if (!$self->canReport()) { + return; + } + $self->report(true, $error['message'], $error['type'], $error['file'], $error['line']); + }); + + $this->enabled = true; + } + + public function disable() { + restore_error_handler(); + $this->enabled = false; + } + + public function report($is_error, $text, $errno = 0, $errfile = '', $errline = '') { + global $config; + + $this->reportRecursionLevel++; + + $logstarted = $this->errCounter > 0 || $this->logCounter > 0; + $num = $is_error ? $this->errCounter++ : $this->logCounter++; + $custom = $is_error && !$errno; + $ts = time(); + $exectime = exectime(); + $bt = backtrace(2); + + $store_file = (!$is_error && $this->checkMessagesStoreType(self::STORE_FILE)) + || ($is_error && $this->checkErrorsStoreType(self::STORE_FILE)); + + $store_mysql = (!$is_error && $this->checkMessagesStoreType(self::STORE_MYSQL)) + || ($is_error && $this->checkErrorsStoreType(self::STORE_MYSQL)); + + if ($this->prefix) + $text = $this->prefix.$text; + + // if ($store_mysql) { + // $db = getMySQL('local_logs', true); + // $data = [ + // 'ts' => $ts, + // 'num' => $num, + // 'time' => $exectime, + // 'custom' => intval($custom), + // 'errno' => $errno, + // 'file' => $errfile, + // 'line' => $errline, + // 'text' => $text, + // 'stacktrace' => $bt, + // 'is_cli' => PHP_SAPI == 'cli' ? 1 : 0, + // ]; + // if (PHP_SAPI == 'cli') { + // $data += [ + // 'ip' => '', + // 'ua' => '', + // 'url' => '', + // ]; + // } else { + // $data += [ + // 'ip' => ip2ulong($_SERVER['REMOTE_ADDR']), + // 'ua' => $_SERVER['HTTP_USER_AGENT'] ?? '', + // 'url' => $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] + // ]; + // } + // $db->insert('backend_errors', $data); + // } + + if ($store_file) { + $title = PHP_SAPI == 'cli' ? 'cli' : $_SERVER['REQUEST_URI']; + $date = date('d/m/y H:i:s', $ts); + $exectime = (string)$exectime; + if (strlen($exectime) < 6) + $exectime .= str_repeat('0', 6 - strlen($exectime)); + + $buf = ""; + if (!$logstarted) { + $buf .= "\n<e fg=white bg=magenta style=fgbright,bold> {$title} </e><e fg=white bg=blue style=fgbright> {$date} </e>\n"; + } + $buf .= "<e fg=".($is_error ? 'red' : 'white').">".($is_error ? 'E' : 'I')."=<e style=bold>${num}</e> <e fg=cyan>{$exectime}</e> "; + if ($is_error && !$custom) { + $buf .= "<e fg=green>{$errfile}<e fg=white>:<e fg=green style=fgbright>{$errline}</e> (".self::errname($errno).") "; + } + $buf = stransi($buf); + + $buf .= $text; + $buf .= "\n"; + if ($is_error && $config['debug_backtrace']) { + $buf .= $bt."\n"; + } + + $debug_file = $this->getDebugFile(); + + $logdir = dirname($debug_file); + if (!file_exists($logdir)) { + mkdir($logdir); + setperm($logdir); + } + + $f = fopen($debug_file, 'a'); + if ($f) { + fwrite($f, $buf); + fclose($f); + } + } + + $this->reportRecursionLevel--; + } + + public function canReport() { + return $this->reportRecursionLevel < 2; + } + + public function setErrorsStoreType($errorsStoreType) { + $this->errorsStoreType = $errorsStoreType; + } + + public function setMessagesStoreType($messagesStoreType) { + $this->messagesStoreType = $messagesStoreType; + } + + public function checkMessagesStoreType($store_type) { + return $this->messagesStoreType == $store_type || $this->messagesStoreType == self::STORE_BOTH; + } + + public function checkErrorsStoreType($store_type) { + return $this->errorsStoreType == $store_type || $this->errorsStoreType == self::STORE_BOTH; + } + + public function overrideDebugFile($file) { + $this->overridenDebugFile = $file; + } + + protected function getDebugFile() { + global $config; + return is_null($this->overridenDebugFile) ? ROOT.'/'.$config['debug_file'] : $this->overridenDebugFile; + } + + public function setSilence($silent) { + $this->silent = $silent; + } + + public function setPrefix($prefix) { + $this->prefix = $prefix; + } + + public static function errname($errno) { + static $errors = null; + if (is_null($errors)) { + $errors = array_flip(array_slice(get_defined_constants(true)['Core'], 0, 15, true)); + } + return $errors[$errno]; + } + + public static function getTypes() { + return self::$Types; + } + +} + +class debug_measure { + + private $name; + private $time; + private $started = false; + + /** + * @param string $name + * @return $this + */ + public function start($name = null) { + if (is_null($name)) { + $name = strgen(3); + } + $this->name = $name; + $this->time = microtime(true); + $this->started = true; + return $this; + } + + /** + * @return float|string|null + */ + public function finish() { + if (!$this->started) { + debugLog("debug_measure::finish(): not started, name=".$this->name); + return null; + } + + $time = (microtime(true) - $this->time); + debugLog("MEASURE".($this->name != '' ? ' '.$this->name : '').": ".$time); + + $this->started = false; + return $time; + } + +} + +/** + * @param $var + * @return string + */ +function str_print_r($var) { + ob_start(); + print_r($var); + return trim(ob_get_clean()); +} + +/** + * @param $var + * @return string + */ +function str_var_dump($var) { + ob_start(); + var_dump($var); + return trim(ob_get_clean()); +} + +/** + * @param $args + * @param bool $all_dump + * @return string + */ +function str_vars($args, $all_dump = false) { + return implode(' ', array_map(function($a) use ($all_dump) { + if ($all_dump) { + return str_var_dump($a); + } + $type = gettype($a); + if ($type == 'string' || $type == 'integer' || $type == 'double') { + return $a; + } else if ($type == 'array' || $type == 'object') { + return str_print_r($a); + } else { + return str_var_dump($a); + } + }, $args)); +} + +/** + * @param int $shift + * @return string + */ +function backtrace($shift = 0) { + $bt = debug_backtrace(); + $lines = []; + foreach ($bt as $i => $t) { + if ($i < $shift) { + continue; + } + if (!isset($t['file'])) { + $lines[] = 'from ?'; + } else { + $lines[] = 'from '.$t['file'].':'.$t['line']; + } + } + return implode("\n", $lines); +} + +/** + * @param mixed ...$args + */ +function debugLog(...$args) { + global $config; + if (!$config['is_dev']) + return; + + debug::getInstance()->report(false, str_vars($args)); +} + +function debugLogOnProd(...$args) { + debug::getInstance()->report(false, str_vars($args)); +} + +/** + * @param mixed ...$args + */ +function debugError(...$args) { + $debug = debug::getInstance(); + if ($debug->canReport()) { + $debug->report(true, str_vars($args)); + } +} |