Skip to content

Commit 285cbcc

Browse files
committed
refactoring LogIndex class into smaller parts, hiding unnecessary public methods.
1 parent aaf36d3 commit 285cbcc

23 files changed

+457
-315
lines changed

config/log-viewer.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@
127127
],
128128
],
129129

130+
/*
131+
|--------------------------------------------------------------------------
132+
| Chunk size when scanning log files lazily
133+
|--------------------------------------------------------------------------
134+
| The size in MB of files to scan before updating the progress bar when searching across all files.
135+
|
136+
*/
137+
'cache_driver' => env('LOG_VIEWER_CACHE_DRIVER', null),
138+
130139
/*
131140
|--------------------------------------------------------------------------
132141
| Chunk size when scanning log files lazily

resources/views/livewire/log-list.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class="table-fixed min-w-full max-w-full border-separate"
9999
@if(!empty($query) && isset($file))
100100
<button class="px-3 ml-3 py-2 border dark:border-gray-700 text-gray-800 dark:text-gray-200 hover:border-emerald-600 dark:hover:border-emerald-700 rounded-md" x-on:click.prevent="selectFile(null)">Search all files</button>
101101
@endif
102-
@if(isset($levels) && count(array_filter($levels, fn ($level) => $level->selected)) === 0 && count(array_filter($levels, fn ($level) => $level->count > 0)))
102+
@if(isset($levels) && count(array_filter($levels, fn ($level) => $level->count > 0 && $level->selected)) === 0 && count(array_filter($levels, fn ($level) => $level->count > 0)) > 0)
103103
<button class="px-3 ml-3 py-2 border dark:border-gray-700 text-gray-800 dark:text-gray-200 hover:border-emerald-600 dark:hover:border-emerald-700 rounded-md" wire:click="selectAllLevels">Select all severities</button>
104104
@endif
105105
</div>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
namespace Opcodes\LogViewer\Concerns\LogIndex;
4+
5+
use Carbon\CarbonInterface;
6+
use Illuminate\Contracts\Cache\Repository;
7+
use Illuminate\Support\Facades\Cache;
8+
use Opcodes\LogViewer\LogIndexChunk;
9+
use Opcodes\LogViewer\Utils\GenerateCacheKey;
10+
11+
trait CanCacheIndex
12+
{
13+
public function clearCache(): void
14+
{
15+
$this->clearChunksFromCache();
16+
17+
$this->cache()->forget($this->metaCacheKey());
18+
$this->cache()->forget($this->cacheKey());
19+
20+
// this will reset all properties to default, because it won't find any cached settings for this index
21+
$this->loadMetadata();
22+
}
23+
24+
protected function saveMetadataToCache(): void
25+
{
26+
$this->cache()->put($this->metaCacheKey(), $this->getMetadata(), $this->cacheTtl());
27+
}
28+
29+
protected function getMetadataFromCache(): array
30+
{
31+
return $this->cache()->get($this->metaCacheKey(), []);
32+
}
33+
34+
protected function saveChunkToCache(LogIndexChunk $chunk): void
35+
{
36+
$this->cache()->put(
37+
$this->chunkCacheKey($chunk->index),
38+
$chunk->data,
39+
$this->cacheTtl()
40+
);
41+
}
42+
43+
protected function getChunkDataFromCache(int $index, $default = null): ?array
44+
{
45+
return $this->cache()->get($this->chunkCacheKey($index), $default);
46+
}
47+
48+
protected function clearChunksFromCache(): void
49+
{
50+
foreach ($this->getChunkDefinitions() as $chunkDefinition) {
51+
$this->cache()->forget($this->chunkCacheKey($chunkDefinition['index']));
52+
}
53+
}
54+
55+
protected function cacheKey(): string
56+
{
57+
return GenerateCacheKey::for($this);
58+
}
59+
60+
protected function metaCacheKey(): string
61+
{
62+
return GenerateCacheKey::for($this, 'metadata');
63+
}
64+
65+
protected function chunkCacheKey(int $index): string
66+
{
67+
return GenerateCacheKey::for($this, "chunk:$index");
68+
}
69+
70+
protected function cache(): Repository
71+
{
72+
return app('log-viewer-cache');
73+
}
74+
75+
protected function cacheTtl(): CarbonInterface
76+
{
77+
if (! empty($this->query)) {
78+
// There will be a lot more search queries, and they're usually just one-off searches.
79+
// We don't want these to take up too much of Redis/File-cache space for too long.
80+
return now()->addDay();
81+
}
82+
83+
return now()->addWeek();
84+
}
85+
}

src/Concerns/CanFilterIndex.php renamed to src/Concerns/LogIndex/CanFilterIndex.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Opcodes\LogViewer\Concerns;
3+
namespace Opcodes\LogViewer\Concerns\LogIndex;
44

55
use Carbon\CarbonInterface;
66
use Opcodes\LogViewer\Level;

src/Concerns/CanIterateIndex.php renamed to src/Concerns/LogIndex/CanIterateIndex.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Opcodes\LogViewer\Concerns;
3+
namespace Opcodes\LogViewer\Concerns\LogIndex;
44

55
use ArrayIterator;
66
use Opcodes\LogViewer\Direction;

src/Concerns/SplitsIndexIntoChunks.php renamed to src/Concerns/LogIndex/CanSplitIndexIntoChunks.php

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<?php
22

3-
namespace Opcodes\LogViewer\Concerns;
3+
namespace Opcodes\LogViewer\Concerns\LogIndex;
44

55
use Illuminate\Support\Facades\Cache;
66
use Opcodes\LogViewer\Exceptions\InvalidChunkSizeException;
77
use Opcodes\LogViewer\LogIndexChunk;
8+
use Opcodes\LogViewer\Utils\GenerateCacheKey;
89

9-
trait SplitsIndexIntoChunks
10+
trait CanSplitIndexIntoChunks
1011
{
1112
protected int $maxChunkSize;
1213

@@ -39,7 +40,7 @@ public function getCurrentChunk(): LogIndexChunk
3940
$this->currentChunk = LogIndexChunk::fromDefinitionArray($this->currentChunkDefinition);
4041

4142
if ($this->currentChunk->size > 0) {
42-
$this->currentChunk->data = Cache::get($this->chunkCacheKey($this->currentChunk->index), []);
43+
$this->currentChunk->data = $this->getChunkDataFromCache($this->currentChunk->index, []);
4344
}
4445
}
4546

@@ -64,28 +65,40 @@ public function getChunkCount(): int
6465
return count($this->getChunkDefinitions());
6566
}
6667

67-
public function chunkCacheKey(int $index): string
68-
{
69-
return $this->cacheKey().':'.$index;
70-
}
71-
7268
public function getChunkData(int $index): ?array
7369
{
7470
$currentChunk = $this->getCurrentChunk();
7571

7672
if ($index === $currentChunk?->index) {
7773
$chunkData = $currentChunk->data ?? [];
7874
} else {
79-
$chunkData = Cache::get($this->chunkCacheKey($index));
75+
$chunkData = $this->getChunkDataFromCache($index);
8076
}
8177

8278
return $chunkData;
8379
}
8480

85-
protected function clearChunksFromCache(): void
81+
protected function rotateCurrentChunk(): void
82+
{
83+
$this->saveChunkToCache($this->currentChunk);
84+
85+
$this->chunkDefinitions[] = $this->currentChunk->toArray();
86+
87+
$this->currentChunk = new LogIndexChunk([], $this->currentChunk->index + 1, 0);
88+
89+
$this->saveMetadata();
90+
}
91+
92+
protected function getRelevantItemsInChunk(array $chunkDefinition): int
8693
{
87-
foreach ($this->getChunkDefinitions() as $chunkDefinition) {
88-
Cache::forget($this->chunkCacheKey($chunkDefinition['index']));
94+
$relevantItemsInChunk = 0;
95+
96+
foreach ($chunkDefinition['level_counts'] as $level => $count) {
97+
if (! isset($this->filterLevels) || in_array($level, $this->filterLevels)) {
98+
$relevantItemsInChunk += $count;
99+
}
89100
}
101+
102+
return $relevantItemsInChunk;
90103
}
91104
}

src/Concerns/LogIndex/HasMetadata.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Opcodes\LogViewer\Concerns\LogIndex;
4+
5+
use Illuminate\Support\Facades\Cache;
6+
7+
trait HasMetadata
8+
{
9+
public function getMetadata(): array
10+
{
11+
return [
12+
'query' => $this->getQuery(),
13+
'identifier' => $this->identifier,
14+
'last_scanned_file_position' => $this->lastScannedFilePosition,
15+
'last_scanned_index' => $this->lastScannedIndex,
16+
'next_log_index_to_create' => $this->nextLogIndexToCreate,
17+
'max_chunk_size' => $this->maxChunkSize,
18+
'current_chunk_index' => $this->getCurrentChunk()->index,
19+
'chunk_definitions' => $this->chunkDefinitions,
20+
'current_chunk_definition' => $this->getCurrentChunk()->toArray(),
21+
];
22+
}
23+
24+
protected function saveMetadata(): void
25+
{
26+
$this->saveMetadataToCache();
27+
}
28+
29+
protected function loadMetadata(): void
30+
{
31+
$data = $this->getMetadataFromCache();
32+
33+
$this->lastScannedFilePosition = $data['last_scanned_file_position'] ?? 0;
34+
$this->lastScannedIndex = $data['last_scanned_index'] ?? 0;
35+
$this->nextLogIndexToCreate = $data['next_log_index_to_create'] ?? 0;
36+
$this->maxChunkSize = $data['max_chunk_size'] ?? self::DEFAULT_CHUNK_SIZE;
37+
$this->chunkDefinitions = $data['chunk_definitions'] ?? [];
38+
$this->currentChunkDefinition = $data['current_chunk_definition'] ?? [];
39+
}
40+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
namespace Opcodes\LogViewer\Concerns\LogIndex;
4+
5+
use Carbon\CarbonImmutable;
6+
use Carbon\CarbonInterface;
7+
8+
trait PreservesIndexingProgress
9+
{
10+
public function setLastScannedFilePosition(int $position): void
11+
{
12+
$this->lastScannedFilePosition = $position;
13+
}
14+
15+
public function getLastScannedFilePosition(): int
16+
{
17+
if (! isset($this->lastScannedFilePosition)) {
18+
$this->loadMetadata();
19+
}
20+
21+
return $this->lastScannedFilePosition;
22+
}
23+
24+
public function setLastScannedIndex(int $index): void
25+
{
26+
$this->lastScannedIndex = $index;
27+
}
28+
29+
public function getLastScannedIndex(): int
30+
{
31+
if (! isset($this->lastScannedIndex)) {
32+
$this->loadMetadata();
33+
}
34+
35+
return $this->lastScannedIndex;
36+
}
37+
38+
public function incomplete(): bool
39+
{
40+
return $this->file->size() !== $this->getLastScannedFilePosition();
41+
}
42+
43+
public function getEarliestTimestamp(): ?int
44+
{
45+
$earliestTimestamp = null;
46+
47+
if ($this->hasFilters()) {
48+
// because it has filters, we can no longer use our chunk definitions, which has
49+
// values for the whole index and not just particular levels/dates.
50+
foreach ($this->get() as $timestamp => $tsIndex) {
51+
$earliestTimestamp = min($timestamp, $earliestTimestamp ?? $timestamp);
52+
}
53+
} else {
54+
foreach ($this->getChunkDefinitions() as $chunkDefinition) {
55+
if (! isset($chunkDefinition['earliest_timestamp'])) {
56+
continue;
57+
}
58+
59+
$earliestTimestamp = min(
60+
$chunkDefinition['earliest_timestamp'],
61+
$earliestTimestamp ?? $chunkDefinition['earliest_timestamp']
62+
);
63+
}
64+
}
65+
66+
return $earliestTimestamp;
67+
}
68+
69+
public function getEarliestDate(): CarbonInterface
70+
{
71+
return CarbonImmutable::createFromTimestamp($this->getEarliestTimestamp());
72+
}
73+
74+
public function getLatestTimestamp(): ?int
75+
{
76+
$latestTimestamp = null;
77+
78+
if ($this->hasFilters()) {
79+
// because it has filters, we can no longer use our chunk definitions, which has
80+
// values for the whole index and not just particular levels/dates.
81+
foreach ($this->get() as $timestamp => $tsIndex) {
82+
$latestTimestamp = max($timestamp, $latestTimestamp ?? $timestamp);
83+
}
84+
} else {
85+
foreach ($this->getChunkDefinitions() as $chunkDefinition) {
86+
if (! isset($chunkDefinition['latest_timestamp'])) {
87+
continue;
88+
}
89+
90+
$latestTimestamp = max(
91+
$chunkDefinition['latest_timestamp'],
92+
$latestTimestamp ?? $chunkDefinition['latest_timestamp']
93+
);
94+
}
95+
}
96+
97+
return $latestTimestamp;
98+
}
99+
100+
public function getLatestDate(): CarbonInterface
101+
{
102+
return CarbonImmutable::createFromTimestamp($this->getLatestTimestamp());
103+
}
104+
}

0 commit comments

Comments
 (0)