Skip to content

Commit 4f49a0b

Browse files
authored
Merge pull request #159 from opcodesio/bug/new-logs-sometimes-overwrite-index-position-of-older-logs
fix a bug with new logs sometimes overriding index of older logs
2 parents 61f7cef + 7d0110e commit 4f49a0b

File tree

5 files changed

+86
-11
lines changed

5 files changed

+86
-11
lines changed

src/LogFile.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public function logs(): LogReader
5858

5959
public function size(): int
6060
{
61+
clearstatcache();
62+
6163
return filesize($this->path);
6264
}
6365

src/LogReader.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ public function scan(int $maxBytesToScan = null, bool $force = false): self
364364
if ($currentLog !== '' && preg_match($logMatchPattern, $currentLog) === 1) {
365365
if ((is_null($this->query) || preg_match($this->query, $currentLog))) {
366366
$logIndex->addToIndex($currentLogPosition, $currentTimestamp, $currentLogLevel, $currentIndex);
367+
$currentIndex++;
367368
}
368369
}
369370

tests/Pest.php

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use Carbon\Carbon;
34
use Illuminate\Support\Facades\File;
45
use Opcodes\LogViewer\LogFile;
56
use Opcodes\LogViewer\LogIndex;
@@ -18,30 +19,60 @@
1819

1920
/**
2021
* Generate log files with random data
21-
*
22-
* @param array <int, string> $files
23-
* @return void
2422
*/
25-
function generateLogFiles(array $files): void
23+
function generateLogFiles(array $files, string $content = null, bool $randomContent = false): array
2624
{
27-
foreach ($files as $file) {
28-
$file = storage_path('logs/'.$file);
25+
return array_map(
26+
fn ($file) => generateLogFile($file, $content, $randomContent),
27+
$files
28+
);
29+
}
2930

30-
if (File::exists($file)) {
31-
File::delete($file);
32-
}
31+
function generateLogFile(string $fileName = null, string $content = null, bool $randomContent = false): LogFile
32+
{
33+
if (is_null($fileName)) {
34+
$fileName = \Illuminate\Support\Str::random().'.log';
35+
}
3336

34-
File::put($file, str()->random());
37+
$path = storage_path('logs/'.$fileName);
3538

36-
test()->assertFileExists($file);
39+
if (File::exists($path)) {
40+
File::delete($path);
3741
}
42+
43+
File::put($path, $content ?? ($randomContent ? dummyLogData() : ''));
44+
45+
// we perform a regular PHP assertion, so it doesn't count towards the unit test assertion count.
46+
assert(file_exists($path));
47+
48+
return new LogFile($fileName, $path);
49+
}
50+
51+
function dummyLogData(int $lines = null): string
52+
{
53+
if (is_null($lines)) {
54+
$lines = rand(1, 10);
55+
}
56+
57+
return implode("\n", array_map(
58+
fn ($_) => makeLogEntry(),
59+
range(1, $lines)
60+
));
3861
}
3962

4063
function clearGeneratedLogFiles(): void
4164
{
4265
File::cleanDirectory(storage_path('logs'));
4366
}
4467

68+
function makeLogEntry(Carbon $date = null, string $level = 'debug', string $message = 'Testing log entry'): string
69+
{
70+
$dateFormatted = $date instanceof Carbon ? $date->toDateTimeString() : now()->toDateTimeString();
71+
$level = strtoupper($level);
72+
73+
return "[$dateFormatted] local.$level: $message";
74+
}
75+
4576
function createLogIndex($file = null, $query = null, array $predefinedLogs = []): LogIndex
4677
{
4778
if (is_null($file)) {

tests/Unit/LogReaderTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\File;
4+
use Opcodes\LogViewer\LogFile;
5+
6+
beforeEach(function () {
7+
$this->file = generateLogFile();
8+
File::append($this->file->path, makeLogEntry());
9+
});
10+
11+
afterEach(fn () => clearGeneratedLogFiles());
12+
13+
it('can scan a log file', function () {
14+
$logReader = $this->file->logs();
15+
expect($logReader->requiresScan())->toBeTrue();
16+
17+
$logReader->scan();
18+
19+
expect($logReader->requiresScan())->toBeFalse()
20+
->and($logReader->index()->total())->toBe(1);
21+
});
22+
23+
it('can re-scan the file after a new entry has been added', function () {
24+
$logReader = $this->file->logs();
25+
$logReader->scan();
26+
27+
\Spatie\TestTime\TestTime::addMinute();
28+
29+
File::append($this->file->path, PHP_EOL.makeLogEntry());
30+
31+
// re-instantiate the log reader to make sure we don't have anything cached
32+
$this->file = new LogFile($this->file->name, $this->file->path);
33+
$logReader = $this->file->logs();
34+
expect($logReader->requiresScan())->toBeTrue();
35+
36+
$logReader->scan();
37+
38+
expect($logReader->requiresScan())->toBeFalse()
39+
->and($logReader->index()->total())->toBe(2)
40+
->and($logReader->index()->getFlatIndex())->toHaveCount(2);
41+
});

0 commit comments

Comments
 (0)