|
4 | 4 |
|
5 | 5 | namespace Laravel\Boost\Concerns; |
6 | 6 |
|
| 7 | +use Illuminate\Support\Arr; |
7 | 8 | use Illuminate\Support\Facades\Config; |
8 | 9 |
|
9 | 10 | trait ReadsLogs |
@@ -45,11 +46,67 @@ protected function resolveLogFilePath(): string |
45 | 46 | $channel = Config::get('logging.default'); |
46 | 47 | $channelConfig = Config::get("logging.channels.{$channel}"); |
47 | 48 |
|
48 | | - if (($channelConfig['driver'] ?? null) === 'daily') { |
49 | | - return storage_path('logs/laravel-'.date('Y-m-d').'.log'); |
| 49 | + $channelConfig = $this->resolveChannelWithPath($channelConfig); |
| 50 | + |
| 51 | + $baseLogPath = Arr::get($channelConfig, 'path', storage_path('logs/laravel.log')); |
| 52 | + |
| 53 | + if (Arr::get($channelConfig, 'driver') === 'daily') { |
| 54 | + return $this->resolveDailyLogFilePath($baseLogPath); |
| 55 | + } |
| 56 | + |
| 57 | + return $baseLogPath; |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * @param array<string, mixed>|null $channelConfig |
| 62 | + * @return array<string, mixed>|null |
| 63 | + */ |
| 64 | + protected function resolveChannelWithPath(?array $channelConfig, int $depth = 0): ?array |
| 65 | + { |
| 66 | + if ($channelConfig === null || $depth > 2) { |
| 67 | + return $channelConfig; |
50 | 68 | } |
51 | 69 |
|
52 | | - return storage_path('logs/laravel.log'); |
| 70 | + if (isset($channelConfig['path'])) { |
| 71 | + return $channelConfig; |
| 72 | + } |
| 73 | + |
| 74 | + if (($channelConfig['driver'] ?? null) !== 'stack') { |
| 75 | + return $channelConfig; |
| 76 | + } |
| 77 | + |
| 78 | + $firstValidLoggerConfig = collect($channelConfig['channels'] ?? []) |
| 79 | + ->map(fn (string $name) => Config::get("logging.channels.{$name}")) |
| 80 | + ->filter(fn ($config): bool => is_array($config)) |
| 81 | + ->map(fn (array $config) => $this->resolveChannelWithPath($config, $depth + 1)) |
| 82 | + ->first(fn (?array $config): bool => isset($config['path'])); |
| 83 | + |
| 84 | + return $firstValidLoggerConfig ?? $channelConfig; |
| 85 | + } |
| 86 | + |
| 87 | + protected function resolveDailyLogFilePath(string $basePath): string |
| 88 | + { |
| 89 | + $pathInfo = pathinfo($basePath); |
| 90 | + $directory = $pathInfo['dirname']; |
| 91 | + $filename = $pathInfo['filename']; |
| 92 | + $extension = isset($pathInfo['extension']) ? '.'.$pathInfo['extension'] : ''; |
| 93 | + |
| 94 | + $todayLogFile = $directory.DIRECTORY_SEPARATOR.$filename.'-'.date('Y-m-d').$extension; |
| 95 | + |
| 96 | + if (file_exists($todayLogFile)) { |
| 97 | + return $todayLogFile; |
| 98 | + } |
| 99 | + |
| 100 | + $pattern = $directory.DIRECTORY_SEPARATOR.$filename.'-*'.$extension; |
| 101 | + $files = glob($pattern) ?: []; |
| 102 | + |
| 103 | + $datePattern = '/^'.preg_quote($filename, '/').'-\d{4}-\d{2}-\d{2}'.preg_quote($extension, '/').'$/'; |
| 104 | + $latestFile = collect($files) |
| 105 | + ->filter(fn ($file): int|false => preg_match($datePattern, basename($file))) |
| 106 | + ->sortDesc() |
| 107 | + ->first(); |
| 108 | + |
| 109 | + return $latestFile ?? $todayLogFile; |
53 | 110 | } |
54 | 111 |
|
55 | 112 | /** |
@@ -130,7 +187,7 @@ protected function scanLogChunkForEntries(string $logFile, int $chunkSize): arra |
130 | 187 | $offset = max($fileSize - $chunkSize, 0); |
131 | 188 | fseek($handle, $offset); |
132 | 189 |
|
133 | | - // If we started mid-line, discard the partial line to align to next newline. |
| 190 | + // If we started mid-line, discard the partial line to align to the next newline. |
134 | 191 | if ($offset > 0) { |
135 | 192 | fgets($handle); |
136 | 193 | } |
|
0 commit comments