faisallbhr / laravel-tracelog
Trace Eloquent model changes without writing debug logs one by one.
Requires
- php: ^8.2
- illuminate/database: ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^11.0 || ^12.0 || ^13.0
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0 || ^10.0 || ^11.0
- phpunit/phpunit: ^11.5 || ^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Trace Eloquent model changes without writing debug logs one by one.
Debugging model changes often means logging a few attributes, repeating the
request, and starting over when one was missed. TraceLog captures the relevant
changes for created, updated, deleted, restored, and forceDeleted
events in one structured debug log, including the application source that
triggered the event.
Requirements
- PHP 8.2 or later (Laravel 13 requires PHP 8.3 or later)
- Laravel 11, 12, or 13
Laravel 11 is tested for legacy compatibility but no longer receives upstream security fixes. Prefer Laravel 12 or later for production.
Installation
Install TraceLog as a development dependency:
composer require --dev faisallbhr/laravel-tracelog
Laravel discovers the service provider and facade automatically. No config file or manual provider registration is required.
Usage
Call watch() before the model operation you want to inspect.
Watch every model
use TraceLog\Facades\TraceLog; TraceLog::watch(); $order->update([ 'status' => 'paid', ]);
Watch a model class
Every instance of the given model class will be traced:
use App\Models\Order; use TraceLog\Facades\TraceLog; TraceLog::watch(Order::class);
Watch one record
Pass a persisted model to trace only that record:
use App\Models\Order; use TraceLog\Facades\TraceLog; $order = Order::findOrFail(123); TraceLog::watch($order);
When watching a specific model instance, it must already be persisted and have a record key.
Filter attributes
Use only() to allow selected attributes and except() to remove attributes.
When combined, except() takes precedence:
TraceLog::watch(Order::class) ->only(['status', 'total', 'updated_at']) ->except(['updated_at']);
An empty only([]) allows no attributes, while an empty except([]) excludes
nothing. An updated event is not logged when filtering removes all of its
changes.
Filter events
Select events using the existing ModelEvent enum:
use TraceLog\Enums\ModelEvent; TraceLog::watch(Order::class)->events([ ModelEvent::Updated, ModelEvent::Deleted, ]);
All supported events are enabled by default. Passing events([]) disables
logging for that watch.
Protect sensitive attributes
TraceLog always redacts password, password_confirmation, remember_token,
api_token, access_token, refresh_token, secret, secret_key, and
private_key. Matching is case-insensitive, including when an attribute is
explicitly selected with only().
Add application-specific sensitive attributes with sensitive():
TraceLog::watch(User::class) ->sensitive(['pin', 'security_answer']);
Both old and new values are written as [REDACTED].
Multiple watches
When multiple watches match a model, the most specific configuration wins: record, model class, then global. Registering the same scope again replaces its previous filtering configuration.
Always trace a model
Add the Traceable trait when a model should always be traced without calling
watch():
namespace App\Models; use Illuminate\Database\Eloquent\Model; use TraceLog\Concerns\Traceable; class Order extends Model { use Traceable; }
Stop tracing
Clear all watches registered in the current application scope:
TraceLog::stop();
stop() does not disable models using the Traceable trait.
Stable API
The supported public API consists of:
TraceLog::watch(),TraceLog::stop(), andTraceLog::isWatching()only(),except(),events(), andsensitive()on a watch configuration- the
ModelEventenum - the
Traceabletrait
Classes under the TraceLog\Internal namespace are implementation details and
are not part of the supported public API.
Log output
TraceLog writes at the debug level through Laravel's default log channel, so
the destination follows your application's logging configuration.
An update produces a structured entry like this:
[2026-11-10 13:57:06] local.DEBUG: {
"event": "updated",
"model": "App\\Models\\Order",
"id": 123,
"changes": {
"status": {
"old": "draft",
"new": "paid"
}
},
"source": "/path/to/app/Http/Controllers/OrderController.php:42"
}
Laravel emits companion events for soft-delete operations. By default,
restore() logs both updated and restored, while forceDelete() logs both
deleted and forceDeleted. Use events() when only the specific lifecycle
event is needed.
Important
Keep TraceLog as a development dependency. Default redaction protects common
credential names, but application-specific sensitive attributes must be added
with sensitive().
Mass updates performed through an Eloquent query do not dispatch model events and therefore are not traced:
Order::query()->update(['status' => 'paid']);
License
Laravel TraceLog is open-source software licensed under the MIT license.