w3docs/log-viewer-bundle
A Symfony log viewer bundle that adds a web interface for reading application logs. Browse and filter entries, inspect exceptions and debug messages, and troubleshoot issues without direct server access.
Read this first: it is not a Laravel package. w3docs/log-viewer-bundle is a Symfony2-era bundle (registered in AppKernel, configured in config.yml, routed via routing.yml). There is no service provider, no config/log-viewer.php, no artisan command. With 3 stars and 0 dependents it is effectively a dormant project — treat it as "small codebase you can read in an afternoon," not "dependency you adopt blindly."
If you are on Laravel: don't force this in. Use opcodesio/log-viewer (or rap2hpoutre/laravel-log-viewer for something tiny). You get the same feature — parse storage/logs/laravel.log, filter by level, paginate — with Laravel-native auth and config.
If you are maintaining a legacy Symfony2 app and this is already installed, or you're evaluating it for one:
composer require w3docs/log-viewer-bundle — expect version constraint friction on modern PHP; check composer.json's require block before you fight it.app/AppKernel.php:
new W3docs\LogViewerBundle\W3docsLogViewerBundle(),
app/config/routing.yml:
log_viewer:
resource: "@W3docsLogViewerBundle/Resources/config/routing.yml"
prefix: /_logs
app/logs/dev.log by default for the dev environment).Where to look first, in this order — this is a small bundle, so source beats docs:
DependencyInjection/Configuration.php — the authoritative list of config keys (log path, parser settings, pagination).Resources/config/routing.yml and the controller — confirms the URL and action names.preg_match / LogParser) — this tells you exactly what line format it expects, which is the single biggest source of "why is my log empty."Resources/views/ — templates you'll likely override.First use case: open the viewer against dev.log, filter to ERROR/CRITICAL, and read the exception. That is 90% of what anyone uses these tools for.
Gate it to dev and protect the route. The default Symfony2 pattern:
# config_dev.yml only
log_viewer:
log_file: %kernel.root_dir%/logs/dev.log
and in security.yml, put the prefix behind access_control with ROLE_ADMIN plus a firewall, or restrict at the web-server level. Never let this route exist in prod config with a prod.log it can read.
Multiple log files. Configure per-environment rather than trying to make one instance read everything — dev reads dev.log, staging reads staging.log. If the bundle exposes a chooser, back it with a parameter map; if not, register two route imports with different prefixes and different configs, or accept the one-file limitation.
Reuse the parser as a service. The interesting part of the bundle isn't the HTML table, it's the line parser. Find its service id (app/console container:debug | grep -i log) and inject it into your own code to build:
CRITICAL and emails/Slacks the team,This is where a scrappy bundle earns its keep — the parser is genuinely reusable even if the UI isn't.
Match your Monolog formatter to the parser. The parser likely expects Monolog's default line format ([%datetime%] %channel%.%level_name%: %message%). If you've switched to monolog.formatter.json or a custom formatter with a different delimiter/ordering, either add a dedicated handler writing a second, parseable file, or write a custom parser class and override the service.
Embed it rather than living in it. Route prefix /_logs, link it from your admin nav, and use target="_blank". Don't build product features on top of the views — build them on the parser service.
Testing. Write one functional test with a fixture log file containing a known good line, a malformed line, and a multi-line stack trace. Assert what the controller renders. It documents the format assumption and catches breakage when Monolog upgrades.
Migration path. If this app will live on, write the ~150 lines yourself: a LogEntry value object, a regex parser, and a controller. You'll remove the abandoned-dependency risk and own the auth integration.
composer.lock, vendor-fork it if you must patch, and put a note in the README that it's on the way out. Don't let it become load-bearing.symfony/symfony ~2.x and PHP 5.x. composer require will fail on PHP 8 — resist --ignore-platform-reqs; if the code uses removed functions it will fatal at runtime, not at install.ERROR: exception occurred with no trace. If traces matter, verify against a real crash before trusting the UI — tail -n 200 dev.log and compare side by side.www-data needs read on app/logs. On RHEL-family hosts, chcon -t httpd_sys_content_t or you'll get a silent empty list. The bundle's own errors land in the same dev.log — check there if the page renders blank.file_get_contents() the whole file. A 500MB rotated log will blow memory_limit and take the request down. Truncate, rotate (logrotate daily, keep 5), and cap what you point it at.config.yml/routing.yml, run app/console cache:clear --env=dev. Symfony2 config changes silently not applying is almost always this.app/console router:debug | grep -i log after importing to confirm the prefix didn't clobber an existing route.app/Resources/W3docsLogViewerBundle/views/; (2) override the parser service definition in your app config with the same service id; (3) bundle inheritance via getParent() if you need to swap the controller. Avoid editing vendor/ — it won't survive the next composer install.tail -f the raw file first. Nine times out of ten it's the formatter or a rotated/misconfigured path, not the bundle.How can I help you explore Laravel packages today?