From cdf3eae890d17fd0df631ecc1fdd5b719f0916aa Mon Sep 17 00:00:00 2001 From: Netkas Date: Sat, 31 Dec 2022 01:23:30 -0500 Subject: [PATCH] Improved backtracing --- src/LogLib/Classes/Console.php | 9 +-- src/LogLib/Classes/FileLogging.php | 7 +- src/LogLib/Classes/Utilities.php | 105 ++++++++---------------- src/LogLib/Log.php | 6 ++ src/LogLib/Objects/Backtrace.php | 126 +++++++++++++++++++++++++++-- src/LogLib/Objects/Event.php | 21 ++++- tests/test_backtrace.php | 8 ++ 7 files changed, 192 insertions(+), 90 deletions(-) create mode 100644 tests/test_backtrace.php diff --git a/src/LogLib/Classes/Console.php b/src/LogLib/Classes/Console.php index 50be148..44b2c18 100644 --- a/src/LogLib/Classes/Console.php +++ b/src/LogLib/Classes/Console.php @@ -108,15 +108,14 @@ if(Validate::checkLevelType(LevelType::Verbose, Log::getRuntimeOptions()->getLogLevel())) { - $backtrace_output = Utilities::parseBacktrace($event); + $backtrace_output = Utilities::getTraceString($event, Log::getRuntimeOptions()->isDisplayAnsi()); print(sprintf( - "%s [%s] [%s] (%s) - %s" . PHP_EOL, + "%s [%s] [%s] %s %s" . PHP_EOL, $event->getTimestamp(), self::formatAppColor($options->getApplicationName()), self::colorize($event, $event->Level), - $backtrace_output !== null ? $backtrace_output : 'λ', - $event->Message + $backtrace_output, $event->Message )); if($event->Exception !== null) @@ -126,7 +125,7 @@ } print(sprintf( - "%s [%s] [%s] - %s" . PHP_EOL, + "%s [%s] [%s] %s" . PHP_EOL, $event->getTimestamp(), self::formatAppColor($options->getApplicationName()), self::colorize($event, $event->Level), diff --git a/src/LogLib/Classes/FileLogging.php b/src/LogLib/Classes/FileLogging.php index a115480..b2158be 100644 --- a/src/LogLib/Classes/FileLogging.php +++ b/src/LogLib/Classes/FileLogging.php @@ -21,14 +21,11 @@ */ public static function out(Options $options, Event $event, ?FileHandle $fileHandle=null): void { - $backtrace_output = Utilities::parseBacktrace($event); + $backtrace_output = Utilities::getTraceString($event); $handle = $fileHandle ?? $options->getFileHandle(); switch($event->Level) { - // Only process Debug/Verbose events if the log level is set to Debug/Verbose - // otherwise omit it because it could be a performance hit if there are a lot of - // debug/verbose events being logged. case LevelType::Debug: case LevelType::Verbose: if(!Validate::checkLevelType($event->Level, Log::getRuntimeOptions()->getLogLevel())) @@ -40,7 +37,7 @@ } $handle->fwrite(sprintf( - "%s [%s] [%s] (%s) - %s" . PHP_EOL, + "%s [%s] [%s] (%s) %s" . PHP_EOL, $event->getTimestamp(), $options->getApplicationName(), Utilities::levelToString($event->Level), diff --git a/src/LogLib/Classes/Utilities.php b/src/LogLib/Classes/Utilities.php index dd614f5..7e34c46 100644 --- a/src/LogLib/Classes/Utilities.php +++ b/src/LogLib/Classes/Utilities.php @@ -6,17 +6,16 @@ use LogLib\Objects\Backtrace; use LogLib\Objects\Event; use OptsLib\Parse; - use Properties\Prop; - use Throwable; class Utilities { /** * Returns the current backtrace * - * @return Backtrace[] + * @param bool $full + * @return array */ - public static function getBacktrace(): array + public static function getBacktrace(bool $full=false): array { if(!function_exists('debug_backtrace')) return []; @@ -26,31 +25,10 @@ foreach($backtrace as $trace) { - $results[] = Prop::fromArray($trace); - } + if(isset($trace['class'] ) && str_contains($trace['class'], 'LogLib') && !$full) + continue; - return $results; - } - - /** - * @param Throwable $e - * @return array - */ - public static function exceptionToArray(Throwable $e): array - { - $results = [ - 'hash' => spl_object_hash($e), - 'type' => get_class($e), - 'message' => $e->getMessage(), - 'code' => $e->getCode(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'trace' => $e->getTrace(), - ]; - - if($e->getPrevious() !== null) - { - $results['previous'] = self::exceptionToArray($e->getPrevious()); + $results[] = new Backtrace($trace); } return $results; @@ -124,6 +102,7 @@ case 'vrb': return LevelType::Verbose; + default: case LevelType::Info: case 'info': case '4': @@ -153,9 +132,6 @@ case '0': case 'sil': return LevelType::Silent; - - default: - return LevelType::Info; } } @@ -202,46 +178,6 @@ return date('Y-m-d') . '.log'; } - /** - * Returns the formatted backtrace - * - * @param Event $event - * @return string|null - */ - public static function parseBacktrace(Event $event): ?string - { - $backtrace = null; - if ($event->Backtrace !== null && count($event->Backtrace) > 0) - { - foreach ($event->Backtrace as $item) - { - if ($item->Class !== 'LogLib\\Log') - { - $backtrace = $item; - break; - } - } - } - - $backtrace_output = null; - if ($backtrace !== null) - { - if ($backtrace->Class !== null) - { - $backtrace_output = $backtrace->Class . $backtrace->Type . $backtrace->Function . '()'; - } - else - { - $backtrace_output = $backtrace->Function . '()'; - } - - if ($backtrace->Line !== null) - $backtrace_output .= ':' . $backtrace->Line; - } - - return $backtrace_output; - } - /** * Returns a random string of characters * @@ -260,4 +196,31 @@ return $randomString; } + /** + * @param Event $event + * @param bool $ansi + * @return string|null + */ + public static function getTraceString(Event $event, bool $ansi=false): ?string + { + if($event->getBacktrace() == null) + return 'λ'; + + $backtrace = $event->getBacktrace()[0]; + $function = $backtrace->getFunction(); + $class = $backtrace->getClass(); + + if($ansi) + { + $function = "\033[1;37m$function\033[0m"; + $class = "\033[1;37m$class\033[0m"; + } + + if($class == null) + return "{$function}()"; + + $type = ($backtrace->getType() == '->' ? '->' : '::'); + return "{$class}{$type}{$function}()"; + } + } \ No newline at end of file diff --git a/src/LogLib/Log.php b/src/LogLib/Log.php index 058fee0..49e8ac4 100644 --- a/src/LogLib/Log.php +++ b/src/LogLib/Log.php @@ -8,10 +8,12 @@ use LogLib\Abstracts\LevelType; use LogLib\Classes\Console; use LogLib\Classes\FileLogging; + use LogLib\Classes\Utilities; use LogLib\Classes\Validate; use LogLib\Objects\Event; use LogLib\Objects\Options; use LogLib\Objects\RuntimeOptions; + use Properties\Exceptions\ReconstructException; use Throwable; class Log @@ -97,6 +99,7 @@ * @param string|null $message The message of the event * @param Throwable|null $throwable The exception that was thrown, if any * @return void + * @throws ReconstructException */ private static function log(string $application_name, string $level=LevelType::Info, ?string $message=null, ?Throwable $throwable=null): void { @@ -115,6 +118,9 @@ $event->Message = $message; $event->Exception = $throwable; + if($event->getBacktrace() == null) + $event->setBacktrace(Utilities::getBacktrace()); + if(self::getRuntimeOptions()->isConsoleOutput()) Console::out($application, $event); diff --git a/src/LogLib/Objects/Backtrace.php b/src/LogLib/Objects/Backtrace.php index fb49dac..bc9f38b 100644 --- a/src/LogLib/Objects/Backtrace.php +++ b/src/LogLib/Objects/Backtrace.php @@ -12,7 +12,7 @@ * @var string|null * @property_name function */ - public $Function; + private $Function; /** * The line number of the backtrace @@ -20,7 +20,7 @@ * @var int|null * @property_name line */ - public $Line; + private $Line; /** * The file name of the backtrace @@ -28,7 +28,7 @@ * @var string|null * @property_name file */ - public $File; + private $File; /** * The class name, if any, of the backtrace @@ -36,7 +36,7 @@ * @var string|null * @property_name class */ - public $Class; + private $Class; /** * The current call type. If a method call, "->" is returned. @@ -47,7 +47,7 @@ * @var string|null * @property_name type */ - public $Type; + private $Type; /** * If inside a function, this lists the functions arguments. If inside @@ -56,5 +56,119 @@ * @var array|null * @property_name args */ - public $Args; + private $Args; + + /** + * Public Constructor + * + * @param array|null $backtrace + */ + public function __construct(?array $backtrace=null) + { + if($backtrace === null) + return; + + $this->Function = $backtrace['function'] ?? null; + $this->Line = $backtrace['line'] ?? null; + $this->File = $backtrace['file'] ?? null; + $this->Class = $backtrace['class'] ?? null; + $this->Type = $backtrace['type'] ?? null; + $this->Args = $backtrace['args'] ?? null; + } + + /** + * @return string|null + */ + public function getFunction(): ?string + { + return $this->Function; + } + + /** + * @param string|null $Function + */ + public function setFunction(?string $Function): void + { + $this->Function = $Function; + } + + /** + * @return int|null + */ + public function getLine(): ?int + { + return $this->Line; + } + + /** + * @param int|null $Line + */ + public function setLine(?int $Line): void + { + $this->Line = $Line; + } + + /** + * @return string|null + */ + public function getFile(): ?string + { + return $this->File; + } + + /** + * @param string|null $File + */ + public function setFile(?string $File): void + { + $this->File = $File; + } + + /** + * @return string|null + */ + public function getClass(): ?string + { + return $this->Class; + } + + /** + * @param string|null $Class + */ + public function setClass(?string $Class): void + { + $this->Class = $Class; + } + + /** + * @return string|null + */ + public function getType(): ?string + { + return $this->Type; + } + + /** + * @param string|null $Type + */ + public function setType(?string $Type): void + { + $this->Type = $Type; + } + + /** + * @return array|null + */ + public function getArgs(): ?array + { + return $this->Args; + } + + /** + * @param array|null $Args + */ + public function setArgs(?array $Args): void + { + $this->Args = $Args; + } } \ No newline at end of file diff --git a/src/LogLib/Objects/Event.php b/src/LogLib/Objects/Event.php index a8c6067..dbcc70f 100644 --- a/src/LogLib/Objects/Event.php +++ b/src/LogLib/Objects/Event.php @@ -7,7 +7,6 @@ use LogLib\Abstracts\LevelType; use LogLib\Classes\Utilities; use Throwable; - class Event { /** @@ -33,7 +32,7 @@ * @var Backtrace[]|null * @property_name backtrace */ - public $Backtrace; + private $Backtrace; /** * The exception that was thrown, if any @@ -53,7 +52,7 @@ public function __construct() { - $this->Timestamp = date('Y-m-dTH:i:s.v') . (date('p') == 'Z' ? 'Z' : 'L'); + $this->Timestamp = date('c'); } /** @@ -75,4 +74,20 @@ return $this->Timestamp; } + /** + * @return array|null + */ + public function getBacktrace(): ?array + { + return $this->Backtrace; + } + + /** + * @param array|null $Backtrace + */ + public function setBacktrace(?array $Backtrace): void + { + $this->Backtrace = $Backtrace; + } + } \ No newline at end of file diff --git a/tests/test_backtrace.php b/tests/test_backtrace.php new file mode 100644 index 0000000..ba8ad3b --- /dev/null +++ b/tests/test_backtrace.php @@ -0,0 +1,8 @@ +