greenskies/web-log-viewer-bundle
A web-based log viewer bundle for PHP applications that lets developers inspect, search, and filter application logs from the browser. It provides a simple interface for navigating log files and debugging issues without direct server access.
Reality check before you composer require anything. This is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/web-log-viewer.php to publish, and no php artisan vendor:publish path. Laravel's package auto-discovery will not find it, and installing it into a Laravel app gets you a class that expects Symfony\Component\HttpKernel\Bundle\Bundle, the Symfony DI container, and Symfony routing. For a Laravel codebase, the realistic options are:
opcodesio/log-viewer or rap2hpoutre/laravel-log-viewer) — same feature set, maintained, zero friction.If you are on Symfony (3.4/4.x era), minimal steps:
composer require greenskies/web-log-viewer-bundle
Then register the bundle in app/AppKernel.php (or config/bundles.php on Symfony 4+), import its routing (check Resources/config/routing.xml/.yml for the route name and path), and set the log file path in your config. Look first at DependencyInjection/Configuration.php — that file is the authoritative list of config keys, defaults, and whether a path or a directory is expected. Second, read the controller and the log-reading service: they tell you exactly which Monolog line format the parser assumes.
First use case: point it at var/log/dev.log, load the route, and confirm it renders the default Monolog format ([2024-01-01 12:00:00] app.INFO: message [] []). If your handler uses a custom formatter (json, logstash), it will likely show blank or unparsed rows — that's your first signal about how much you'd need to fork it.
config/packages/*.yaml under the bundle's alias rather than hardcoding. The bundle has no environment awareness of its own; it reads whatever path you give it.var/log/prod.log while the bundle points at %kernel.logs_dir%/app.log (a Symfony 2/3-era default). Grep your monolog.yaml handlers for the path: value and copy it verbatim.access_control entry requiring ROLE_ADMIN (or an IP allowlist via security.access_control with ips:). Better still, put it on a separate admin firewall/subdomain so a misconfigured anonymous: true can't leak it. Log files contain session IDs, API tokens, and PII.{timestamp, channel, level, message, context} → render. In Laravel that's a Route::get('/logs', ...) behind auth + a Gate, using SplFileObject with SEEK_END-style tailing for large files, plus a Str::contains filter. Do not use file() — see gotchas.storage/logs into the Symfony container read-only and point the bundle at it. This is the one scenario where the bundle genuinely earns its place.Bundle no longer auto-resolving paths, type: annotation route loading removed, deprecated Twig functions in the templates, and services.yml autowiring that doesn't match modern defaults. composer require will most likely fail on constraints; use composer why-not greenskies/web-log-viewer-bundle to confirm, then vendor a patched fork.each()/create_function-era code if it's present. Run with error_reporting(E_ALL) once before trusting the output.symfony/flex recipe, so registration and routing import are entirely manual. Missing the routing import is the #1 cause of a 404 — verify with bin/console debug:router | grep -i log.file()/file_get_contents (loads everything) or a streamed iterator. Test against a ~200–500 MB rotated log before shipping; a viewer that OOMs the FPM worker is worse than no viewer.prod.log means the UI silently switches to the fresh file after rotation, and yesterday's prod-2024-01-01.log disappears from view. If you need history, point at a directory (if supported — check the config tree) or a stable symlink.audit.log for avc: denied on the log path before assuming the bundle is broken.bin/console debug:config <bundle_alias> (confirms your keys are actually merged), debug:router, lint:container. A blank page is usually the security firewall redirecting you to login in a loop rather than a template error.templates/bundles/<BundleName>/ on Symfony 4+. There are no events, no parser interface worth decorating, and no hook system — anything beyond path config means forking.Controller/ and the reader service for 10 minutes, port the parsing to Laravel, gate it behind auth, and move on.How can I help you explore Laravel packages today?