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

Nova Log Viewer Laravel Package

laravel/nova-log-viewer

A Laravel Nova tool for viewing your application logs right inside Nova, with polling support. Install via Composer and register LogViewer::make() in your NovaServiceProvider's tools method.

View on GitHub
Deep Wiki
Context7

Getting Started

Three commands and one array entry, no publish step, no migrations, no config file:

composer require laravel/nova-log-viewer
// app/Providers/NovaServiceProvider.php
public function tools()
{
    return [
        // ...
        \Laravel\Nova\LogViewer\LogViewer::make(),
    ];
}

Nothing to compile on your side — the tool ships its own built assets. Restart your queue/OPcache if you're on a config-cached deploy, then refresh Nova and look for the new sidebar entry.

Where to look first. Open the tool once and identify the two controls that will define your day-to-day use: the file selector (v1.0.2 specifically fixed selection when multiple log files exist, so single-plus-daily setups should list laravel.log and each laravel-YYYY-MM-DD.log) and the polling toggle. Everything else is a text view of the file on disk.

First use case. Pick a staging box, throw a deliberate exception at a route (throw new \Exception('log viewer smoke test');), open the tool, and confirm the entry appears — then leave polling on and throw a second one to confirm it arrives without a manual refresh. That ten-minute spike tells you three things at once: the tool has read access to storage/logs, you're looking at the right channel, and polling behaves against your real log volume. Do this on staging before production, because the second part of the check is watching how the UI feels when laravel.log is 40MB rather than 4KB.

Implementation Patterns

Gate it explicitly — there is no RBAC in the package. Out of the box, anyone who can reach Nova can read raw logs. Nova's Tool base class gives you the hooks; use them:

public function tools()
{
    return [
        \Laravel\Nova\LogViewer\LogViewer::make()
            ->canSee(fn ($request) => $request->user()->hasRole('admin'))
            ->canRun(fn ($request) => $request->user()->hasRole('admin')),
    ];
}

canSee hides the sidebar link; canRun blocks the route. Set both — hiding a menu item is not authorization. If you already have an App\Nova\Tools policy or a viewLogs gate, this is where it goes.

Register per environment. Many teams want this on staging and production but not on local, where tail -f and Telescope are already in muscle memory:

return array_filter([
    \Laravel\Nova\LogViewer\LogViewer::make()->canSee($adminOnly),
    // ...
]);

Or drop it entirely via $this->app->isLocal(). Keeping local clean avoids a stale second window into the same file you're already watching.

Support triage loop. The workflow that actually pays for the install: a customer reports a 500 at 14:32. Support opens the tool, sets polling on, selects the date-partitioned file for today, and scrolls to the timestamp. They copy the exception class and top stack frame into the ticket before escalating. Engineering receives a triaged ticket instead of "customer says it's broken." The tool has no search across history and no aggregation — so coach support to scan the visible window and paste, not to expect a query interface.

Deploy and job verification. Add a temporary Log::info('deploy marker', ['sha' => $sha]); to your deploy script (or listen to Illuminate\Foundation\Events\Terminating), then watch the tool during a deploy to confirm the new code is live and booting cleanly. The same pattern covers queue workers: a failed job dumps its full stack trace plus serialized payload into laravel.log, and this is often the fastest way to read it without shell access to the box.

Make the logs worth reading. The viewer is only as good as what you write. Structured context renders far better than string concatenation:

Log::error('Payment capture failed', [
    'order_id' => $order->id,
    'gateway_status' => $response->status(),
]);

If you have a noisy stack, route the signal to a dedicated channel so it lands in its own file and its own tab in the file selector rather than buried in a 60MB default file:

// config/logging.php
'payments' => ['driver' => 'daily', 'path' => storage_path('logs/payments.log'), 'level' => 'debug'],

Log::channel('payments')->error(...) then shows up as a selectable file.

Pair with LOG_LEVEL discipline. In production, LOG_LEVEL=error means the viewer will show you almost nothing. The tool is a window onto whatever your logger writes — if the file is empty, check config/logging.php and .env before assuming the package is broken.

Gotchas and Tips

  • It reads files, not streams. single and daily on local disk work. stderr, syslog, and any shipping driver (CloudWatch, Papertrail, Datadog) leave the app with no file to open, and the viewer shows nothing or a stale remnant. Confirm your default channel before installing.
  • Multi-replica deployments lie to you. Behind a load balancer, each request reads whichever replica served it, so you see one container's logs with no indication which one. Ephemeral pods make this worse — the file resets on deploy. This is the single biggest reason to look elsewhere in a Kubernetes estate.
  • Permissions are a real failure mode. storage/logs is often www-data-owned and laravel.log may be created lazily. If the web user can't read the directory, the file selector comes up empty with no error worth reading. sudo -u www-data ls -la storage/logs is the first debugging step.
  • Polling against a fat file. There's no documented batching, pagination, or throttle knob. Polling re-reads a growing file, so a 200MB laravel.log left open in a tab in three people's browsers is a genuine load source during an incident. Mitigate operationally: use daily so files are bounded, rotate/trim aggressively, and close the tab when you're done. The package has no config to tune here — that's the limit, not a setting you've missed.
  • PII and secrets land in logs. Stack traces carry request context, SQL fragments, internal hostnames, and occasionally tokens or email addresses. Because there's no redaction, the access decision is the redaction decision. If compliance requires an audit trail of who viewed what, this package cannot provide it — you'd need to wrap the route.
  • Version pinning matters. Laravel 13 needs v1.2.0+; Nova 5.9 needs v1.3.0+; Nova 5.7.7 needs v1.1.0+. If you're on Nova 5.9 and see Inertia or asset-resolution errors, check composer show laravel/nova-log-viewer first.
  • The 403-vs-redirect fix landed in v1.2.0. Before that, an expired session hitting the tool's endpoint returned 403 instead of redirecting to login, which looks like an authorization bug in your own gates. Stay on ≥1.2.0 if you have short session lifetimes.
  • Truncation mid-poll. > storage/logs/laravel.log (shell redirect) rather than a true rotation can leave the viewer's read offset past the end of the file, showing a blank pane until refresh. Prefer daily channels or logrotate with copytruncate.
  • Extension point is the Nova Tool class, not a config file. There's no publishable config and no per-user log scoping. If you need "each tenant sees only their own log file," that's a fork or a custom tool — don't expect to configure it in.
  • It is triage, not observability. No historical search, no counts, no alerting, no retention. When you find yourself wanting "how often did this happen last week," that's the signal to reach for a real platform rather than bending this tool.
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.
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo
bernskioldmedia/laravel-harvest
bernskiold/laravel-data-scrubber
bernskiold/laravel-currency-converter
bernskiold/laravel-campaign-monitor
bernskioldmedia/laravel-autotranslate
siberfx/telegram-bot
roy-sandip/laravel-view-extended
gregsphotography/site-builder-core
roy-sandip/laravel-view
anodyne/blade-fluentui-icons
webx-ui/module-catalog-collections