Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Log Viewer Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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:

  1. composer require w3docs/log-viewer-bundle — expect version constraint friction on modern PHP; check composer.json's require block before you fight it.
  2. Register in app/AppKernel.php:
    new W3docs\LogViewerBundle\W3docsLogViewerBundle(),
    
  3. Import routes in app/config/routing.yml:
    log_viewer:
        resource: "@W3docsLogViewerBundle/Resources/config/routing.yml"
        prefix:   /_logs
    
  4. Point it at your Monolog output (app/logs/dev.log by default for the dev environment).
  5. Ensure the web server user can read the log directory.

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.
  • The parser class (search for 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.

Implementation Patterns

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:

  • a "last 10 errors" widget on an admin dashboard,
  • a cron job that scans for CRITICAL and emails/Slacks the team,
  • a health-check endpoint returning counts by level for the last hour.

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.

Gotchas and Tips

  • It's a dead dependency. Zero dependents, three stars, no recent activity. Pin the exact version in 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.
  • PHP/Symfony version ceiling. Symfony2 bundles of this vintage often hard-require 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.
  • Multi-line exceptions are the classic failure. Monolog writes a stack trace on continuation lines with no timestamp prefix. Naive parsers either drop those lines or attribute them to the wrong entry, so you see 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.
  • Permissions and SELinux. 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.
  • Memory on big files. Parsers of this generation often 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.
  • Log leakage. Logs contain SQL, request payloads, tokens, and sometimes passwords in exception messages. This is the reason to gate the route hard and never enable in prod. Treat the viewer as a privileged debug tool, not a feature.
  • Config caching. After editing config.yml/routing.yml, run app/console cache:clear --env=dev. Symfony2 config changes silently not applying is almost always this.
  • Route name collisions. Run app/console router:debug | grep -i log after importing to confirm the prefix didn't clobber an existing route.
  • Extension points, cheapest first: (1) override templates by mirroring the path under 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.
  • Debugging discipline: when the UI disagrees with reality, always tail -f the raw file first. Nine times out of ten it's the formatter or a rotated/misconfigured path, not the bundle.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource