|
1 | 1 | <?php |
2 | 2 |
|
| 3 | +use Opcodes\LogViewer\LogLevels\LaravelLogLevel; |
3 | 4 | use Opcodes\LogViewer\Logs\LaravelLog; |
4 | 5 | use Opcodes\LogViewer\Utils\Utils; |
5 | 6 |
|
| 7 | +use function PHPUnit\Framework\assertEquals; |
| 8 | + |
| 9 | +it('can understand the default Laravel log format', function () { |
| 10 | + $text = '[2022-08-25 11:16:17] local.DEBUG: Example log entry for the level debug'; |
| 11 | + |
| 12 | + $log = new LaravelLog($text, $fileIdentifier = 'laravel.log', $filePosition = 5200, $index = 10); |
| 13 | + |
| 14 | + assertEquals($index, $log->index); |
| 15 | + assertEquals(LaravelLogLevel::Debug, $log->level); |
| 16 | + assertEquals('local', $log->extra['environment']); |
| 17 | + assertEquals('2022-08-25 11:16:17', $log->datetime->toDateTimeString()); |
| 18 | + assertEquals('Example log entry for the level debug', $log->message); |
| 19 | + assertEquals('Example log entry for the level debug', $log->getOriginalText()); |
| 20 | + assertEquals($fileIdentifier, $log->fileIdentifier); |
| 21 | + assertEquals($filePosition, $log->filePosition); |
| 22 | +}); |
| 23 | + |
| 24 | +it('can understand multi-line logs', function () { |
| 25 | + $logText = <<<'EOF' |
| 26 | +Example log entry for the level debug |
| 27 | +with multiple lines of content. |
| 28 | +can contain dumped objects or JSON as well - it's all part of the contents. |
| 29 | +EOF; |
| 30 | + $text = '[2022-08-25 11:16:17] local.DEBUG: '.$logText; |
| 31 | + |
| 32 | + $log = new LaravelLog($text, 'laravel.log', 0, 0); |
| 33 | + |
| 34 | + assertEquals('Example log entry for the level debug', $log->message); |
| 35 | + assertEquals($logText, $log->getOriginalText()); |
| 36 | +}); |
| 37 | + |
| 38 | +it('extracts JSON from the log text', function () { |
| 39 | + config(['log-viewer.strip_extracted_context' => true]); |
| 40 | + $logText = <<<'EOF' |
| 41 | +Example log entry for the level debug |
| 42 | +with multiple lines of content. |
| 43 | + {"one":1,"two":"two","three":[1,2,3]} |
| 44 | +can contain dumped objects or JSON as well - it's all part of the contents. |
| 45 | +EOF; |
| 46 | + $jsonString = '{"one":1,"two":"two","three":[1,2,3]}'; |
| 47 | + $text = '[2022-08-25 11:16:17] local.DEBUG: '.$logText; |
| 48 | + |
| 49 | + $log = new LaravelLog($text, 'laravel.log', 0, 0); |
| 50 | + |
| 51 | + assertEquals('Example log entry for the level debug', $log->message); |
| 52 | + assertEquals(rtrim(str_replace($jsonString, '', $logText)), $log->getOriginalText()); |
| 53 | + assertEquals(json_decode($jsonString, true), $log->context); |
| 54 | +}); |
| 55 | + |
| 56 | +it('extracts JSON, but does not remove from the log text if the config is set to false', function () { |
| 57 | + config(['log-viewer.strip_extracted_context' => false]); |
| 58 | + $logText = <<<'EOF' |
| 59 | +Example log entry for the level debug |
| 60 | +with multiple lines of content. |
| 61 | + {"one":1,"two":"two","three":[1,2,3]} |
| 62 | +can contain dumped objects or JSON as well - it's all part of the contents. |
| 63 | +EOF; |
| 64 | + $text = '[2022-08-25 11:16:17] local.DEBUG: '.$logText; |
| 65 | + |
| 66 | + $log = new LaravelLog($text, 'laravel.log'); |
| 67 | + |
| 68 | + assertEquals('Example log entry for the level debug', $log->message); |
| 69 | + assertEquals($logText, $log->getOriginalText()); |
| 70 | + assertEquals(json_decode('{"one":1,"two":"two","three":[1,2,3]}', true), $log->context); |
| 71 | +}); |
| 72 | + |
| 73 | +it('extracts JSON from a complex log', function () { |
| 74 | + config(['log-viewer.strip_extracted_context' => true]); |
| 75 | + $logText = <<<'EOF' |
| 76 | +Initiating facebook login. |
| 77 | +[HTTP request] |
| 78 | +*User ID:* guest |
| 79 | +*Request:* GET https://system.test/book/arunas/submit-facebook |
| 80 | +*Agent:* Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/19G82 [FBAN/FBIOS;FBDV/iPhone9,3;FBMD/iPhone;FBSN/iOS;FBSV/15.6.1;FBSS/2;FBID/phone;FBLC/da_DK;FBOP/5] |
| 81 | + {"permalink":"arunas","session":{"_token":"BpqyiNyinnLamzer4jqzrh9NTyC6emFR41FitMpv","_previous":{"url":"https://system.test/book/arunas/center"},"_flash":{"old":[],"new":[]},"latest_permalink":"arunas"},"ip":"127.0.0.1","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/19G82 [FBAN/FBIOS;FBDV/iPhone9,3;FBMD/iPhone;FBSN/iOS;FBSV/15.6.1;FBSS/2;FBID/phone;FBLC/da_DK;FBOP/5]"} |
| 82 | +EOF; |
| 83 | + |
| 84 | + $jsonString = '{"permalink":"arunas","session":{"_token":"BpqyiNyinnLamzer4jqzrh9NTyC6emFR41FitMpv","_previous":{"url":"https://system.test/book/arunas/center"},"_flash":{"old":[],"new":[]},"latest_permalink":"arunas"},"ip":"127.0.0.1","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/19G82 [FBAN/FBIOS;FBDV/iPhone9,3;FBMD/iPhone;FBSN/iOS;FBSV/15.6.1;FBSS/2;FBID/phone;FBLC/da_DK;FBOP/5]"}'; |
| 85 | + $text = '[2022-08-25 11:16:17] local.DEBUG: '.$logText; |
| 86 | + |
| 87 | + $log = new LaravelLog($text, 'laravel.log'); |
| 88 | + |
| 89 | + assertEquals('arunas', $log->context['permalink'] ?? null); |
| 90 | + assertEquals('Initiating facebook login.', $log->message); |
| 91 | + assertEquals(rtrim(str_replace($jsonString, '', $logText)), $log->getOriginalText()); |
| 92 | + assertEquals(json_decode($jsonString, true), $log->context); |
| 93 | +}); |
| 94 | + |
| 95 | +it('can understand the optional microseconds in the timestamp', function () { |
| 96 | + $text = '[2022-08-25 11:16:17.125000] local.DEBUG: Example log entry for the level debug'; |
| 97 | + |
| 98 | + $log = new LaravelLog($text, 'laravel.log', 0, 0); |
| 99 | + |
| 100 | + assertEquals(125000, $log->datetime->micro); |
| 101 | +}); |
| 102 | + |
| 103 | +it('can understand the optional time offset in the timestamp', function () { |
| 104 | + $text = '[2022-08-25 11:16:17.125000+02:00] local.DEBUG: Example log entry for the level debug'; |
| 105 | + $expectedTimestamp = 1661418977; |
| 106 | + |
| 107 | + $log = new LaravelLog($text, 'laravel.log', 0, 0); |
| 108 | + |
| 109 | + assertEquals($expectedTimestamp, $log->datetime->timestamp); |
| 110 | + |
| 111 | + // Meanwhile, if we switch the time offset an hour forward, |
| 112 | + // we can expect the timestamp to be reduced by 3600 seconds. |
| 113 | + $text = '[2022-08-25 11:16:17.125000+03:00] local.DEBUG: Example log entry for the level debug'; |
| 114 | + $newExpectedTimestamp = $expectedTimestamp - 3600; |
| 115 | + |
| 116 | + $log = new LaravelLog($text, 'laravel.log', 0, 0); |
| 117 | + |
| 118 | + assertEquals($newExpectedTimestamp, $log->datetime->timestamp); |
| 119 | +}); |
| 120 | + |
| 121 | +it('can handle text in-between timestamp and environment/severity', function () { |
| 122 | + $text = '[2022-08-25 11:16:17] some additional text [!@#$%^&] and characters // !@#$ local.DEBUG: Example log entry for the level debug'; |
| 123 | + $expectedAdditionalText = 'some additional text [!@#$%^&] and characters // !@#$'; |
| 124 | + |
| 125 | + $log = new LaravelLog($text, 'laravel.log', 0, 0); |
| 126 | + |
| 127 | + assertEquals($expectedAdditionalText.' Example log entry for the level debug', $log->message); |
| 128 | + assertEquals($expectedAdditionalText.' Example log entry for the level debug', $log->getOriginalText()); |
| 129 | + // got to make sure the rest of the data is still processed correctly! |
| 130 | + assertEquals('local', $log->extra['environment']); |
| 131 | + assertEquals(LaravelLogLevel::Debug, $log->level); |
| 132 | +}); |
| 133 | + |
| 134 | +it('finds the correct log level', function ($levelProvided, $levelExpected) { |
| 135 | + $text = "[2022-08-25 11:16:17] local.$levelProvided: Example log entry for the level debug"; |
| 136 | + |
| 137 | + $log = new LaravelLog($text, 'laravel.log', 0, 0); |
| 138 | + |
| 139 | + assertEquals($levelExpected, $log->level); |
| 140 | +})->with([ |
| 141 | + ['INFO', LaravelLogLevel::Info], |
| 142 | + ['DEBUG', LaravelLogLevel::Debug], |
| 143 | + ['ERROR', LaravelLogLevel::Error], |
| 144 | + ['WARNING', LaravelLogLevel::Warning], |
| 145 | + ['CRITICAL', LaravelLogLevel::Critical], |
| 146 | + ['ALERT', LaravelLogLevel::Alert], |
| 147 | + ['EMERGENCY', LaravelLogLevel::Emergency], |
| 148 | + ['info', LaravelLogLevel::Info], |
| 149 | + ['iNfO', LaravelLogLevel::Info], |
| 150 | + ['', LaravelLogLevel::None], |
| 151 | +]); |
| 152 | + |
| 153 | +it('handles missing message', function () { |
| 154 | + $text = '[2022-11-07 17:51:33] production.ERROR: '; |
| 155 | + |
| 156 | + $log = new LaravelLog($text, 'laravel.log', 0, 0); |
| 157 | + |
| 158 | + assertEquals('2022-11-07 17:51:33', $log->datetime?->toDateTimeString()); |
| 159 | + assertEquals(LaravelLogLevel::Error, $log->level); |
| 160 | + assertEquals('production', $log->extra['environment']); |
| 161 | + assertEquals('', $log->getOriginalText()); |
| 162 | +}); |
| 163 | + |
| 164 | +it('strips extracted context when there\'s multiple contexts available', function () { |
| 165 | + config(['log-viewer.strip_extracted_context' => true]); |
| 166 | + $logText = <<<'EOF' |
| 167 | +[2023-08-16 14:00:25] testing.INFO: Test message. ["one","two"] {"memory_usage":"78 MB","process_id":1234} |
| 168 | +EOF; |
| 169 | + |
| 170 | + $log = new LaravelLog($logText); |
| 171 | + |
| 172 | + assertEquals('Test message.', $log->message); |
| 173 | + assertEquals(2, count($log->context)); |
| 174 | + assertEquals(['one', 'two'], $log->context[0]); |
| 175 | + assertEquals(['memory_usage' => '78 MB', 'process_id' => 1234], $log->context[1]); |
| 176 | +}); |
| 177 | + |
| 178 | +it('correctly handles objects with number keys', function () { |
| 179 | + $logText = <<<'EOF' |
| 180 | +[2024-03-13 12:57:30] local.DEBUG: This is a log message {"array":{"10":"value1","20":"value2"}} |
| 181 | +EOF; |
| 182 | + |
| 183 | + $log = new LaravelLog($logText); |
| 184 | + |
| 185 | + assertEquals('This is a log message', $log->message); |
| 186 | + assertEquals(['array' => ['10' => 'value1', '20' => 'value2']], $log->context); |
| 187 | +}); |
| 188 | + |
6 | 189 | it('can extract mail preview from a log', function () { |
7 | 190 | $messageString = <<<'EOF' |
8 | 191 | [2023-08-24 15:51:14] local.DEBUG: From: sender@example.com |
|
0 commit comments