From c709906d0a41790b000625ce70b0c6430add266d Mon Sep 17 00:00:00 2001 From: Lito Date: Mon, 9 May 2022 22:37:14 +0200 Subject: [PATCH] [2.X] Allow stacktraces parser on LineFormatter (#1665) * Allow stacktraces parser on LineFormatter * Added includeStacktraces parse tests --- src/Monolog/Formatter/LineFormatter.php | 23 ++++++- tests/Monolog/Formatter/LineFormatterTest.php | 67 +++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/Monolog/Formatter/LineFormatter.php b/src/Monolog/Formatter/LineFormatter.php index a855c525..d0b4de94 100644 --- a/src/Monolog/Formatter/LineFormatter.php +++ b/src/Monolog/Formatter/LineFormatter.php @@ -33,6 +33,8 @@ class LineFormatter extends NormalizerFormatter protected $ignoreEmptyContextAndExtra; /** @var bool */ protected $includeStacktraces; + /** @var ?callable */ + protected $stacktracesParser; /** * @param string|null $format The format of the message @@ -49,11 +51,12 @@ class LineFormatter extends NormalizerFormatter parent::__construct($dateFormat); } - public function includeStacktraces(bool $include = true): self + public function includeStacktraces(bool $include = true, ?callable $parser = null): self { $this->includeStacktraces = $include; if ($this->includeStacktraces) { $this->allowInlineLineBreaks = true; + $this->stacktracesParser = $parser; } return $this; @@ -209,9 +212,25 @@ class LineFormatter extends NormalizerFormatter $str .= '): ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . ')'; if ($this->includeStacktraces) { - $str .= "\n[stacktrace]\n" . $e->getTraceAsString() . "\n"; + $str .= $this->stacktracesParser($e); } return $str; } + + private function stacktracesParser(\Throwable $e): string + { + $trace = $e->getTraceAsString(); + + if ($this->stacktracesParser) { + $trace = $this->stacktracesParserCustom($trace); + } + + return "\n[stacktrace]\n" . $trace . "\n"; + } + + private function stacktracesParserCustom(string $trace): string + { + return implode("\n", array_filter(array_map($this->stacktracesParser, explode("\n", $trace)))); + } } diff --git a/tests/Monolog/Formatter/LineFormatterTest.php b/tests/Monolog/Formatter/LineFormatterTest.php index 86d22d38..d4d7c658 100644 --- a/tests/Monolog/Formatter/LineFormatterTest.php +++ b/tests/Monolog/Formatter/LineFormatterTest.php @@ -155,6 +155,73 @@ class LineFormatterTest extends \PHPUnit\Framework\TestCase $this->assertRegexp('{^\['.date('Y-m-d').'] core\.CRITICAL: foobar \{"exception":"\[object] \(RuntimeException\(code: 0\): Foo at '.preg_quote(substr($path, 1, -1)).':'.(__LINE__ - 8).'\)\n\[stacktrace]\n#0}', $message); } + public function testDefFormatWithExceptionAndStacktraceParserFull() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $formatter->includeStacktraces(true, function ($line) { + return $line; + }); + + $message = $formatter->format([ + 'level_name' => 'CRITICAL', + 'channel' => 'core', + 'context' => ['exception' => new \RuntimeException('Foo')], + 'datetime' => new \DateTimeImmutable, + 'extra' => [], + 'message' => 'foobar', + ]); + + $trace = explode('[stacktrace]', $message, 2)[1]; + + $this->assertStringContainsString('TestCase.php', $trace); + $this->assertStringContainsString('TestResult.php', $trace); + } + + public function testDefFormatWithExceptionAndStacktraceParserCustom() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $formatter->includeStacktraces(true, function ($line) { + if (strpos($line, 'TestCase.php') === false) { + return $line; + } + }); + + $message = $formatter->format([ + 'level_name' => 'CRITICAL', + 'channel' => 'core', + 'context' => ['exception' => new \RuntimeException('Foo')], + 'datetime' => new \DateTimeImmutable, + 'extra' => [], + 'message' => 'foobar', + ]); + + $trace = explode('[stacktrace]', $message, 2)[1]; + + $this->assertStringNotContainsString('TestCase.php', $trace); + $this->assertStringContainsString('TestResult.php', $trace); + } + + public function testDefFormatWithExceptionAndStacktraceParserEmpty() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $formatter->includeStacktraces(true, function ($line) { + return null; + }); + + $message = $formatter->format([ + 'level_name' => 'CRITICAL', + 'channel' => 'core', + 'context' => ['exception' => new \RuntimeException('Foo')], + 'datetime' => new \DateTimeImmutable, + 'extra' => [], + 'message' => 'foobar', + ]); + + $trace = explode('[stacktrace]', $message, 2)[1]; + + $this->assertStringNotContainsString('#', $trace); + } + public function testDefFormatWithPreviousException() { $formatter = new LineFormatter(null, 'Y-m-d');