Activity Log
Audits who changed what across Volāre models using spatie/laravel-activitylog (v5), with an attribute-driven per-model configuration, a Filament viewer, and an Artisan health check.
When to Use
Section titled “When to Use”- Trace who changed a record and what the before/after values were
- Decide whether a new model should be activity-logged or excluded
- Audit non-model events (impersonation, flight searches, product duplication)
What Gets Logged
Section titled “What Gets Logged”Models opt in with the #[ActivityLog] attribute plus the ConfiguresActivityLog trait (which wraps Spatie’s LogsActivity). Around 87 models are configured this way.
Defaults on the attribute are audit-friendly (since #2164):
- Only changed attributes are recorded (
logOnlyDirty) — an update stores just the dirty fields, with the diff in Spatie v5’sattribute_changescolumn. - No-op saves are skipped (
dontLogEmptyChanges). - Both are overridable per model via the attribute’s parameters (
logName,logFillable,submitEmptyLogs,logAttributes,logOnlyDirty,dontLogAttributes).
A PHPStan rule (backend/phpstan/Rules/RequireActivityLogOnModelsRule.php) enforces that every Eloquent model is either configured or explicitly listed as excluded, so logging can’t be forgotten silently.
Besides model events, a few flows write custom entries via the activity() helper with their own log names: impersonation (UserImpersonation), flight-searches (CascadeFlightSearchForDateJob, FlightSearchActivityLogger), product-duplication (ProductDuplicationService), and ai_tour_parser (TCAI tour parsing).
What Is Deliberately Excluded
Section titled “What Is Deliberately Excluded”High-volume machine-churn models were removed from logging in #2162 to control table bloat — their state lives in their own tables and no consumer read it from the log (a PipedriveSync retry loop alone was the largest share of the table):
PipedriveSync,CurrencyExchangeRate,OfferFlight,OfferFlightBinding,OfferPriceSnapshot,ProductByMarketFlightLeg
Also excluded (cache/metrics/transient data): BudgetEntry, ProductSlugAlias, DynamicFlightCache, DynamicFlightCacheRoute, DynamicFlightCacheSegment, DynamicFlightProvider, DynamicFlightRefreshSchedule, FlightSearchResult, L2bMetric.
The full exclusion list is RequireActivityLogOnModelsRule::EXCLUDED_MODELS.
Viewer Page
Section titled “Viewer Page”ActivityLogs (System → Activity Logs, admin-only) lists all entries with:
- Filters for event (built dynamically so custom events are filterable), subject type, user, and date range
- A slide-over detail view showing a side-by-side before/after diff for updates, initial values for creates, and last-held values for deletes. The diff is read from the v5
attribute_changescolumn with a fallback topropertiesso pre-v5 rows and custom diff logs still render - A Go to Element link that resolves the subject’s Filament edit page when one exists
Source: backend/app/Filament/Pages/ActivityLogs.php
Health Check Command
Section titled “Health Check Command”vendor/bin/sail artisan activity-log:check [--json]Scans every class in app/Models and reports three buckets: configured (attribute + trait), misconfigured (attribute without the ConfiguresActivityLog trait — exits non-zero), and not configured. Use -v to list unconfigured models.
Source: backend/app/Console/Commands/ActivityLogCheckCommand.php
Configuration
Section titled “Configuration”Config file: backend/config/activitylog.php
enabled— kill switch (ACTIVITYLOG_ENABLED, defaults to true)clean_after_days— 365-day retention used by Spatie’sactivitylog:cleancommand. Note: the command is not scheduled; the automatic prune was dropped from #2162 as too risky to run on deploy, so historical cleanup is a manual operation.
Related
Section titled “Related”- Health Monitoring
- Source:
backend/app/Attributes/ActivityLog.php - Source:
backend/app/Traits/ConfiguresActivityLog.php