diff --git a/src/Monolog/Formatter/JsonFormatter.php b/src/Monolog/Formatter/JsonFormatter.php index 10a62c19..28086e10 100644 --- a/src/Monolog/Formatter/JsonFormatter.php +++ b/src/Monolog/Formatter/JsonFormatter.php @@ -27,8 +27,6 @@ class JsonFormatter extends NormalizerFormatter protected $batchMode; protected $appendNewline; - protected $maxNormalizeDepth = 9; - protected $maxNormalizeItemCount = 1000; /** * @var bool @@ -61,32 +59,6 @@ class JsonFormatter extends NormalizerFormatter return $this->appendNewline; } - /** - * The maximum number of normalization levels to go through - */ - public function getMaxNormalizeDepth(): int - { - return $this->maxNormalizeDepth; - } - - public function setMaxNormalizeDepth(int $maxNormalizeDepth): void - { - $this->maxNormalizeDepth = $maxNormalizeDepth; - } - - /** - * The maximum number of items to normalize per level - */ - public function getMaxNormalizeItemCount(): int - { - return $this->maxNormalizeItemCount; - } - - public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): void - { - $this->maxNormalizeItemCount = $maxNormalizeItemCount; - } - /** * {@inheritdoc} */ diff --git a/src/Monolog/Formatter/NormalizerFormatter.php b/src/Monolog/Formatter/NormalizerFormatter.php index 857f9a0f..14d5e37e 100644 --- a/src/Monolog/Formatter/NormalizerFormatter.php +++ b/src/Monolog/Formatter/NormalizerFormatter.php @@ -24,6 +24,8 @@ class NormalizerFormatter implements FormatterInterface const SIMPLE_DATE = "Y-m-d\TH:i:sP"; protected $dateFormat; + protected $maxNormalizeDepth = 9; + protected $maxNormalizeItemCount = 1000; /** * @param string $dateFormat The format of the timestamp: one supported by DateTime::format @@ -56,14 +58,40 @@ class NormalizerFormatter implements FormatterInterface return $records; } + /** + * The maximum number of normalization levels to go through + */ + public function getMaxNormalizeDepth(): int + { + return $this->maxNormalizeDepth; + } + + public function setMaxNormalizeDepth(int $maxNormalizeDepth): void + { + $this->maxNormalizeDepth = $maxNormalizeDepth; + } + + /** + * The maximum number of items to normalize per level + */ + public function getMaxNormalizeItemCount(): int + { + return $this->maxNormalizeItemCount; + } + + public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): void + { + $this->maxNormalizeItemCount = $maxNormalizeItemCount; + } + /** * @param mixed $data * @return int|bool|string|null|array */ protected function normalize($data, int $depth = 0) { - if ($depth > 9) { - return 'Over 9 levels deep, aborting normalization'; + if ($depth > $this->maxNormalizeDepth) { + return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization'; } if (null === $data || is_scalar($data)) { @@ -84,8 +112,8 @@ class NormalizerFormatter implements FormatterInterface $count = 1; foreach ($data as $key => $value) { - if ($count++ > 1000) { - $normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization'; + if ($count++ > $this->maxNormalizeItemCount) { + $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items ('.count($data).' total), aborting normalization'; break; } diff --git a/tests/Monolog/Formatter/JsonFormatterTest.php b/tests/Monolog/Formatter/JsonFormatterTest.php index a8698343..eeb6b5bb 100644 --- a/tests/Monolog/Formatter/JsonFormatterTest.php +++ b/tests/Monolog/Formatter/JsonFormatterTest.php @@ -166,12 +166,12 @@ class JsonFormatterTest extends TestCase } /** - * @param JsonFormatter $formatter - * @param \Exception|\Throwable $exception + * @param JsonFormatter $formatter + * @param \Throwable $exception * * @return string */ - private function formatRecordWithExceptionInContext(JsonFormatter $formatter, $exception) + private function formatRecordWithExceptionInContext(JsonFormatter $formatter, \Throwable $exception) { $message = $formatter->format([ 'level_name' => 'CRITICAL', diff --git a/tests/Monolog/Formatter/NormalizerFormatterTest.php b/tests/Monolog/Formatter/NormalizerFormatterTest.php index 1275e254..b1878797 100644 --- a/tests/Monolog/Formatter/NormalizerFormatterTest.php +++ b/tests/Monolog/Formatter/NormalizerFormatterTest.php @@ -289,6 +289,48 @@ class NormalizerFormatterTest extends \PHPUnit\Framework\TestCase $this->assertSame('{"message":"€ŠšŽžŒœŸ"}', $res); } + public function testMaxNormalizeDepth() + { + $formatter = new NormalizerFormatter(); + $formatter->setMaxNormalizeDepth(1); + $throwable = new \Error('Foo'); + + $message = $this->formatRecordWithExceptionInContext($formatter, $throwable); + $this->assertEquals( + 'Over 1 levels deep, aborting normalization', + $message['context']['exception'] + ); + } + + public function testMaxNormalizeItemCountWith0ItemsMax() + { + $formatter = new NormalizerFormatter(); + $formatter->setMaxNormalizeDepth(9); + $formatter->setMaxNormalizeItemCount(0); + $throwable = new \Error('Foo'); + + $message = $this->formatRecordWithExceptionInContext($formatter, $throwable); + $this->assertEquals( + ["..." => "Over 0 items (6 total), aborting normalization"], + $message + ); + } + + public function testMaxNormalizeItemCountWith3ItemsMax() + { + $formatter = new NormalizerFormatter(); + $formatter->setMaxNormalizeDepth(9); + $formatter->setMaxNormalizeItemCount(2); + $throwable = new \Error('Foo'); + + $message = $this->formatRecordWithExceptionInContext($formatter, $throwable); + + $this->assertEquals( + ["level_name" => "CRITICAL", "channel" => "core", "..." => "Over 2 items (6 total), aborting normalization"], + $message + ); + } + /** * @param mixed $in Input * @param mixed $expect Expected output @@ -387,6 +429,26 @@ class NormalizerFormatterTest extends \PHPUnit\Framework\TestCase $result['context']['exception']['trace'][0] ); } + + /** + * @param NormalizerFormatter $formatter + * @param \Throwable $exception + * + * @return string + */ + private function formatRecordWithExceptionInContext(NormalizerFormatter $formatter, \Throwable $exception) + { + $message = $formatter->format([ + 'level_name' => 'CRITICAL', + 'channel' => 'core', + 'context' => ['exception' => $exception], + 'datetime' => null, + 'extra' => [], + 'message' => 'foobar', + ]); + + return $message; + } } class TestFooNorm