Installation:
composer require root913/laravel-log-viewer
Register Service Provider:
Add Rap2hpoutre\LaravelLogViewer\LaravelLogViewerServiceProvider::class to config/app.php under providers.
Publish Config (Optional):
php artisan vendor:publish --provider="Rap2hpoutre\LaravelLogViewer\LaravelLogViewerServiceProvider"
This creates a config/log-viewer.php file for customization (e.g., log file paths, permissions).
Route the Controller:
Add this to your routes/web.php (or routes/api.php if needed):
Route::get('/logs', 'Rap2hpoutre\LaravelLogViewer\LogViewerController@index');
Protect this route with middleware (e.g., auth) in production.
First Use Case:
Visit /logs to view Laravel’s default log file (storage/logs/laravel.log). Filter by date, search for errors, or download logs.
Log Inspection:
2023-10-01 or error)..txt file for offline analysis.Integration with Existing Systems:
log-viewer.php to include additional log files (e.g., storage/logs/debug.log):
'files' => [
storage_path('logs/laravel.log'),
storage_path('logs/debug.log'),
],
Route::get('/api/logs', [LogViewerController::class, 'apiIndex']);
Development vs. Production:
auth:support) and log viewer usage to APP_DEBUG=true:
if (!app()->environment('local') && !config('log-viewer.enabled')) {
abort(403);
}
Automated Logging:
Log::critical() for high-severity issues to ensure they appear prominently in the viewer.Log::debug('User {id} logged in', ['id' => $user->id])) for easier filtering.Log Anonymization:
Override the LogViewerController to sanitize sensitive data before rendering:
public function index() {
$logs = $this->getLogs();
$sanitizedLogs = collect($logs)->map(fn($log) => str_replace('password=***', 'password=****', $log));
return view('log-viewer::index', ['logs' => $sanitizedLogs]);
}
Log Retention Policies:
Combine with Laravel’s log-rotate package to auto-clean old logs and reduce viewer load.
Custom Views:
Extend the default Blade template (resources/views/vendor/log-viewer/index.blade.php) to add:
Permission Issues:
403.www-data) has read access to storage/logs/:
chmod -R 755 storage/logs/
chown -R www-data:www-data storage/logs/
storage_path('logs') in log-viewer.php to avoid hardcoding paths.Log Rotation Conflicts:
log-viewer.php to include rotated logs:
'files' => [
storage_path('logs/laravel-*.log'), // Wildcard for rotated files
],
php artisan log:rotate before deploying.Performance with Large Logs:
config/logging.php.config('log-viewer.max_lines', 1000) to cap displayed logs.Middleware Conflicts:
api routes). Use:
Route::middleware(['web'])->get('/logs', [LogViewerController::class, 'index']);
Check Logs First:
If the viewer fails, inspect storage/logs/laravel.log for errors like:
[2023-10-01 12:00:00] local.ERROR: File not found at /path/to/log (View: /vendor/...)
This often indicates a path or permission issue.
Disable Caching: Clear Laravel’s view cache if templates aren’t updating:
php artisan view:clear
Test with Minimal Config:
Reset log-viewer.php to defaults to isolate issues:
return [
'enabled' => true,
'files' => [storage_path('logs/laravel.log')],
];
Custom Log Formats:
Override the LogViewerController to parse custom log formats (e.g., JSON):
protected function parseLogLine($line) {
$data = json_decode($line, true);
return $data['message'] ?? $line;
}
Add Log Context:
Extend the LogViewerController to include additional metadata (e.g., request IDs):
public function index() {
$logs = $this->getLogs();
$enrichedLogs = array_map(function($log) {
return [
'line' => $log,
'context' => $this->extractContext($log),
];
}, $logs);
return view('log-viewer::index', ['logs' => $enrichedLogs]);
}
Plugin Architecture: Create a trait for reusable log-viewer logic:
namespace App\Traits;
use Rap2hpoutre\LaravelLogViewer\LogViewerController as BaseController;
trait LogViewerExtensions {
protected function getLogs() {
$logs = parent::getLogs();
// Add custom logic (e.g., filter by IP)
return $logs;
}
}
Then use it in your controller:
class CustomLogViewerController extends BaseController {
use LogViewerExtensions;
}
Localization: Override the default Blade templates to support multiple languages:
cp vendor/rap2hpoutre/laravel-log-viewer/resources/views/vendor/log-viewer/* resources/views/vendor/log-viewer/
Then translate strings in resources/views/vendor/log-viewer/index.blade.php.
enabled Flag:
Disable the viewer in production by default (config('log-viewer.enabled', false)) and enable only for specific environments:
'enabled' => app()->environment(['local', 'staging']),
File Path Wildcards:
Use glob()-compatible patterns in log-viewer.php:
'files' => [
storage_path('logs/*.log'), // All log files
storage_path('logs/error-*.log'), // Only error logs
],
Memory Limits:
Large logs may hit PHP’s memory limit. Increase in .env:
MEMORY_LIMIT=512M
Or stream logs line-by-line in the controller:
public function index() {
$handle = fopen(storage_path('logs/laravel.log'), 'r');
$logs = [];
while (!feof($handle)) {
$logs[] = fgets($handle);
}
fclose($handle);
return view('log-viewer::index', ['logs' => $logs]);
}
How can I help you explore Laravel packages today?