obelaw/trail
Obelaw Trail
Activity trail/audit log for Eloquent models. Captures model changes and request context, supports optional queueing, and includes a prune command.
Features
- Observes model events: created, updated, deleted, restored, forceDeleted
- Stores attribute changes and optional snapshot
- Captures request context: IP, user agent, method, URL, guard, request ID
- Masks sensitive fields by default: password, token, secret
- Optional queueing for non-blocking writes
- Artisan command to prune old records
Installation
Publish config and migrations, then migrate:
php artisan vendor:publish --tag=trail-config
php artisan vendor:publish --tag=trail-migrations
php artisan migrate
Middleware is auto-registered to the web and api groups to capture request context. An alias trail.capture is also available if you want to apply it manually.
Configuration
config/trail.php keys:
connection: database connection (null = default)table: table name (default: trails)events: model events to observeignore_attributes: attributes to ignore when computing diffs (e.g. updated_at)redact_attributes: attributes to mask in logs (password, token, secret)store_snapshot: whether to store a full snapshotqueue: write via queue job when truebroadcast: fire TrailRecorded event after saveretention_days: default prune retentionwatch: optional list of model classes to auto-observe
Usage
Attach to models via trait or config:
- Use the
TracksTrailtrait on your Eloquent model; or - Add model classes to
trail.watchin config.
Manual logging via facade/builder:
use Obelaw\Trail\Facades\Trail;
Trail::for($model)
->event('custom')
->changes(['name' => ['old' => 'A', 'new' => 'B']])
->snapshot($model->toArray())
->save();
Request context (IP, user agent, URL, method, guard, request ID) is captured automatically by the middleware.
Querying
use Obelaw\Trail\Models\Trail as TrailModel;
// All trails for a model
TrailModel::forTrailed($model->getMorphClass(), $model->getKey())->get();
// Filter by event
TrailModel::event('updated')->get();
Pruning
Run manually with a custom retention:
php artisan trail:prune --days=180
Or schedule daily using the value from retention_days:
$schedule->command('trail:prune')->daily();
Related Packages
Powerful PHP database abstraction layer (DBAL) with many features for database s...
Laravel Serializable Closure provides an easy and secure way to serialize closur...
Cli error handling for console/command-line PHP applications.