juststeveking/eloquent-log-driver
A Laravel logging driver that stores your application logs in the database through Eloquent, letting you query, filter, and manage log entries like any other model instead of writing them to flat files.
What we are actually evaluating. Stripping the framing, juststeveking/eloquent-log-driver is a Monolog handler, a LogManager extension via a service provider, a publishable config stub, a migration, and an Eloquent model. It converts Log::info(...) into an INSERT against a logs table. There is no viewer, no retention job, no redaction, no alerting, no search index, and no access control. As a TPM the thing to decide is not "do we install this package" but "do we want queryable in-app logs as a capability, and who owns the roughly 150 lines that deliver it."
Architecture fit. The design is idiomatic and correctly scoped: it extends Laravel at the sanctioned seam — a custom channel registered through the logging manager — rather than monkey-patching the Log facade. Blast radius is confined to the channels we explicitly route through it, which is why the pattern is worth copying even where the code is not. The architectural consequence I have to own as TPM is that it relocates logging onto the primary application database's write path: same connection, same CPU, same disk, same failure domain as the business data. That is defensible for low-volume, single-tenant, queryable application events (failed webhook deliveries, payment-provider callbacks, auth anomalies, scheduled-command outcomes). It is indefensible for high-throughput APIs, multi-service estates, or any system where the database is already the contended resource.
Integration feasibility. High for a mid-level Laravel engineer — a handful of artisan commands, a migration, and a config/logging.php entry; readable end to end in under an hour. Low as a dependency decision. That distinction is the whole assessment: engineering effort is trivial, lifecycle exposure is not.
Technical risk — the package fails on lifecycle, not on design.
write(array $record); Monolog 3 (Laravel 9+) expects write(LogRecord $record): void. Highest-probability outcome on a current stack is a hard failure at channel instantiation or first write. Verify in a spike; do not plan around it working.context column accumulates unbounded and will capture request payloads, headers, tokens, and user identifiers unless we intervene.Key questions to answer before any commitment.
Stack fit. Appropriate for a Laravel monolith or a small worker fleet where support and ops need to SELECT logs from inside the product — an admin log viewer, per-tenant debugging, a "recent activity" panel — without procuring an observability vendor. Not appropriate where we already ship to stdout with Loki/ELK/CloudWatch, where the database is shared and contended, or where throughput makes write amplification a real line item.
Migration path — the recommended sequence, and the product framing behind it.
Compatibility. Pin Laravel and Monolog constraints explicitly. Add the channel to CI smoke tests so a framework upgrade that breaks the handler fails the build rather than silently stopping logging in production. Silent drift is the worst failure mode here, because nothing alerts on "we stopped receiving logs."
Sequencing.
channel, level, created_at — not message/context) before production; use a dedicated database connection if the primary is contended.Maintenance. Upstream is dormant, so ownership transfers to us on day one whichever path we take. Budget 2–4 engineer-days per year for framework and Monolog compatibility, plus 1–2 days of initial build. That is the dominant lifecycle cost and it buys nothing differentiating: the low opportunity score correctly reads a database log sink as table-stakes plumbing, not a product lever. The offsetting value is real but bounded — it defers or avoids a log-aggregation SaaS contract for low-volume internal apps and unblocks support tooling that would otherwise wait on a vendor procurement cycle.
Support. No upstream support channel, no SLA, no issue-triage expectation. Internal support burden is whatever we design in: an escalation path for "logs aren't showing up," documented retention and access policy, and a named owner. Because the capability is user-visible (support staff will use the log viewer), the support surface is larger than the code size suggests.
Scaling. Single-node, synchronous, row-per-record. Table growth is linear in log volume with no partitioning strategy; query performance degrades as the table grows unless indexes are curated and pruning is automated. At high write rates the handler competes with business queries for connections and I/O, and connection-pool exhaustion under a logging storm is a realistic secondary failure. Plan for a dedicated connection and a pruning window before volume becomes a problem rather than after.
Failure modes. In rough order of likelihood and severity: (1) silent log loss after a framework upgrade breaks the handler — no alert fires; (2) database outage causing logging to throw and cascade, masking the original incident; (3) unbounded table growth degrading both logging and application queries; (4) PII accumulation in the context column creating a compliance exposure discovered during an audit; (5) latency regression at p99 under load, attributed late because logging is rarely the first suspect.
Ramp-up. Trivial for anyone who knows Laravel's logging configuration — under an hour to understand the component. The non-trivial ramp is organizational: establishing the retention/redaction policy, the on-call story for log pipeline failures, and the discipline to keep stdout primary. Treating this as a secondary channel with a documented fallback is what keeps the operational blast radius contained.
How can I help you explore Laravel packages today?