mlsolutions/nova-logs
A Laravel Nova tool for viewing and managing application logs from the dashboard. Browse log files, search and filter entries, inspect stack traces, and monitor recent errors without needing SSH access.
Install into an existing Nova 4/5 app and confirm it registers as a Nova tool:
composer require mlsolutions/nova-logs
php artisan vendor:publish --provider="MlSolutions\NovaLogs\NovaLogsServiceProvider" --tag=config
Most Nova tools are auto-discovered through NovaServiceProvider::tools(). If the entry does not appear in the sidebar after php artisan nova:publish / cache clear, register the tool class manually in app/Nova/NovaServiceProvider.php:
public function tools()
{
return [
new \MlSolutions\NovaLogs\NovaLogs,
];
}
Where to look first:
config/nova-logs.php (published config) — log path, allowed channels, level filters, permissions.src/ directory — the controller that reads log files and the parser that splits entries. This tells you whether it uses File::get(), a streaming reader, or a third-party parser.routes/ — Nova tools register a ToolServiceProvider with routes under /nova-vendor/.... Confirm the middleware includes Nova's auth middleware.First use case: Open the tool, point it at storage/logs/laravel.log, and verify it renders the most recent entries with level badges and timestamps. Then reproduce a known exception (e.g. throw in a tinker session) and confirm it appears without a page refresh or after a manual reload.
Daily debugging loop. Use the tool as a first-pass triage screen: filter to error/critical, copy the stack trace, then jump to Telescope or the exception handler for the full context. The log viewer is best at "what happened in the last hour," not at deep tracing.
Channel-aware configuration. If you use multiple channels (daily, slack, stderr), configure the tool to only expose filesystem-backed channels. Pointing it at a nonexistent path typically produces an empty state rather than an error, which silently hides misconfiguration — add a health check or assert the path exists at boot in non-production.
Per-environment visibility. Guard the tool so it is only visible where it makes sense:
public function fields(NovaRequest $request)
{
return [];
}
public function canSee(NovaRequest $request)
{
return $request->user()->isAdmin()
&& app()->environment(['local', 'staging']);
}
Use this to keep production log access restricted to on-call engineers, and pair it with Nova's Gate policies if you have role-based access.
Wiring into existing workflows. Two integrations pay off quickly:
laravel/telescope for structured exceptions and keep this package for raw output that Telescope truncates — things like dd() output, PHP warnings, and queue worker noise.Rotation and archival. For daily channels, configure the tool with a date-aware file pattern (e.g. laravel-*.log) and sort newest-first. If the parser only accepts a single filename, either extend it or accept that you will be reading the current day only — plan a separate archival path for anything older.
Local development. In local, set the log level to debug and use the viewer as the primary output stream while iterating. It is a faster feedback loop than tailing a terminal when you are already in the browser, especially for form/validation errors surfaced through Nova actions.
file_get_contents() on a 500 MB log will exhaust memory. Check whether the implementation streams line-by-line or reads whole files; if the latter, cap what you display (last N lines / last N entries) and document it.#) under the parent record. If it does not, filtering by level will show orphaned trace fragments.storage/logs ownership before debugging the package.config('app.timezone'); the viewer may render in the user's browser timezone. Date filters can therefore appear off by hours. Confirm which side converts, and prefer filtering by level over by exact timestamp until you know.canSee hook but no opinion about roles. If you forget to override it, every Nova user with access to the panel can read stack traces, SQL fragments, and possibly credentials in logged payloads. Treat log access as a privileged capability.php artisan config:cache in deploy scripts will freeze the published config. Any runtime toggle (e.g. enabling the tool per environment) must be resolved through canSee, not through config mutation.composer.json, and wrap it behind a feature flag so you can drop it without a refactor. For long-term needs, opcodesio/log-viewer (standalone, framework-agnostic) or Telescope's log watcher are better-supported alternatives.How can I help you explore Laravel packages today?