Audit-Ready Activity Logs in Filament (Laravel + Spatie Activitylog)

Categories: Laravel Startups
1 min read

Filament makes it easy to ship a Laravel admin panel fast. But once real teams use it, one question always comes up: "Who changed this, and when?" For startups, that answer protects revenue, speeds support, and reduces compliance risk. This post lays out a pragmatic approach using Laravel, Filament, and the Spatie Activitylog package so your admin actions are accountable, readable, and safe. I'm a freelance Laravel developer working with teams in Bath, Bristol, and Wiltshire - if you're comparing options, see my Laravel development page.

Why Audit Logs Matter for Startups

Audit logs turn "I think" into "I know." When a customer disputes a change, a support ticket escalates, or an investor asks how you protect data, you need a clear timeline. For early-stage teams in Bath, Bristol, and Wiltshire, an audit log is a lightweight way to build trust without slowing delivery.

Start With the Right Scope

The quickest way to wreck an activity log is to log everything. Start small and focus on events that matter:

  • State changes: status changes, role updates, approvals, cancellations.
  • Money or access: anything that affects billing, permissions, or critical data.
  • Admin-only actions: changes a customer would never do themselves.

Avoid logging low-value events like list filters, navigation, or non-mutating actions. The goal is clarity, not noise.

Use Spatie Activitylog at the Model Level

Spatie's Laravel Activitylog package is a great fit for Laravel apps because it stays close to Eloquent. You can attach logging to key models and capture the important fields only.

use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;

class Invoice extends Model
{
    use LogsActivity;

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logOnly(['status', 'total', 'due_date'])
            ->logOnlyDirty()
            ->dontSubmitEmptyLogs();
    }
}

This keeps your log focused and avoids full model snapshots. If a field is sensitive, exclude it here rather than hoping it never leaks later.

Log Filament Actions Explicitly

Filament actions are a perfect place to add explicit log events because you already know the intent. After the action runs, record the event in a human-readable format.

Actions\Action::make('approve')
    ->action(function (Invoice $record) {
        $record->approve();

        activity()
            ->causedBy(auth()->user())
            ->performedOn($record)
            ->log('invoice.approved');
    });

This is where Filament and Spatie work nicely together: Filament gives you the UX and action points; Spatie gives you the audit trail.

Make Events Readable for Humans

Your support team should be able to read the log without decoding it. Keep event names short, stable, and descriptive, and include the important context.

activity()
    ->causedBy(auth()->user())
    ->performedOn($invoice)
    ->withProperties([
        'from' => $oldStatus,
        'to' => $newStatus,
    ])
    ->log('invoice.status.changed');

The point is to answer "what happened" in one scan: who did it, what changed, and why it matters.

Protect Integrity and Privacy

"Audit-ready" means tamper-resistant. Treat logs as append-only, restrict who can view them, and avoid logging secrets or tokens. If you need to capture sensitive fields, record hashes or masked values instead of raw data.

Performance and Retention

Activity logs are write-heavy. Keep them cheap:

Surface Logs Inside Filament

Filament makes it easy to add a dedicated Activity Log resource. Give your team filters by model, user, and date, and add a clean "timeline" view for critical entities. If the log isn't accessible, it won't be used.

Common Questions

What should an audit log capture?

Who did what, when, and which record was affected. Focus on state changes (status updates, approvals), actions that affect money or access, and admin-only operations. Avoid logging low-value events like navigation or list filters - the goal is clarity, not noise.

Where should logging happen?

At the model or domain layer to avoid UI-only gaps. Spatie Activitylog attaches logging to Eloquent models, so changes are captured regardless of where they originate. For Filament actions, add explicit log events after the action runs.

How do you keep logs performant?

Use retention policies, indexing, and clear event scopes. Queue log writes for heavy or bulk actions, index by subject and date so admin filters stay fast, and set a retention policy to archive older records. Log what matters, not everything.

The Bottom Line

Filament helps you ship a Laravel admin quickly, but accountability still matters. Spatie Activitylog gives you a lightweight, proven foundation for audit logs that scale with your product. If you're building a Laravel admin for a startup and want this implemented cleanly, let's talk.

Ben Lumley StackOverflow Github Linkedin

Related posts