diff --git a/src/LogLib/Abstracts/CallType.php b/src/LogLib/Abstracts/CallType.php index b83b4a6..d095a92 100644 --- a/src/LogLib/Abstracts/CallType.php +++ b/src/LogLib/Abstracts/CallType.php @@ -31,4 +31,11 @@ * @var string LAMBDA_CALL */ public const LAMBDA_CALL = 'λ'; + + /** + * Represents an eval() call. + * + * @var string EVAL_CALL + */ + public const EVAL_CALL = 'eval()'; } \ No newline at end of file diff --git a/src/LogLib/Classes/Console.php b/src/LogLib/Classes/Console.php index 41f864a..d96b0ca 100644 --- a/src/LogLib/Classes/Console.php +++ b/src/LogLib/Classes/Console.php @@ -82,17 +82,16 @@ } /** - * Applies a specified color to the given text, based on the event level, using ANSI escape sequences. + * Colorizes the log message based on the event level using ANSI escape sequences. * - * @param Event $event The event object. - * @param string $text The text to apply the color to. - * @return string The text with the specified color applied. + * @param Event $event The log event to colorize. + * @return string The colorized log message. */ - private static function colorize(Event $event, string $text): string + private static function colorize(Event $event): string { if(!Log::getRuntimeOptions()->displayAnsi()) { - return Utilities::levelToString($text); + return Utilities::levelToString($event->getLevel()); } $color = match($event->getLevel()) @@ -108,10 +107,10 @@ if($color === null) { - return Utilities::levelToString($text); + return Utilities::levelToString($event->getLevel()); } - return self::color(Utilities::levelToString($text), $color); + return self::color(Utilities::levelToString($event->getLevel()), $color); } /** @@ -166,30 +165,46 @@ return; } - if(Validate::checkLevelType(LevelType::VERBOSE, Log::getRuntimeOptions()->getLoglevel())) + if(Validate::checkLevelType(LevelType::DEBUG, Log::getRuntimeOptions()->getLoglevel())) { $backtrace_output = Utilities::getTraceString($event, Log::getRuntimeOptions()->displayAnsi()); print(sprintf("[%s] [%s] [%s] %s %s" . PHP_EOL, self::getTimestamp(), self::formatAppColor($options->getApplicationName()), - self::colorize($event, $event->getLevel()), + self::colorize($event), $backtrace_output, $event->getMessage() )); if($event->getException() !== null) { - /** @noinspection NullPointerExceptionInspection */ self::outException($event->getException()); } return; } - print(sprintf("[%s] [%s] [%s] %s" . PHP_EOL, - self::getTimestamp(), + if(Validate::checkLevelType(LevelType::VERBOSE, Log::getRuntimeOptions()->getLoglevel())) + { + $backtrace_output = Utilities::getTraceString($event, Log::getRuntimeOptions()->displayAnsi()); + + print(sprintf("[%s] [%s] %s %s" . PHP_EOL, + self::formatAppColor($options->getApplicationName()), + self::colorize($event), + $backtrace_output, $event->getMessage() + )); + + if($event->getException() !== null) + { + self::outException($event->getException()); + } + + return; + } + + print(sprintf("[%s] [%s] %s" . PHP_EOL, self::formatAppColor($options->getApplicationName()), - self::colorize($event, $event->getLevel()), + self::colorize($event), $event->getMessage() )); } @@ -198,11 +213,16 @@ * Prints information about the given exception, including the error message, error code, * and stack trace. * - * @param Throwable $exception The exception to print information about. + * @param Throwable|null $exception The exception to print information about. * @return void */ - private static function outException(Throwable $exception): void + private static function outException(?Throwable $exception=null): void { + if($exception === null) + { + return; + } + $trace_header = self::color($exception->getFile() . ':' . $exception->getLine(), ConsoleColors::PURPLE); $trace_error = self::color('error: ', ConsoleColors::RED); @@ -223,7 +243,6 @@ { print('Previous Exception:' . PHP_EOL); - /** @noinspection NullPointerExceptionInspection */ self::outException($exception->getPrevious()); } } diff --git a/src/LogLib/Classes/Utilities.php b/src/LogLib/Classes/Utilities.php index e861322..0599f4e 100644 --- a/src/LogLib/Classes/Utilities.php +++ b/src/LogLib/Classes/Utilities.php @@ -4,7 +4,6 @@ use LogLib\Abstracts\CallType; use LogLib\Abstracts\LevelType; - use LogLib\Objects\Backtrace; use LogLib\Objects\Event; use OptsLib\Parse; use Throwable; @@ -14,36 +13,23 @@ /** * Returns a backtrace of the calling code. * - * @param bool $full Determines whether the full backtrace should be returned or not. Default is false. * @return array An array containing backtrace information. - * Each element in the array represents a single call in the call stack and is an instance of the Backtrace class. - * If the debug_backtrace () function is not available, an empty array will be returned. */ - public static function getBacktrace(bool $full=false): array + public static function getBacktrace(): array { if(!function_exists('debug_backtrace')) { return []; } - $backtrace = debug_backtrace(); - $results = []; - - foreach($backtrace as $trace) - { - if(!$full && isset($trace['class']) && str_contains($trace['class'], 'LogLib')) - { - continue; - } - - $results[] = new Backtrace($trace); - } - - return $results; + return debug_backtrace(); } /** + * Converts a log level to its corresponding string representation. * + * @param int $level The log level to convert. + * @return string The string representation of the log level. */ public static function levelToString(int $level): string { @@ -176,19 +162,58 @@ */ public static function getTraceString(Event $event, bool $ansi=false): ?string { - if($event->getBacktrace() === null) + if($event->getBacktrace() === null || count($event->getBacktrace()) === 0) { return CallType::LAMBDA_CALL; } - $backtrace = $event->getBacktrace()[0]; - $function = $backtrace->getFunction(); - $class = $backtrace->getClass(); + $backtrace = $event->getBacktrace()[count($event->getBacktrace()) - 1]; + + // Ignore \LogLib namespace + if(isset($backtrace['class']) && str_starts_with($backtrace['class'], 'LogLib')) + { + if(isset($backtrace['file'])) + { + return ($ansi ? "\033[1;37m" : '') . basename($backtrace['file']) . ($ansi ? "\033[0m" : ''); + } + + return basename($backtrace['file']); + } + + if($backtrace['function'] === '{closure}') + { + if(isset($backtrace['file'])) + { + return ($ansi ? "\033[1;37m" : '') . basename($backtrace['file']) . ($ansi ? "\033[0m" : '') . CallType::STATIC_CALL . CallType::LAMBDA_CALL; + } + + return basename($backtrace['file']) . CallType::STATIC_CALL . CallType::LAMBDA_CALL; + } + + if($backtrace['function'] === 'eval') + { + if(isset($backtrace['file'])) + { + return ($ansi ? "\033[1;37m" : '') . basename($backtrace['file']) . ($ansi ? "\033[0m" : '') . CallType::STATIC_CALL . CallType::EVAL_CALL; + } + + return basename($backtrace['file']) . CallType::STATIC_CALL . CallType::EVAL_CALL; + } if($ansi) { - $function = "\033[1;37m$function\033[0m"; - $class = "\033[1;37m$class\033[0m"; + $function = sprintf("\033[1;37m%s\033[0m", $backtrace['function']); + $class = null; + + if(isset($backtrace["class"])) + { + $class = sprintf("\033[1;37m%s\033[0m", $backtrace['class']); + } + } + else + { + $function = $backtrace['function']; + $class = $backtrace['class'] ?? null; } if($class === null) @@ -196,10 +221,11 @@ return $function . CallType::FUNCTION_CALL; } - $type = ($backtrace->getType() === CallType::METHOD_CALL ? CallType::METHOD_CALL : CallType::STATIC_CALL); + $type = ($backtrace['type'] === CallType::METHOD_CALL ? CallType::METHOD_CALL : CallType::STATIC_CALL); return "{$class}{$type}{$function}" . CallType::FUNCTION_CALL; } + /** * Converts an exception object to an array representation. * diff --git a/src/LogLib/Log.php b/src/LogLib/Log.php index f54e4f8..1a06987 100644 --- a/src/LogLib/Log.php +++ b/src/LogLib/Log.php @@ -110,13 +110,13 @@ * Logs a message with a specified application name, level, optional message, and optional throwable. * * @param string $application_name The name of the application - * @param string $level The level type of the log (default is LevelType::INFO) + * @param int $level The level type of the log (default is LevelType::INFO) * @param string|null $message The message of the log event * @param Throwable|null $throwable The exception that was thrown, if any * @return void * @throws InvalidArgumentException If the provided level type is invalid or a message is null */ - private static function log(string $application_name, string $level=LevelType::INFO, ?string $message=null, ?Throwable $throwable=null): void + private static function log(string $application_name, int $level=LevelType::INFO, ?string $message=null, ?Throwable $throwable=null): void { $application = self::getOptions($application_name); diff --git a/src/LogLib/Objects/Backtrace.php b/src/LogLib/Objects/Backtrace.php deleted file mode 100644 index cf03a73..0000000 --- a/src/LogLib/Objects/Backtrace.php +++ /dev/null @@ -1,179 +0,0 @@ -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; - } - - /** - * Optional. Returns the function name of the backtrace - * - * @return string|null - */ - public function getFunction(): ?string - { - return $this->function; - } - - /** - * Sets the function name of the backtrace - * - * @param string|null $function - */ - public function setFunction(?string $function): void - { - $this->function = $function; - } - - /** - * Optional. Returns the line number of the backtrace - * - * @return int|null - */ - public function getLine(): ?int - { - return $this->line; - } - - /** - * Sets the line number of the backtrace - * - * @param int|null $line - */ - public function setLine(?int $line): void - { - $this->line = $line; - } - - /** - * Optional. Returns the file name of the backtrace - * - * @return string|null - */ - public function getFile(): ?string - { - return $this->file; - } - - /** - * Sets the file name of the backtrace - * - * @param string|null $file - */ - public function setFile(?string $file): void - { - $this->file = $file; - } - - /** - * Optional. Returns the class name, if any, of the backtrace - * - * @return string|null - */ - public function getClass(): ?string - { - return $this->class; - } - - /** - * Sets the class name, if any, of the backtrace - * - * @param string|null $class - */ - public function setClass(?string $class): void - { - $this->class = $class; - } - - /** - * Optional. Returns the current call type. If a method call, "->" is returned. - * - * @return string|null - */ - public function getType(): ?string - { - return $this->type; - } - - /** - * Sets the current call type. If a method call, "->" is returned. - * - * @param string|null $type - */ - public function setType(?string $type): void - { - $this->type = $type; - } - - /** - * Optional. Return the functions arguments or included file name(s) - * - * @return array|null - */ - public function getArgs(): ?array - { - return $this->args; - } - - /** - * Sets the function arguments or included file name(s) - * - * @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 5ca960b..406c890 100644 --- a/src/LogLib/Objects/Event.php +++ b/src/LogLib/Objects/Event.php @@ -12,12 +12,12 @@ { /** * @see LevelType - * @var string + * @var int */ private $level; /** - * @var Backtrace[]|null + * @var array|null */ private $backtrace; diff --git a/tests/logging.php b/tests/logging.php index 8afcbaf..a2e846b 100644 --- a/tests/logging.php +++ b/tests/logging.php @@ -1,6 +1,5 @@ testLogging(); + + eval('\LogLib\Log::debug(\'net.nosial.optslib\', \'This is a debug message\');'); + eval('\LogLib\Log::verbose(\'net.nosial.optslib\', \'This is a verbose message\');'); + + $callable = static function() + { + Log::info('net.nosial.optslib', 'This is an info message'); + Log::warning('net.nosial.optslib', 'This is a warning message'); + Log::error('net.nosial.optslib', 'This is an error message'); + Log::fatal('net.nosial.optslib', 'This is a fatal message'); + }; + + $callable(); + + + class test2 + { + public function testEval(): void + { + eval('\LogLib\Log::debug(\'net.nosial.optslib\', \'This is a debug message\');'); + eval('\LogLib\Log::verbose(\'net.nosial.optslib\', \'This is a verbose message\');'); + } + + public function testCallable(): void + { + $b = static function() + { + Log::info('net.nosial.optslib', 'This is an info message'); + Log::warning('net.nosial.optslib', 'This is a warning message'); + Log::error('net.nosial.optslib', 'This is an error message'); + Log::fatal('net.nosial.optslib', 'This is a fatal message'); + }; + + $b(); + } + } + + $test2 = new test2(); + $test2->testEval(); + $test2->testCallable(); \ No newline at end of file