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

Laravel Log Db Laravel Package

yoeriboven/laravel-log-db

Store Laravel application logs in the database instead of files. This package adds a database log channel that saves messages, levels, context and timestamps to a queryable logs table, so you can browse, filter and search your logs directly from your app or admin panel.

View on GitHub
Deep Wiki
Context7

Getting Started

yoeriboven/laravel-log-db adds a Monolog handler that persists Laravel log records to a database table, so log entries become queryable rows instead of grepping through storage/logs/laravel.log. Version 3.0 is a support-matrix release: it adds Laravel 13 and drops Laravel 9, 10 and 11 (all EOL). Supported targets are now Laravel 12 and 13. There are no new features or schema changes, so day-to-day usage is identical to 2.x.

Minimum setup:

  1. composer require yoeriboven/laravel-log-db — on Laravel ≤11 this resolves to ^2.1; require ^3.0 explicitly and confirm your laravel/framework constraint allows 12/13 before upgrading.
  2. Publish the config and migration: php artisan vendor:publish --tag="log-db-config" and php artisan vendor:publish --tag="log-db-migrations".
  3. php artisan migrate to create the logs table (message, level, context, channel, timestamps).
  4. Register a channel in config/logging.php that uses the package's Monolog handler, then add it to your stack:
// config/logging.php
'db' => [
    'driver'  => 'monolog',
    'handler' => \Yoeriboven\LogDb\Handlers\LogDbHandler::class,
    'level'   => env('LOG_DB_LEVEL', 'error'),
],
  1. Set LOG_STACK=single,db (or add db to your stack channel) so file logging still happens as a fallback.
  2. Verify: Log::error('boom', ['order_id' => 42]); then DB::table('logs')->latest('id')->first();.

First use case: production error triage. Instead of SSHing to tail a file, you query Log::where('level', 'error')->whereDate('created_at', today()) from Tinker, a Nova/Filament resource, or a scheduled digest command.

Implementation Patterns

Keep file logging in the stack, not the DB channel alone. The DB handler should be an additional sink. LOG_STACK=single,db gives you the queryable row plus a durable file record if the database write itself fails.

Tier the levels per environment. Don't write debug to the database in production. Use a narrow DB channel (error+ in prod, debug locally) and let the file channel absorb the noisy levels. This is the single biggest lever on table growth and write overhead.

Separate channels for separate intents. A common pattern is two DB channels — one for error/critical used by a "recent incidents" dashboard, and one for info/warning on specific domains (payments, webhooks, imports) where you actually want audit-style queryability. Register both as handlers with different level values and point code at them explicitly: Log::channel('payments_db')->info(...).

Query through the package model. Bind Yoeriboven\LogDb\Models\Log (or a subclass) and expose scopes for the queries you run repeatedly — errors(), forChannel($name), since($date). Adding ->where('context->order_id', $id) works well on MySQL/Postgres JSON columns and lets support staff reconstruct a single order's history without touching the filesystem.

Wire retention from day one. Add a scheduled prune rather than hoping the table stays small:

// routes/console.php
Schedule::call(fn () => Log::where('created_at', '<', now()->subDays(30))->delete())
    ->daily();

Index level and created_at (and add a composite index if you filter by both) before volume arrives, not after.

Route the noisy stuff elsewhere. Framework/queue/vendor chatter dominates row counts. Use config/logging.php per-channel config to keep the DB handler off channels you don't care about, and add context filtering so exceptions with large payloads don't bloat rows.

Test against the channel, not the table. Log::spy() / Log::shouldReceive() assertions stay stable across driver changes; assertions on raw table rows couple tests to the handler's formatting.

Gotchas and Tips

3.0 is a hard upgrade gate. If any app or shared package pins Laravel 9/10/11, stay on ^2.1. Nothing in your config/log-db.php, migrations, or handler registration changes between 2.1 and 3.0 — treat this as a Composer constraint change and verify CI matrix and any lockfile-pinned deployments together.

Database-down means logs-down. The handler writes over the same connection it's reporting about. If the DB is unreachable or the connection is exhausted, DB log writes fail silently (or throw inside the logging path). Always keep the file channel first in the stack, and consider pointing the package at a separate connection in config/log-db.php if you log about a primary DB.

Transactions can eat your logs. Rows written inside a transaction that later rolls back disappear — which is exactly when you most wanted them. Don't rely on DB logs for auditing failed writes; log to file or a separate connection for post-mortem-critical events.

logs is a popular table name. Other packages and hand-rolled migrations collide here. Check php artisan migrate output on a fresh DB, and rename via the config's table setting rather than editing the published migration if you need to coexist.

Config caching hides channel changes. After editing config/logging.php or config/log-db.php, run php artisan config:clear locally and config:cache in deploy. A stale cache silently keeps writing to the old level/table and looks like a broken handler.

Sensitive context leaks into the table. Validation failures and request exceptions can carry passwords, tokens, and full payloads. Filter context before it reaches the handler, and treat the logs table with the same access controls as your users table.

Don't debug the handler blind. If rows stop appearing: confirm the channel is in LOG_STACK, confirm the level threshold on both the channel and the package config, and test with Log::channel('db')->error(...) directly — bypassing the stack isolates routing problems from handler problems.

Extension point: subclass the handler (or the Log model) rather than modifying the published config in place, so upgrades stay copy-paste clean.

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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums