kahovskaia/laravel-log-viewer
Lightweight Laravel log viewer package for browsing application log files from within your app. Helps locate, filter, and inspect recent entries during development or debugging without leaving the Laravel environment.
Installation
composer require kahovskaia/laravel-log-viewer
Publish the config file (if needed):
php artisan vendor:publish --provider="Kahovskaia\LogViewer\LogViewerServiceProvider"
Basic Usage
The package provides a facade (LogViewer) to read log files. Start by configuring the log paths in config/log-viewer.php:
'paths' => [
storage_path('logs/laravel.log'),
storage_path('logs/debug.log'),
],
First Use Case Fetch and display logs in a controller or blade view:
use Kahovskaia\LogViewer\Facades\LogViewer;
$logs = LogViewer::getLogs();
return view('logs.view', compact('logs'));
Reading Logs Fetch logs with optional filtering:
// Get all logs
$logs = LogViewer::getLogs();
// Filter by date range (YYYY-MM-DD)
$logs = LogViewer::getLogs('2023-01-01', '2023-01-31');
// Filter by log level (e.g., 'error', 'debug')
$logs = LogViewer::getLogs(null, null, 'error');
Integration with Blade Views
Create a dedicated view (resources/views/logs/view.blade.php):
@foreach($logs as $log)
<div class="log-entry">
<strong>{{ $log['datetime'] }}</strong>
<span class="level">{{ $log['level'] }}</span>
<p>{{ $log['message'] }}</p>
</div>
@endforeach
API Endpoint for Logs Expose logs via an API route:
Route::get('/api/logs', function () {
return response()->json(LogViewer::getLogs());
});
Custom Log Parsing
Extend the package by overriding the LogParser class (located in src/LogParser.php):
namespace App\Services;
use Kahovskaia\LogViewer\LogParser as BaseLogParser;
class CustomLogParser extends BaseLogParser
{
protected function parseLine($line)
{
// Custom parsing logic
return parent::parseLine($line);
}
}
Bind the custom parser in AppServiceProvider:
public function register()
{
$this->app->bind(
\Kahovskaia\LogViewer\Contracts\LogParser::class,
\App\Services\CustomLogParser::class
);
}
Log Tailing (Real-Time) Implement a real-time log viewer using Laravel Echo/Pusher or a simple AJAX poll:
// Example AJAX polling
function pollLogs() {
fetch('/api/logs')
.then(response => response.json())
.then(logs => {
// Update UI with new logs
document.getElementById('logs-container').innerHTML = logs.map(log => `<div>${log.message}</div>`).join('');
});
setTimeout(pollLogs, 5000); // Poll every 5 seconds
}
pollLogs();
Log Search Functionality Add search to your Blade view:
// Controller
$searchTerm = request('search');
$logs = LogViewer::getLogs(null, null, null, $searchTerm);
// Blade
<input type="text" name="search" placeholder="Search logs...">
<button>Search</button>
Log File Rotation
LogViewer paths include all rotated logs (e.g., laravel.log, laravel-2023-01-01.log).'paths' => [storage_path('logs/laravel-*.log')],
Performance with Large Logs
$logs = LogViewer::getLogs(null, null, null, null, 50); // Limit to 50 entries
Custom Log Formats
LogParser (as shown above) or pre-process logs.Permissions
www-data) has read access to log files:
chmod 644 storage/logs/*
chown -R www-data:www-data storage/logs/
Check Parsed Logs Temporarily dump parsed logs to debug:
$rawLogs = LogViewer::readLogFiles();
dd($rawLogs); // Inspect raw log content
Log Parser Errors
If logs aren’t parsing correctly, verify the parseLine method in LogParser matches your log format. Example debug line:
protected function parseLine($line)
{
if (preg_match('/\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (\w+)\. (\d+)\. (.*)/', $line, $matches)) {
return [
'datetime' => $matches[1],
'level' => $matches[2],
'context' => $matches[4],
'message' => $matches[4],
];
}
return null; // Return null for unparseable lines
}
Missing Logs
config/log-viewer.php is correct.LOG_CHANNEL in .env matches the log file location.Add Log Levels
Extend the supported log levels in LogViewer:
// In a service provider
$this->app->extend('log-viewer', function ($viewer) {
$viewer->addLogLevel('custom', 'Custom Level');
return $viewer;
});
Custom Storage Backend Override the default file-based log reader to fetch logs from a database or external service:
namespace App\Services;
use Kahovskaia\LogViewer\Contracts\LogReader;
class DatabaseLogReader implements LogReader
{
public function read()
{
return DB::table('logs')->get()->toArray();
}
}
Bind it in AppServiceProvider:
$this->app->bind(
\Kahovskaia\LogViewer\Contracts\LogReader::class,
\App\Services\DatabaseLogReader::class
);
Log Anonymization Sanitize sensitive data in logs before displaying them:
$logs = LogViewer::getLogs();
$sanitizedLogs = array_map(function ($log) {
$log['message'] = preg_replace('/[a-zA-Z0-9]{8,}/', '[REDACTED]', $log['message']);
return $log;
}, $logs);
How can I help you explore Laravel packages today?