From 6082fcf8d23cb0edcd37a0120a26b26750a2073c Mon Sep 17 00:00:00 2001 From: sunxyw Date: Fri, 13 May 2022 02:36:05 +0800 Subject: [PATCH 1/5] refactor console logger --- src/ZM/Logger/ConsoleLogger.php | 189 +++++++++++++++++++++----------- 1 file changed, 122 insertions(+), 67 deletions(-) diff --git a/src/ZM/Logger/ConsoleLogger.php b/src/ZM/Logger/ConsoleLogger.php index 88b1a17..dd6f14e 100644 --- a/src/ZM/Logger/ConsoleLogger.php +++ b/src/ZM/Logger/ConsoleLogger.php @@ -12,24 +12,41 @@ class ConsoleLogger extends AbstractLogger { public const VERSION = '1.0.0-alpha'; + /** + * 日志输出格式 + * + * @var string + */ public static $format = '[%date%] [%level%] %process%%body%'; + /** + * 日志输出日期格式 + * + * @var string + */ public static $date_format = 'Y-m-d H:i:s'; /** - * @var string[][] 颜色表 + * 颜色表 + * + * @var array{int, array{string}} */ protected static $styles = [ - LogLevel::EMERGENCY => ['blink', 'white', 'bg_bright_red'], - LogLevel::ALERT => ['white', 'bg_bright_red'], - LogLevel::CRITICAL => ['underline', 'red'], - LogLevel::ERROR => ['red'], - LogLevel::WARNING => ['bright_yellow'], - LogLevel::NOTICE => ['cyan'], - LogLevel::INFO => ['green'], - LogLevel::DEBUG => ['gray'], + ['blink', 'white', 'bg_bright_red'], // emergency + ['white', 'bg_bright_red'], // alert + ['underline', 'red'], // critical + ['red'], // error + ['bright_yellow'], // warning + ['cyan'], // notice + ['green'], // info + ['gray'], // debug ]; + /** + * 等级表 + * + * @var array{int, int} + */ protected static $levels = [ LogLevel::EMERGENCY, // 0 LogLevel::ALERT, // 1 @@ -41,31 +58,44 @@ class ConsoleLogger extends AbstractLogger LogLevel::DEBUG, // 7 ]; - protected static $logLevel; + /** + * 当前日志等级 + * + * @var int + */ + protected static $log_level; - protected $exceptionHandler; - - public function __construct($logLevel = LogLevel::INFO) + /** + * 创建一个 ConsoleLogger 实例 + * + * @param string $level 日志等级 + */ + public function __construct(string $level = LogLevel::INFO) { - self::$logLevel = array_flip(self::$levels)[$logLevel]; - //ExceptionHandler::getInstance(); + self::$log_level = $this->castLogLevel($level); } /** - * @return string[][] + * 获取当前样式表 + * + * @return array{int, array{string}} */ public static function getStyles(): array { return self::$styles; } - public function colorize($string, $level): string + /** + * 获取版本号 + */ + public static function getVersion(): string { - $string = $this->stringify($string); - $styles = self::$styles[$level] ?? []; - return ConsoleColor::apply($styles, $string)->__toString(); + return self::VERSION; } + /** + * 打印执行栈 + */ public function trace(): void { $log = "Stack trace:\n"; @@ -84,82 +114,107 @@ class ConsoleLogger extends AbstractLogger } $log .= "{$t['function']}()\n"; } - $log = $this->colorize($log, LogLevel::DEBUG); + $log = $this->colorize($log, $this->castLogLevel(LogLevel::DEBUG)); echo $log; } - public function getTrace(): string + /** + * 根据日志等级将样式应用至指定字符串 + * + * @param mixed $string 日志内容 + * @param int $level 日志等级 + */ + public function colorize($string, int $level): string { -// if (self::$info_level !== null && self::$info_level == 4) { -// $trace = debug_backtrace()[2] ?? ['file' => '', 'function' => '']; -// $trace = '[' . ($trace['class'] ?? '') . ':' . ($trace['function'] ?? '') . '] '; -// } -// return $trace ?? ''; - return ''; + $string = $this->stringify($string); + $styles = self::$styles[$level] ?? []; + return ConsoleColor::apply($styles, $string)->__toString(); } -// $trace = debug_backtrace()[1] ?? ['file' => '', 'function' => '']; -// $trace = '[' . ($trace['class'] ?? '') . ':' . ($trace['function'] ?? '') . '] '; - + /** + * {@inheritDoc} + */ public function log($level, $message, array $context = []): void { - if (!in_array($level, self::$levels, true)) { - throw new InvalidArgumentException(); - } + $level = $this->castLogLevel($level); - if (array_flip(self::$levels)[$level] > self::$logLevel) { + if (!$this->shouldLog($level)) { return; } $output = str_replace( ['%date%', '%level%', '%body%'], - [date(self::$date_format), strtoupper(substr($level, 0, 4)), $message], + [date(self::$date_format), strtoupper(substr(self::$levels[$level], 0, 4)), $message], self::$format ); $output = $this->interpolate($output, $context); echo $this->colorize($output, $level) . "\n"; } - public static function getVersion(): string + /** + * 转换日志等级 + */ + private function castLogLevel(string $level): int { - return self::VERSION; + if (in_array($level, self::$levels, true)) { + return array_flip(self::$levels)[$level]; + } + + throw new InvalidArgumentException('无效的日志等级'); } - private function stringify($item) + /** + * 将日志内容转换为字符串 + * + * @param mixed $item 日志内容 + */ + private function stringify($item): string { - if (is_object($item) && method_exists($item, '__toString')) { - return $item; + switch (true) { + case is_callable($item): + if (is_array($item)) { + if (is_object($item[0])) { + return get_class($item[0]) . '@' . $item[1]; + } + return $item[0] . '::' . $item[1]; + } + return 'closure'; + case is_string($item): + return $item; + case is_array($item): + return 'array' . json_encode($item, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS); + case is_object($item): + return get_class($item); + case is_resource($item): + return 'resource(' . get_resource_type($item) . ')'; + case is_null($item): + return 'null'; + case is_bool($item): + return $item ? 'true' : 'false'; + case is_float($item): + case is_int($item): + return (string) $item; + default: + return 'unknown'; } - if (is_string($item) || is_numeric($item)) { - return $item; - } - if (is_callable($item)) { - return '{Closure}'; - } - if (is_bool($item)) { - return $item ? '*True*' : '*False*'; - } - if (is_array($item)) { - return json_encode( - $item, - JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS - ); - } - if (is_resource($item)) { - return '{Resource}'; - } - if (is_null($item)) { - return 'NULL'; - } - return '{Not Stringable Object:' . get_class($item) . '}'; } - private function interpolate($message, array $context = []) + /** + * 判断是否应该记录该等级日志 + */ + private function shouldLog(int $level): bool { - if (is_array($message)) { - return $message; - } + return $level <= self::$log_level; + } + /** + * 插入变量到日志内容中 + * + * @param string $message 日志内容 + * @param array $context 变量列表 + */ + private function interpolate(string $message, array $context = []): string + { $replace = []; foreach ($context as $key => $value) { $replace['{' . $key . '}'] = $this->stringify($value); From bfa816f734e8ddea98c22507765899e6d781247c Mon Sep 17 00:00:00 2001 From: sunxyw Date: Fri, 13 May 2022 18:06:03 +0800 Subject: [PATCH 2/5] remove legacy process placeholder --- src/ZM/Logger/ConsoleLogger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ZM/Logger/ConsoleLogger.php b/src/ZM/Logger/ConsoleLogger.php index dd6f14e..ae2eb7b 100644 --- a/src/ZM/Logger/ConsoleLogger.php +++ b/src/ZM/Logger/ConsoleLogger.php @@ -17,7 +17,7 @@ class ConsoleLogger extends AbstractLogger * * @var string */ - public static $format = '[%date%] [%level%] %process%%body%'; + public static $format = '[%date%] [%level%] %body%'; /** * 日志输出日期格式 From 5423de6df5e9ebac9574ec7305458906dd0580b8 Mon Sep 17 00:00:00 2001 From: sunxyw Date: Fri, 13 May 2022 18:33:57 +0800 Subject: [PATCH 3/5] add static context support --- src/ZM/Logger/ConsoleLogger.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ZM/Logger/ConsoleLogger.php b/src/ZM/Logger/ConsoleLogger.php index ae2eb7b..69732c5 100644 --- a/src/ZM/Logger/ConsoleLogger.php +++ b/src/ZM/Logger/ConsoleLogger.php @@ -65,6 +65,13 @@ class ConsoleLogger extends AbstractLogger */ protected static $log_level; + /** + * 静态上下文 + * + * @var array + */ + protected $static_context = []; + /** * 创建一个 ConsoleLogger 实例 * @@ -147,10 +154,18 @@ class ConsoleLogger extends AbstractLogger [date(self::$date_format), strtoupper(substr(self::$levels[$level], 0, 4)), $message], self::$format ); - $output = $this->interpolate($output, $context); + $output = $this->interpolate($output, array_merge($this->static_context, $context)); echo $this->colorize($output, $level) . "\n"; } + /** + * 添加静态上下文 + */ + public function addStaticContext(array $context): void + { + $this->static_context = array_merge($this->static_context, $context); + } + /** * 转换日志等级 */ From 3e10a5b758cbbbfcfd1ce009dd22814fa8ae056a Mon Sep 17 00:00:00 2001 From: sunxyw Date: Fri, 13 May 2022 18:38:23 +0800 Subject: [PATCH 4/5] optimize type hints --- src/ZM/Logger/ConsoleLogger.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ZM/Logger/ConsoleLogger.php b/src/ZM/Logger/ConsoleLogger.php index 69732c5..f715f23 100644 --- a/src/ZM/Logger/ConsoleLogger.php +++ b/src/ZM/Logger/ConsoleLogger.php @@ -29,7 +29,7 @@ class ConsoleLogger extends AbstractLogger /** * 颜色表 * - * @var array{int, array{string}} + * @var string[][] */ protected static $styles = [ ['blink', 'white', 'bg_bright_red'], // emergency @@ -45,7 +45,7 @@ class ConsoleLogger extends AbstractLogger /** * 等级表 * - * @var array{int, int} + * @var string[] */ protected static $levels = [ LogLevel::EMERGENCY, // 0 @@ -85,7 +85,7 @@ class ConsoleLogger extends AbstractLogger /** * 获取当前样式表 * - * @return array{int, array{string}} + * @return string[][] */ public static function getStyles(): array { From 9bfa140de152b9a9bfd71ca8b945bee8ea25cf07 Mon Sep 17 00:00:00 2001 From: sunxyw Date: Fri, 13 May 2022 19:43:52 +0800 Subject: [PATCH 5/5] add log callback feature --- composer.json | 3 ++- src/ZM/Logger/ConsoleLogger.php | 38 ++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 6dad9dd..c17b69d 100644 --- a/composer.json +++ b/composer.json @@ -57,6 +57,7 @@ "[ $COMPOSER_DEV_MODE -eq 0 ] || vendor/bin/cghooks add" ], "analyse": "phpstan analyse --memory-limit 300M", - "cs-fix": "php-cs-fixer fix" + "cs-fix": "php-cs-fixer fix", + "test": "phpunit --no-coverage" } } diff --git a/src/ZM/Logger/ConsoleLogger.php b/src/ZM/Logger/ConsoleLogger.php index f715f23..8d0de4f 100644 --- a/src/ZM/Logger/ConsoleLogger.php +++ b/src/ZM/Logger/ConsoleLogger.php @@ -72,6 +72,13 @@ class ConsoleLogger extends AbstractLogger */ protected $static_context = []; + /** + * 日志记录回调 + * + * @var callable[] + */ + protected $log_callbacks = []; + /** * 创建一个 ConsoleLogger 实例 * @@ -100,6 +107,22 @@ class ConsoleLogger extends AbstractLogger return self::VERSION; } + /** + * 添加静态上下文 + */ + public function addStaticContext(array $context): void + { + $this->static_context = array_merge($this->static_context, $context); + } + + /** + * 添加日志记录回调 + */ + public function addLogCallback(callable $callback): void + { + $this->log_callbacks[] = $callback; + } + /** * 打印执行栈 */ @@ -155,15 +178,14 @@ class ConsoleLogger extends AbstractLogger self::$format ); $output = $this->interpolate($output, array_merge($this->static_context, $context)); - echo $this->colorize($output, $level) . "\n"; - } - /** - * 添加静态上下文 - */ - public function addStaticContext(array $context): void - { - $this->static_context = array_merge($this->static_context, $context); + foreach ($this->log_callbacks as $callback) { + if ($callback($level, $output, $message, $context) === false) { + return; + } + } + + echo $this->colorize($output, $level) . "\n"; } /**