From 53883e9153b85f9ef947ae66a36d79f2e6fc3e43 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Fri, 20 Dec 2024 17:27:13 +0100 Subject: [PATCH] error.php: wip --- inc/error.php | 133 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 4 deletions(-) diff --git a/inc/error.php b/inc/error.php index 4c8eb19e..7ebf6296 100644 --- a/inc/error.php +++ b/inc/error.php @@ -1,9 +1,134 @@ include_details = $include_details; + $this->logger_fn = [ __CLASS__, 'default_logger' ]; + } + + public function setLogger(?callable $logger_fn) { + $this->logger_fn = $logger_fn !== null ? $logger_fn : [ __CLASS__, 'default_logger' ]; + } + + public function installGlobally() { + $logger_fn = $this->logger_fn; + $include_details = $this->include_details; + + \set_error_handler(function($errno, $errstr, $errfile, $errline) use ($logger_fn, $include_details) { + $errno = \error_reporting() & $errno; + if ($errno !== 0) { + $level = self::errnoToLogLevel($errno); + + // https://stackoverflow.com/a/35930682 + $trace = (new \Exception)->getTraceAsString(); + self::handle_error($level, $errstr, $logger_fn, $include_details, $errfile, $errline, $trace); + } + return false; + }); + + \set_exception_handler(function($exception) use ($logger_fn, $include_details) { + $message = $exception->getMessage(); + $file = $exception->getFile(); + $line = $exception->getLine(); + $trace = $exception->getTraceAsString(); + + self::handle_error(\LOG_EMERG, $message, $logger_fn, $include_details, $file, $line, $trace); + }); + + \register_shutdown_function(function() use ($logger_fn, $include_details) { + $error = \error_get_last(); + if ($error !== null) { + $level = self::errnoToLogLevel($error['type']); + $message = $error['message']; + $file = $error['file']; + $line = $error['line']; + + self::handle_error($level, $message, $logger_fn, $include_details, $file, $line, null); + } + }); + } +} + +/** + * Install a fancy error handler with the given logger. + * + * @param ?callable $logger Called when there is to log something. Use null to use the minimal default implementation. + * The callable is invoke with two parameters, the first being the log level (integer), as + * listed by the syslog constants, the second is the log message (string). + * Consider that $config may not have been initialized yet. + */ +function install_error_handler(bool $basic, ?callable $logger_fn): void { + global $config; + + $logger_fn ??= function($level, $message) use ($config) { + if (isset($config['syslog']) && $config['syslog']) { + _syslog($level, $message); + } else { + \error_log($message); + } + }; + + if (!$basic) { + \set_error_handler(function($errno, $errstr, $errfile, $errline) use ($config) { + if (\error_reporting() & $errno) { + $config['debug'] = true; + \error("$errstr in $errfile at line $errline"); + } + return false; + }); } return false; }