diff --git a/CHANGELOG.md b/CHANGELOG.md index c37183a5..a185cac8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ - New #111: Add `DateTime` and `DateTimeImmutable` support as time in log context (@vjik) - New #112: Add `Message::category()` method and `Message::DEFAULT_CATEGORY` constant, deprecate `CategoryFilter::DEFAULT` in favor it (@vjik) +- New #113: Add `Message::trace()` method (@vjik) +- Enh #113: Remove unnecessary `unset` call in `ContextProvider` (@vjik) ## 2.0.0 May 22, 2022 diff --git a/src/ContextProvider/ContextProvider.php b/src/ContextProvider/ContextProvider.php index b6f43dec..11cd4424 100644 --- a/src/ContextProvider/ContextProvider.php +++ b/src/ContextProvider/ContextProvider.php @@ -8,13 +8,7 @@ use Yiisoft\Log\Message; /** - * @psalm-type Backtrace = list + * @psalm-import-type TraceItem from Message */ final class ContextProvider implements ContextProviderInterface { @@ -40,6 +34,7 @@ public function __construct( public function getContext(): array { + /** @psalm-var list $trace */ $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); array_shift($trace); return [ @@ -97,11 +92,11 @@ public function setExcludedTracePaths(array $excludedTracePaths): self /** * Collects a trace when tracing is enabled with {@see Logger::setTraceLevel()}. * - * @param array $backtrace The list of call stack information. - * @psalm-param Backtrace|list $backtrace + * @param array[] $backtrace The list of call stack information. + * @psalm-param list $backtrace * - * @return array Collected a list of call stack information. - * @psalm-return Backtrace + * @return array[] Collected a list of call stack information. + * @psalm-return list */ private function collectTrace(array $backtrace): array { @@ -118,7 +113,6 @@ private function collectTrace(array $backtrace): array ); if (empty($excludedMatch)) { - unset($trace['object'], $trace['args']); $traces[] = $trace; if (++$count >= $this->traceLevel) { break; diff --git a/src/Message.php b/src/Message.php index 5d673700..8010787b 100644 --- a/src/Message.php +++ b/src/Message.php @@ -16,6 +16,14 @@ /** * Message is a data object that stores log message data. + * + * @psalm-type TraceItem = array{ + * file?:string, + * line?:int, + * function?:string, + * class?:string, + * type?:string, + * } */ final class Message { @@ -118,6 +126,27 @@ public function category(): string return $category; } + /** + * Returns the debug trace. + * + * @return array[]|null The debug trace or null if the trace is not set. + * + * @psalm-return list|null + */ + public function trace(): ?array + { + $trace = $this->context['trace'] ?? null; + if ($trace === null) { + return null; + } + + /** + * @psalm-var list $trace We believe that the debug trace in context is always received as result of call + * `debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)`. + */ + return $trace; + } + /** * Parses log message resolving placeholders in the form: "{foo}", * where foo will be replaced by the context data in key "foo". diff --git a/src/Message/Formatter.php b/src/Message/Formatter.php index da43c1ef..a90afc6b 100644 --- a/src/Message/Formatter.php +++ b/src/Message/Formatter.php @@ -248,17 +248,13 @@ private function getContext(Message $message, array $commonContext): string */ private function getTrace(Message $message): string { - $traces = $message->context('trace', []); - if (empty($traces) || !is_array($traces)) { + $traces = $message->trace(); + if ($traces === null) { return ''; } $lines = array_map( static function (mixed $trace): string { - if (!is_array($trace)) { - return '???'; - } - $file = $trace['file'] ?? null; $line = $trace['line'] ?? null; if (is_string($file) && is_int($line)) { diff --git a/tests/Message/FormatterTest.php b/tests/Message/FormatterTest.php index bd71a828..eab89dce 100644 --- a/tests/Message/FormatterTest.php +++ b/tests/Message/FormatterTest.php @@ -215,23 +215,6 @@ public function testFormatWithTraceInContext(string $expectedTrace, array $trace $this->assertSame($expected, $this->formatter->format($message, [])); } - public function testNonArrayTraceItem() - { - $timestamp = 1_508_160_390; - $this->formatter->setTimestampFormat('Y-m-d H:i:s'); - $message = new Message( - LogLevel::INFO, - 'message', - ['category' => 'app', 'time' => $timestamp, 'trace' => [new stdClass()]], - ); - - $expected = "2017-10-16 13:26:30 [info][app] message\n\nMessage context:\n\n" - . "trace:\n ???\n" - . "category: 'app'\ntime: $timestamp\n"; - - $this->assertSame($expected, $this->formatter->format($message, [])); - } - public function invalidCallableReturnStringProvider(): array { return [