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 Devlogger Laravel Package

onamfc/laravel-devlogger

Laravel DevLogger stores application logs in the database with automatic exception catching, tagging, queue and request/user context, advanced filtering, and configurable retention cleanup. Easily configurable via environment variables.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Parallel logging path, not a Monolog channel. DevLogger is a facade (DevLogger::info()) plus a model over a developer_logs table. It does not plug into Laravel's logging.php channel stack, so it duplicates rather than replaces the existing log pipeline. Adopters will run two logging systems (file/stderr via Monolog, structured rows via DevLogger) unless they explicitly retire the other — budget for that duplication in both cost and cognitive overhead.
  • Best fit: single-tenant modular monolith, Laravel 9–12, PHP 8.2+, no existing error-tracking vendor. The feature set — open/closed status, tags, updated_by, user attribution — is effectively lightweight incident triage. It competes with Sentry/Flare/Bugsnag on workflow and loses on alerting, grouping, and breadcrumbs. Where a team already pays for Sentry, this package adds little beyond SQL-queryable history.
  • The "management capabilities" are a query API, not a product. Filtering is Eloquent scopes (level(), open(), dateRange(), queue()) and a DeveloperLog model. There is no dashboard, no alerting, no grouping/dedup. Any stakeholder promise of "a log UI" is a build item we own, not an install item. This is the single largest scope risk in the evaluation.
  • No external service dependency is a genuine advantage: no egress, no DPA with a third party, works air-gapped, data stays in our DB. That matters for regulated or on-prem deployments.

Integration Feasibility

  • Low-effort install, moderate-effort hardening. composer require → publish config → php artisan migrate is a 30-minute path to first row. The real work is environment config, exception-handler integration, retention scheduling, and PII scoping.
  • Exception capture has two integration modes and one is invasive. Extending DevLoggerExceptionHandler replaces our existing app/Exceptions/Handler.php base class — unacceptable in any app with custom report()/render() logic. Use Option 2 (a report() hook) or the Laravel 12 withExceptions(...) closure, both of which are additive and reversible. Note the README's Laravel 12 sample uses request()?->fullUrl() and request()?->except() — the nullsafe call on a helper function is a documentation smell that signals console-context paths are under-tested.
  • PII capture is on by default and the redaction is our job. The schema stores request_url, request_method, ip_address, user_agent, user_id, and the README's sample context includes request input with only password fields stripped by hand-written code. Nothing in the package enforces redaction. This needs a written policy and a wrapper logging API before it touches production, especially under GDPR/CCPA-adjacent obligations.

Technical Risk

  • Retention was silently broken until v1.1.11 — treat as the headline risk. The release notes state devlogger:cleanup --days "changed the output and nothing else," and that cleanup() deleted through a model with SoftDeletes, so expired rows were only stamped deleted_at and re-stamped on every run. A retention control that reports success while doing nothing is the worst failure class for a log store: the table grows unbounded while dashboards say otherwise. Mitigation: pin >=1.1.11, and independently verify row counts before/after a run.
  • Packaging churn indicates thin CI. Versions 1.1.5 through 1.1.9 are almost entirely path-resolution, config-publish, and Laravel 12 Schema::connection() signature fixes. Five consecutive patch releases to make vendor:publish and migrations resolve correctly is a signal that the package is not tested against a clean install matrix. Assume we are the integration test.
  • Bus factor ≈ 1. 16 stars, 0 dependents, single maintainer, MIT licensed. There is no community to absorb a breaking Laravel 13 change. Plan for fork-and-own: vendor the source, keep patches in our repo, and accept that we will maintain it.
  • Write-path coupling to the primary database. Default DEVLOGGER_DB_CONNECTION=null means every log write lands on the app's primary connection. Logging inside a transaction that later rolls back takes the log row with it — we lose the record of the very failure we wanted to capture. fallback_channels defaults to null, so a DB outage means logs vanish rather than degrade.

Key Questions

  1. What problem are we solving — error triage, audit history, or user-facing support diagnostics? Each implies a different tool.
  2. Who consumes the logs, and do they read SQL or need a UI? If a UI, we are scoping a build.
  3. Do we have a Sentry/Flare contract? If yes, does this replace or supplement it?
  4. Can we dedicate a separate DB connection for the log table to decouple it from transaction rollback and primary-DB load?
  5. What is our PII redaction policy for input, request_url, and ip_address, and who signs it off?
  6. Are we willing to fork and maintain this if the author stops shipping?

Integration Approach

Stack Fit

  • Confirmed compatible with Laravel 9, 10, 11, 12 on PHP 8.2+. The package's own constraints target ^12.0 on Illuminate while retaining older-version patterns.
  • Requires a relational database with JSON column support — MySQL 5.7+/8, MariaDB 10.2+, or PostgreSQL. Verify the json column and index behavior on our engine before committing; MySQL JSON filtering has different index semantics than Postgres jsonb.
  • No Redis, queue, or external service prerequisite. Queue support is metadata association (onQueue()), not an async write path — logs are written synchronously.

Migration Path

  • Additive and low-blast-radius: one new table (developer_logs), one config file, no changes to existing tables or models. Rollback is php artisan migrate:rollback plus deleting the config and any DevLogger:: call sites.
  • Sequence the cutover as: (1) install and migrate in a staging environment, (2) enable DEVLOGGER_ENABLE_DB=true with DEVLOGGER_AUTO_CATCH=false and manual logging only at a single choke point, (3) run one week of dual-write against the existing channel and reconcile, (4) enable auto-catch, (5) add retention and confirm deletions. Explicitly do not enable auto-catch on day one — the log volume, and the PII surface, becomes immediately real.
  • Set fallback_channels to our existing channel name at step 3; leaving it null is a silent data-loss configuration.
  • If we later exit the package, existing DevLogger:: calls break. Wrap them behind a small internal App\Support\AppLogger facade from day one so the vendor is swappable.

Compatibility

  • Laravel 12 bootstrap/app.php integration differs materially from 9–11 handler extension. The two paths must be validated separately if we run mixed-version applications.
  • Watch the Laravel 12 Schema::connection() stricter signature fixes (v1.1.2, v1.1.3) — confirm migrations run cleanly on our exact minor version, not just "Laravel 12."
  • Multi-tenant and multi-connection apps: the database_connection config is global, not per-tenant. Confirm one table is acceptable before adoption.
  • PHP 8.3+ nullable-parameter deprecations were fixed in 1.1.5; anything below 1.1.11 should be blocked at the Composer constraint level.

Sequencing

  1. Week 1 — Validation spike. Install on a scratch branch, run migrations, verify publish tags resolve on a clean vendor/, load-test ~10k inserts, confirm cleanup actually deletes rows (count before/after, plus OPTIMIZE TABLE).
  2. Week 2 — Governance. Decide redaction policy, retention window, DB connection strategy, and whether a UI is in scope. Lock the Composer constraint to ^1.1.11.
  3. Week 3–4 — Staging. Manual logging behind an internal wrapper; dual-write comparison; measure write latency delta on the hot path.
  4. Week 5 — Production, auto-catch off. Manual logging only, in one service or one module.
  5. Week 6 — Enable auto-catch. Schedule verification that the cleanup command is registered and firing; alert if table row count breaches an expected ceiling.
  6. Post-adoption — Triage layer. Only then assess whether a minimal read-only admin view over DeveloperLog is worth building, or whether SQL access is sufficient.

Operational Impact

Maintenance

  • Low surface area but non-zero ownership. The package owns: a migration, a config file, a model, a facade, one artisan command, and (presumably) a scheduled cleanup registration. Upgrades touch any of these.
  • Assume we will fork. Keep the fork on a branch, rebase on upstream releases, and pin. Budget roughly a few hours per Laravel major upgrade for revalidation, plus ad-hoc patching if upstream goes quiet.
  • The package's own history is the maintenance argument: 11 patch releases where the last three fixed a retention feature that was never deleting data. Every upgrade must be followed by a verification step, not just a composer update.

Support

  • No vendor, no SLA, no paid tier. Support is GitHub issues on a 16-star repo — effectively self-support.
  • Internal support burden lands on whoever owns observability: answering "where do I see this error," running ad-hoc SQL, and managing the status open/closed workflow if teams adopt it.
  • Without a UI, the support experience is "file a ticket and someone runs a query." That is acceptable for an engineering-facing tool and poor for anything customer-support-adjacent. Set expectations accordingly before rollout.

Scaling

  • Write volume is the primary scaling concern. One synchronous INSERT per log event on the app's primary DB. At high error volume (a retry storm or a failing dependency) log writes compound the outage — the classic self-inflicted amplification loop. The package has no sampling, rate limiting, or batching that the documentation describes.
  • Row size: longtext message plus longtext stack trace plus JSON context and JSON tags. Realistically 5–20 KB per exception row. At 50k exceptions/day, that is roughly 250 MB–1 GB/day before indexes. Default 30-day retention implies tens of GB. Plan storage and indexing (level, created_at, status, queue at minimum) explicitly, and confirm the package's shipped indexes match our query patterns.
  • Cleanup at scale: v1.1.11 moved to chunked deletion (1000 rows/statement) precisely because a single unbounded DELETE times out. The release notes also warn that DELETE does not return disk to the OS — a scheduled OPTIMIZE TABLE (or engine-appropriate equivalent) is an operational commitment, not an optimization. On a first run against a table with a soft-delete backlog, expect an unusually large delete; schedule it off-peak.
  • Read-side: ad-hoc Eloquent queries against a large JSON-heavy table will be slow without composite indexes. Budget for a read replica or a separate connection if the triage UI gains traction.

Failure Modes

  • Silent retention failure. The evidenced worst case: cleanup prints a number, deletes nothing. Detection requires an external check — a row-count alert or a cleanupCandidates() assertion in a health check — not trust in the command's output.
  • Log loss on transaction rollback. Writes on the primary connection disappear when the surrounding transaction rolls back. Mitigation: dedicated DEVLOGGER_DB_CONNECTION, or accept the gap knowingly.
  • DB outage takes logging with it. fallback_channels=null by default means logs are dropped exactly when they matter most. Must be configured to an existing Monolog channel.
  • Recursion risk. A logger that throws inside the exception handler can loop. The README claims failed DB writes fall back, but the guard is undocumented and untested here. Verify by simulating a write failure on a hard-down connection.
  • Console/queue context gaps. request_url, request_method, ip_address, user_agent are null in queue workers and scheduled jobs. Queries and UI must tolerate nulls; the README's nullsafe-call pattern on request() suggests this path is lightly exercised upstream.
  • PII leakage. input context and ip_address captured by default with no enforced redaction. A single unredacted payload in a shared log table is a compliance incident, and it survives until retention deletes it — which, per the above, may not happen.

Ramp-up

  • Engineers: under an hour. The facade API (info, error, withTags, onQueue, chaining) mirrors Laravel's Log facade closely enough to be intuitive.
  • Operators/SRE: one to two days. The learning is not the API, it is the failure surface — retention verification, storage growth, fallback behavior, and the cleanup/OPTIMIZE cadence.
  • Support/non-engineering users: effectively blocked without a UI build. Do not promise "you'll be able to look up errors" until that exists.
  • Produce a one-page internal runbook covering: where logs live, how to query them, the retention job and how to verify it, the redaction policy, and the fallback channel. This is the deliverable that makes adoption stick, and it is ours to write, not the package's.
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.
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo