From 9a397d796d79d8b34b589044b7a148d6bc210fd9 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 6 Jun 2018 13:28:39 +0200 Subject: [PATCH 1/6] The Humand Readable Formatter is now even more human readable. --- .../HumanReadableExceptionFormatter.php | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/Formatter/HumanReadableExceptionFormatter.php b/src/Formatter/HumanReadableExceptionFormatter.php index eca7bec..dcc02ad 100644 --- a/src/Formatter/HumanReadableExceptionFormatter.php +++ b/src/Formatter/HumanReadableExceptionFormatter.php @@ -2,14 +2,13 @@ namespace PolderKnowledge\LogModule\Formatter; -use Monolog\Formatter\FormatterInterface; -use Monolog\Formatter\NormalizerFormatter; +use Monolog\Formatter\LineFormatter; use WShafer\PSR11MonoLog\FactoryInterface; /** * Format an Exception in a similar way PHP does by default when an exception bubbles to the top */ -class HumanReadableExceptionFormatter extends NormalizerFormatter implements FormatterInterface, FactoryInterface +class HumanReadableExceptionFormatter extends LineFormatter implements FactoryInterface { public function __invoke(array $options) { @@ -23,25 +22,47 @@ public function __invoke(array $options) public function format(array $record): string { $exception = $record['context']['exception'] ?? null; - if ($exception) { - return $this->printFromException($exception); - } else { - return $this->printWithoutException($record); + + if (!$exception) { + return parent::format($record); } + + return $this->printFromThrowable($record, $exception); } - protected function printWithoutException(array $record): string + protected function printFromThrowable(array $record, \Throwable $throwable) { - return sprintf("[%s] %s: %s\n", ...[ - date('r'), + $record = $this->normalize($record); + + $result = sprintf( + "[%s] %s.%s: %s\n\n", + $record['datetime'], + $record['channel'], $record['level_name'], $record['message'] - ]); + ); + + $result .= "[Context]\n"; + $result .= sprintf(" Type: %s\n", get_class($throwable)); + $result .= sprintf(" Code: %d\n", $throwable->getCode()); + $result .= sprintf(" File: %s\n", $throwable->getFile()); + $result .= sprintf(" Line: %d\n\n", $throwable->getLine()); + + $result .= "[Trace]\n"; + $result .= $this->buildTraceOutput($throwable->getTraceAsString()); + $result .= "\n\n"; + + return $result; } - - protected function printFromException(\Throwable $exception) + + private function buildTraceOutput($trace) { - return implode("\n", ExceptionPrinter::linesFromException($exception)) . "\n" - . "---------------------------------------\n"; + $lines = explode("\n", $trace); + + $indented = array_map(function ($item) { + return ' ' . $item; + }, $lines); + + return implode("\n", $indented); } } From 561a16eb9e24fa7e49339e51352c00a2756ca9df Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 6 Jun 2018 13:32:09 +0200 Subject: [PATCH 2/6] Removed the ExceptionPrinter class, it's no longer being used --- src/Formatter/ExceptionPrinter.php | 139 ----------------------------- 1 file changed, 139 deletions(-) delete mode 100644 src/Formatter/ExceptionPrinter.php diff --git a/src/Formatter/ExceptionPrinter.php b/src/Formatter/ExceptionPrinter.php deleted file mode 100644 index 38d09c9..0000000 --- a/src/Formatter/ExceptionPrinter.php +++ /dev/null @@ -1,139 +0,0 @@ -getTrace() as $traceLine) { - $lines[] = self::formatTraceLine($traceLine); - } - - if ($exception->getPrevious()) { - $previousLines = self::linesFromException($exception->getPrevious(), true); - - // recursion makes sure deeper nesting has longer prefixes - foreach ($previousLines as $previousLine) { - $lines[] = ' ' . $previousLine; - } - } - - return $lines; - } - - public static function printFirstLineFromException(\Throwable $exception, bool $nested): string - { - return sprintf('[%s] %s: %s in %s:%s', ...[ - // only the root exception has a timestamp - $nested ? 'Previous Exception' : date('r'), - get_class($exception), - $exception->getMessage(), - $exception->getFile(), - $exception->getLine() - ]); - } - - /** - * Transform an element of the array Exception::getTrace - * to a string of a single line - * - * @param mixed[] $trace element of Exception::getTrace - * @return string of a single line - */ - public static function formatTraceLine(array $trace): string - { - $output = ''; - - // only display file if we're not in the context of a class - // to save space for the sake for readability of the stack trace - if (isset($trace['file']) && !isset($trace['class'])) { - $output .= $trace['file']; - - if (isset($trace['line'])) { - $output .= '(' . $trace['line'] . ')'; - } - - if (!isset($trace['function'])) { - return $output; - } - } - - $output .= $trace['class'] ?? ''; - $output .= $trace['type'] ?? ''; - $output .= $trace['function'] ?? ''; - - if (isset($trace['function'])) { - $arguments = self::formatArguments($trace['args'] ?? []); - $output .= '(' . $arguments . ')'; - } - - // print line number now if we skipped it - if (isset($trace['class']) && isset($trace['line'])) { - $output .= ':' . $trace['line']; - } - - return $output; - } - - /** - * Convert function arguments of any type to a short readable string - * - * @param mixed[] $arguments - * @return string a summary of the list of arguments - */ - public static function formatArguments(array $arguments): string - { - return implode(', ', array_map([__CLASS__, 'formatArgument'], $arguments)); - } - - /** - * Summarize a variable - * - * @param mixed $argument anything at all - * @return string a summary of the argument - */ - public static function formatArgument($argument): string - { - if (is_object($argument)) { - return get_class($argument); - } - - if (is_int($argument) || is_float($argument)) { - return $argument; - } - - if (is_string($argument)) { - return self::truncateString($argument); - } - - if ($argument === false) { - return 'false'; - } - - if ($argument === true) { - return 'true'; - } - - if (is_array($argument)) { - return 'array(' . count($argument) . ')'; - } - - // resource or null - return gettype($argument); - } - - public static function truncateString(string $argument): string - { - if (strlen($argument) < 80) { - $truncated = $argument; - } else { - $truncated = substr($argument, 0, 30) . '...' . substr($argument, -30, 30); - } - - return "'$truncated'"; - } -} From 6b4e5a02b0398012608244c12916c332147d8d0b Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 6 Jun 2018 14:01:54 +0200 Subject: [PATCH 3/6] Removed unit tests that are no longer valid --- tests/Formatter/FormatArgumentTest.php | 38 ------------------ tests/Formatter/FormatTraceTest.php | 55 -------------------------- 2 files changed, 93 deletions(-) delete mode 100644 tests/Formatter/FormatArgumentTest.php delete mode 100644 tests/Formatter/FormatTraceTest.php diff --git a/tests/Formatter/FormatArgumentTest.php b/tests/Formatter/FormatArgumentTest.php deleted file mode 100644 index 4107373..0000000 --- a/tests/Formatter/FormatArgumentTest.php +++ /dev/null @@ -1,38 +0,0 @@ -getTrace(); - - self::assertEquals( - "MyClass->MyMethod(false, 'mystring', array(3), stdClass, NULL):42", - ExceptionPrinter::formatTraceLine($trace[0]) - ); - - self::assertEquals( - 'index.php(144)', - ExceptionPrinter::formatTraceLine($trace[1]) - ); - - } - - private function getTrace() - { - return [ - [ - 'file' => 'MyClass.php', - 'line' => 42, - 'class' => 'MyClass', - 'type' => '->', - 'function' => 'MyMethod', - 'args' => [ - false, - 'mystring', - [0, 0, 0], - new \stdClass, - null, - ], - ], [ - 'file' => 'index.php', - 'line' => '144', - 'class' => null, - 'type' => null, - 'function' => null, - 'args' => null, - ] - ]; - } -} From 325fd35fa92b1869a2fb9ba20e914168b3a5f66c Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 6 Jun 2018 16:04:41 +0200 Subject: [PATCH 4/6] Implemented logging of previous exceptions --- .../HumanReadableExceptionFormatter.php | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/Formatter/HumanReadableExceptionFormatter.php b/src/Formatter/HumanReadableExceptionFormatter.php index dcc02ad..0bb9974 100644 --- a/src/Formatter/HumanReadableExceptionFormatter.php +++ b/src/Formatter/HumanReadableExceptionFormatter.php @@ -2,6 +2,7 @@ namespace PolderKnowledge\LogModule\Formatter; +use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use WShafer\PSR11MonoLog\FactoryInterface; @@ -42,25 +43,43 @@ protected function printFromThrowable(array $record, \Throwable $throwable) $record['message'] ); - $result .= "[Context]\n"; - $result .= sprintf(" Type: %s\n", get_class($throwable)); - $result .= sprintf(" Code: %d\n", $throwable->getCode()); - $result .= sprintf(" File: %s\n", $throwable->getFile()); - $result .= sprintf(" Line: %d\n\n", $throwable->getLine()); + $exceptionCounter = 1; - $result .= "[Trace]\n"; - $result .= $this->buildTraceOutput($throwable->getTraceAsString()); - $result .= "\n\n"; + while ($throwable !== null) { + $result .= sprintf("[Exception #%d]\n", $exceptionCounter++); + $result .= sprintf(" Type: %s\n", get_class($throwable)); + $result .= sprintf(" Message: %s\n", $throwable->getMessage()); + $result .= sprintf(" Code: %d\n", $throwable->getCode()); + $result .= sprintf(" File: %s\n", $throwable->getFile()); + $result .= sprintf(" Line: %d\n\n", $throwable->getLine()); + + $result .= "[Trace]\n"; + $result .= $this->indentLines($throwable->getTraceAsString()); + $result .= "\n\n"; + + $throwable = $throwable->getPrevious(); + } + + foreach ($record['extra'] as $key => $params) { + if (is_array($params) || is_object($params)) { + $lines = json_encode($params, JSON_PRETTY_PRINT | JSON_FORCE_OBJECT); + } else { + $lines = $params; + } + + $result .= "[Extra - " . $key . "]\n"; + $result .= $this->indentLines($lines) . "\n\n"; + } return $result; } - private function buildTraceOutput($trace) + private function indentLines(string $input, int $spaces = 2) { - $lines = explode("\n", $trace); + $lines = explode("\n", $input); - $indented = array_map(function ($item) { - return ' ' . $item; + $indented = array_map(function ($item) use ($spaces) { + return str_repeat(' ', $spaces) . $item; }, $lines); return implode("\n", $indented); From 848555e505a2b379fd95d4252379ae47232947a5 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 6 Jun 2018 16:22:24 +0200 Subject: [PATCH 5/6] Normal PHP errors are also nicely formatted now --- .../HumanReadableExceptionFormatter.php | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/Formatter/HumanReadableExceptionFormatter.php b/src/Formatter/HumanReadableExceptionFormatter.php index 0bb9974..e654cd5 100644 --- a/src/Formatter/HumanReadableExceptionFormatter.php +++ b/src/Formatter/HumanReadableExceptionFormatter.php @@ -2,14 +2,13 @@ namespace PolderKnowledge\LogModule\Formatter; -use Monolog\Formatter\FormatterInterface; -use Monolog\Formatter\LineFormatter; +use Monolog\Formatter\NormalizerFormatter; use WShafer\PSR11MonoLog\FactoryInterface; /** * Format an Exception in a similar way PHP does by default when an exception bubbles to the top */ -class HumanReadableExceptionFormatter extends LineFormatter implements FactoryInterface +class HumanReadableExceptionFormatter extends NormalizerFormatter implements FactoryInterface { public function __invoke(array $options) { @@ -22,18 +21,9 @@ public function __invoke(array $options) public function format(array $record): string { - $exception = $record['context']['exception'] ?? null; + $throwable = $record['context']['exception'] ?? null; - if (!$exception) { - return parent::format($record); - } - - return $this->printFromThrowable($record, $exception); - } - - protected function printFromThrowable(array $record, \Throwable $throwable) - { - $record = $this->normalize($record); + $record = parent::format($record); $result = sprintf( "[%s] %s.%s: %s\n\n", From 087d0b4386da03d553ad4fe3651ad840670b0be4 Mon Sep 17 00:00:00 2001 From: Walter Tamboer Date: Wed, 6 Jun 2018 16:22:35 +0200 Subject: [PATCH 6/6] Added the context for php errors --- src/Formatter/HumanReadableExceptionFormatter.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Formatter/HumanReadableExceptionFormatter.php b/src/Formatter/HumanReadableExceptionFormatter.php index e654cd5..67ef48a 100644 --- a/src/Formatter/HumanReadableExceptionFormatter.php +++ b/src/Formatter/HumanReadableExceptionFormatter.php @@ -33,6 +33,21 @@ public function format(array $record): string $record['message'] ); + if (isset($record['context']['file'])) { + $result .= "[Context]\n\n"; + + if (isset($record['context']['message'])) { + $result .= sprintf(" Message: %s\n", $record['context']['message']); + } + + $result .= sprintf(" File: %s\n", $record['context']['file']); + $result .= sprintf(" Line: %d\n", $record['context']['line']); + + if (isset($record['context']['code'])) { + $result .= sprintf(" Code: %s\n\n", $record['context']['code']); + } + } + $exceptionCounter = 1; while ($throwable !== null) {