diff --git a/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php b/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php index 4325026..b5c8dea 100644 --- a/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php +++ b/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php @@ -184,8 +184,9 @@ public function all() foreach ($headings as $h) { for ($i = 0, $j = count($h); $i < $j; $i++) { foreach ($this->level->all() as $level) { - if (strpos(strtolower($h[$i]), '.' . $level) || strpos(strtolower($h[$i]), $level . ':')) { - + // Check if level appears in correct position (after context or right after timestamp) + $levelPattern = '/\]\s*(?:\w+\.)?' . preg_quote($level, '/') . ':/i'; + if (preg_match($levelPattern, $h[$i])) { preg_match($this->pattern->getPattern('current_log', 0) . $level . $this->pattern->getPattern('current_log', 1), $h[$i], $current); if (!isset($current[4])) { continue; diff --git a/tests/LaravelLogViewerTest.php b/tests/LaravelLogViewerTest.php index 3de7b4a..a379ed0 100644 --- a/tests/LaravelLogViewerTest.php +++ b/tests/LaravelLogViewerTest.php @@ -48,24 +48,24 @@ public function testSetFolderWithCorrectPath() public function testSetFolderWithArrayStoragePath() { $path = __DIR__; - + $laravel_log_viewer = new LaravelLogViewer(); $laravel_log_viewer->setStoragePath([$path]); if(!File::exists("$path/samuel")) File::makeDirectory("$path/samuel"); $laravel_log_viewer->setFolder('samuel'); - + $this->assertEquals("samuel", $laravel_log_viewer->getFolderName()); } public function testSetFolderWithDefaultStoragePath() { - + $laravel_log_viewer = new LaravelLogViewer(); $laravel_log_viewer->setStoragePath(storage_path()); $laravel_log_viewer->setFolder('logs'); - + $this->assertEquals("logs", $laravel_log_viewer->getFolderName()); } @@ -84,7 +84,7 @@ public function testPathToLogFile() $laravel_log_viewer = new LaravelLogViewer(); $pathToLogFile = $laravel_log_viewer->pathToLogFile(storage_path(('logs/laravel.log'))); - + $this->assertEquals($pathToLogFile, storage_path('logs/laravel.log')); } @@ -126,7 +126,7 @@ public function testAllWithEmptyFileName() { $laravel_log_viewer = new LaravelLogViewer(); $laravel_log_viewer->setStoragePath(__DIR__); - + $data = $laravel_log_viewer->all(); $this->assertEquals('local', $data[0]['context']); $this->assertEquals('error', $data[0]['level']); @@ -144,7 +144,7 @@ public function testFolderFiles() $this->assertIsArray($data); $this->assertNotEmpty($data); - + $this->assertStringContainsString('tests', $data[count(explode($data[0], '/')) - 1]); } @@ -153,7 +153,7 @@ public function testGetFolderFiles() $laravel_log_viewer = new LaravelLogViewer(); $laravel_log_viewer->setStoragePath(__DIR__); $data = $laravel_log_viewer->getFolderFiles(); - + $this->assertIsArray($data); $this->assertNotEmpty($data, "Folder files is null"); } @@ -163,7 +163,7 @@ public function testGetFiles() $laravel_log_viewer = new LaravelLogViewer(); $laravel_log_viewer->setStoragePath(storage_path()); $data = $laravel_log_viewer->getFiles(); - + $this->assertIsArray($data); $this->assertNotEmpty($data, "Folder files is null"); } @@ -173,7 +173,7 @@ public function testGetFolders() $laravel_log_viewer = new LaravelLogViewer(); $laravel_log_viewer->setStoragePath(storage_path()); $data = $laravel_log_viewer->getFolders(); - + $this->assertIsArray($data); $this->assertNotEmpty($data, "files is null"); } @@ -184,10 +184,60 @@ public function testDirectoryStructure() ob_start(); $log_viewer->directoryTreeStructure(storage_path('logs'), $log_viewer->foldersAndFiles()); $data = ob_get_clean(); - + $this->assertIsString($data); $this->assertNotEmpty($data); } + /** + * Test that level names appearing in log message text are not incorrectly + * parsed as separate log levels. This tests the fix for the bug where + * words like "processed" or "failed" in messages were creating false log entries. + */ + public function testLevelNamesInMessageTextNotParsedAsLevels() + { + // Create a temporary log file with entries containing level names in the message + $testLogPath = storage_path('logs/test-level-parsing.log'); + $testLogContent = <<<'LOG' +[2025-10-28 20:59:22] local.INFO: Redirect map successfully rebuilt and cached. Entries processed: 6866, Aliases mapped: 15918 +[2025-10-28 20:59:23] local.WARNING: Job processing failed with error code 500 +[2025-10-28 20:59:24] local.DEBUG: Processing diagnostic information +LOG; + + File::put($testLogPath, $testLogContent); + + try { + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setFile($testLogPath); + $data = $laravel_log_viewer->all(); + + // Should only have 3 log entries (not more due to false "processed" or "failed" matches) + $this->assertCount(3, $data, 'Should only parse 3 log entries, not create false entries from level names in message text'); + + // Verify the first entry is correctly parsed as INFO level, not "processed" + $this->assertEquals('info', $data[2]['level'], 'First entry should be INFO level'); + $this->assertEquals('local', $data[2]['context']); + $this->assertStringContainsString('Entries processed: 6866', $data[2]['text'], 'Message text should contain "processed" but not be parsed as a level'); + + // Verify the second entry is correctly parsed as WARNING level, not "failed" + $this->assertEquals('warning', $data[1]['level'], 'Second entry should be WARNING level'); + $this->assertEquals('local', $data[1]['context']); + $this->assertStringContainsString('Job processing failed', $data[1]['text'], 'Message text should contain "failed" but not be parsed as a level'); + + // Verify the third entry is correctly parsed as DEBUG level + $this->assertEquals('debug', $data[0]['level'], 'Third entry should be DEBUG level'); + + // Ensure no entries have "processed" or "failed" as their level + foreach ($data as $entry) { + $this->assertNotEquals('processed', $entry['level'], 'No entry should have "processed" as a level'); + $this->assertNotEquals('failed', $entry['level'], 'No entry should have "failed" as a level'); + } + } finally { + // Clean up the test log file + if (File::exists($testLogPath)) { + File::delete($testLogPath); + } + } + } }