diff --git a/src/Monolog/Formatter/HtmlFormatter.php b/src/Monolog/Formatter/HtmlFormatter.php index a343b065..26f74fa9 100644 --- a/src/Monolog/Formatter/HtmlFormatter.php +++ b/src/Monolog/Formatter/HtmlFormatter.php @@ -59,7 +59,7 @@ class HtmlFormatter extends NormalizerFormatter $td = '
'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'
'; } - return "\n$th:\n".$td."\n"; + return "\n$th:\n".$td."\n"; } /** diff --git a/src/Monolog/Formatter/JsonFormatter.php b/src/Monolog/Formatter/JsonFormatter.php index 1fcfd579..10a62c19 100644 --- a/src/Monolog/Formatter/JsonFormatter.php +++ b/src/Monolog/Formatter/JsonFormatter.php @@ -159,10 +159,11 @@ class JsonFormatter extends NormalizerFormatter $count = 1; foreach ($data as $key => $value) { - if ($count++ >= $this->maxNormalizeItemCount) { - $normalized['...'] = 'Over '.$this->maxNormalizeItemCount.' items, aborting normalization'; + if ($count++ > $this->maxNormalizeItemCount) { + $normalized['...'] = 'Over '.$this->maxNormalizeItemCount.' items ('.count($data).' total), aborting normalization'; break; } + $normalized[$key] = $this->normalize($value, $depth + 1); } diff --git a/src/Monolog/Formatter/NormalizerFormatter.php b/src/Monolog/Formatter/NormalizerFormatter.php index 84f644c6..857f9a0f 100644 --- a/src/Monolog/Formatter/NormalizerFormatter.php +++ b/src/Monolog/Formatter/NormalizerFormatter.php @@ -84,10 +84,11 @@ class NormalizerFormatter implements FormatterInterface $count = 1; foreach ($data as $key => $value) { - if ($count++ >= 1000) { + if ($count++ > 1000) { $normalized['...'] = 'Over 1000 items ('.count($data).' total), aborting normalization'; break; } + $normalized[$key] = $this->normalize($value, $depth + 1); } diff --git a/src/Monolog/Handler/RotatingFileHandler.php b/src/Monolog/Handler/RotatingFileHandler.php index 78da690e..55160d9a 100644 --- a/src/Monolog/Handler/RotatingFileHandler.php +++ b/src/Monolog/Handler/RotatingFileHandler.php @@ -166,7 +166,7 @@ class RotatingFileHandler extends StreamHandler $fileInfo = pathinfo($this->filename); $glob = str_replace( ['{filename}', '{date}'], - [$fileInfo['filename'], '*'], + [$fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'], $fileInfo['dirname'] . '/' . $this->filenameFormat ); if (!empty($fileInfo['extension'])) { diff --git a/tests/Monolog/Formatter/JsonFormatterTest.php b/tests/Monolog/Formatter/JsonFormatterTest.php index 699c27a3..a8698343 100644 --- a/tests/Monolog/Formatter/JsonFormatterTest.php +++ b/tests/Monolog/Formatter/JsonFormatterTest.php @@ -131,22 +131,22 @@ class JsonFormatterTest extends TestCase $message = $this->formatRecordWithExceptionInContext($formatter, $throwable); $this->assertEquals( - '{"...":"Over 0 items, aborting normalization"}'."\n", + '{"...":"Over 0 items (6 total), aborting normalization"}'."\n", $message ); } - public function testMaxNormalizeItemCountWith3ItemsMax() + public function testMaxNormalizeItemCountWith2ItemsMax() { $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, true); $formatter->setMaxNormalizeDepth(9); - $formatter->setMaxNormalizeItemCount(3); + $formatter->setMaxNormalizeItemCount(2); $throwable = new \Error('Foo'); $message = $this->formatRecordWithExceptionInContext($formatter, $throwable); $this->assertEquals( - '{"level_name":"CRITICAL","channel":"core","...":"Over 3 items, aborting normalization"}'."\n", + '{"level_name":"CRITICAL","channel":"core","...":"Over 2 items (6 total), aborting normalization"}'."\n", $message ); } @@ -217,4 +217,40 @@ class JsonFormatterTest extends TestCase return $formattedException; } + + public function testNormalizeHandleLargeArraysWithExactly1000Items() + { + $formatter = new NormalizerFormatter(); + $largeArray = range(1, 1000); + + $res = $formatter->format(array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array($largeArray), + 'datetime' => new \DateTime, + 'extra' => array(), + )); + + $this->assertCount(1000, $res['context'][0]); + $this->assertArrayNotHasKey('...', $res['context'][0]); + } + + public function testNormalizeHandleLargeArrays() + { + $formatter = new NormalizerFormatter(); + $largeArray = range(1, 2000); + + $res = $formatter->format(array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array($largeArray), + 'datetime' => new \DateTime, + 'extra' => array(), + )); + + $this->assertCount(1001, $res['context'][0]); + $this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']); + } } diff --git a/tests/Monolog/Formatter/NormalizerFormatterTest.php b/tests/Monolog/Formatter/NormalizerFormatterTest.php index 52a8c796..1275e254 100644 --- a/tests/Monolog/Formatter/NormalizerFormatterTest.php +++ b/tests/Monolog/Formatter/NormalizerFormatterTest.php @@ -227,6 +227,24 @@ class NormalizerFormatterTest extends \PHPUnit\Framework\TestCase $this->assertEquals(@json_encode([$resource]), $res); } + public function testNormalizeHandleLargeArraysWithExactly1000Items() + { + $formatter = new NormalizerFormatter(); + $largeArray = range(1, 1000); + + $res = $formatter->format(array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array($largeArray), + 'datetime' => new \DateTime, + 'extra' => array(), + )); + + $this->assertCount(1000, $res['context'][0]); + $this->assertArrayNotHasKey('...', $res['context'][0]); + } + public function testNormalizeHandleLargeArrays() { $formatter = new NormalizerFormatter(); @@ -241,7 +259,7 @@ class NormalizerFormatterTest extends \PHPUnit\Framework\TestCase 'extra' => array(), )); - $this->assertCount(1000, $res['context'][0]); + $this->assertCount(1001, $res['context'][0]); $this->assertEquals('Over 1000 items (2000 total), aborting normalization', $res['context'][0]['...']); } diff --git a/tests/Monolog/Handler/RotatingFileHandlerTest.php b/tests/Monolog/Handler/RotatingFileHandlerTest.php index 5fc4416a..58932cd1 100644 --- a/tests/Monolog/Handler/RotatingFileHandlerTest.php +++ b/tests/Monolog/Handler/RotatingFileHandlerTest.php @@ -195,6 +195,40 @@ class RotatingFileHandlerTest extends TestCase ]; } + /** + * @dataProvider rotationWhenSimilarFilesExistTests + */ + public function testRotationWhenSimilarFileNamesExist($dateFormat) + { + touch($old1 = __DIR__.'/Fixtures/foo-foo-'.date($dateFormat).'.rot'); + touch($old2 = __DIR__.'/Fixtures/foo-bar-'.date($dateFormat).'.rot'); + + $log = __DIR__.'/Fixtures/foo-'.date($dateFormat).'.rot'; + + $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->setFilenameFormat('{filename}-{date}', $dateFormat); + $handler->handle($this->getRecord()); + $handler->close(); + + $this->assertTrue(file_exists($log)); + } + + public function rotationWhenSimilarFilesExistTests() + { + + return [ + 'Rotation is triggered when the file of the current day is not present but similar exists' + => [RotatingFileHandler::FILE_PER_DAY], + + 'Rotation is triggered when the file of the current month is not present but similar exists' + => [RotatingFileHandler::FILE_PER_MONTH], + + 'Rotation is triggered when the file of the current year is not present but similar exists' + => [RotatingFileHandler::FILE_PER_YEAR], + ]; + } + public function testReuseCurrentFile() { $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';