PHPackages                             campelo/laravel-audit-log - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. campelo/laravel-audit-log

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

campelo/laravel-audit-log
=========================

Automatic audit logging for Laravel applications - track who, when, where, what changed

v1.3.0(3mo ago)00MITPHPPHP ^8.1

Since Feb 13Pushed 3mo agoCompare

[ Source](https://github.com/campeloneto1/laravel-audit-log)[ Packagist](https://packagist.org/packages/campelo/laravel-audit-log)[ RSS](/packages/campelo-laravel-audit-log/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (5)Versions (5)Used By (0)

Laravel Audit Log
=================

[](#laravel-audit-log)

Automatic audit logging for Laravel applications. Track who did what, when, where, and what changed.

Features
--------

[](#features)

- **Automatic Request Logging** - Middleware logs all HTTP requests (POST, PUT, PATCH, DELETE by default)
- **Model Event Logging** - Trait to automatically log model changes (created, updated, deleted)
- **Error Logging** - Capture and log exceptions and errors (4xx, 5xx) with stack traces
- **Performance Logging** - Track slow database queries and slow HTTP requests
- **Rollback** - Revert model changes based on audit log history
- **Detailed Information** - Captures user, IP, user agent, URL, method, table, old/new values
- **Built-in API** - Query audit logs with filters via REST API
- **Sensitive Data Protection** - Automatically redacts passwords and sensitive fields
- **Queue Support** - Offload logging to queues for better performance
- **Customizable** - Configure which methods, routes, events, and error types to log
- **Notifications** - Send email/Slack alerts when critical errors occur

Installation
------------

[](#installation)

```
composer require campelo/laravel-audit-log
```

Publish the config and migrations:

```
php artisan vendor:publish --tag=audit-log-config
php artisan vendor:publish --tag=audit-log-migrations
php artisan migrate
```

Quick Start
-----------

[](#quick-start)

### 1. Automatic Request Logging

[](#1-automatic-request-logging)

The middleware is automatically registered. All POST, PUT, PATCH, DELETE requests will be logged.

```
// config/audit-log.php
'log_methods' => [
    'POST',
    'PUT',
    'PATCH',
    'DELETE',
    // 'GET', // Uncomment to also log read operations
],
```

### 2. Model Event Logging

[](#2-model-event-logging)

Add the `Auditable` trait to your models:

```
use Campelo\AuditLog\Traits\Auditable;

class User extends Model
{
    use Auditable;

    // Optional: exclude sensitive fields
    protected array $auditExclude = ['password', 'remember_token'];

    // Optional: only include specific fields
    protected array $auditInclude = ['name', 'email', 'role'];
}
```

### 3. Manual Logging

[](#3-manual-logging)

```
use Campelo\AuditLog\Facades\AuditLog;

// Log a custom event
AuditLog::log(
    event: 'user_promoted',
    model: $user,
    oldValues: ['role' => 'user'],
    newValues: ['role' => 'admin'],
    description: 'User was promoted to admin'
);
```

### 4. Error Logging

[](#4-error-logging)

Automatically log all exceptions and errors that occur in your application.

**Step 1: Configure in your `.env`:**

```
AUDIT_LOG_ERRORS_ENABLED=true
AUDIT_LOG_ERRORS_4XX=false   # Log client errors (400-499)
AUDIT_LOG_ERRORS_5XX=true    # Log server errors (500-599)
```

**Step 2: Integrate with your Exception Handler:**

```
// app/Exceptions/Handler.php

use Campelo\AuditLog\Exceptions\AuditLogExceptionHandler;

class Handler extends ExceptionHandler
{
    use AuditLogExceptionHandler;

    public function register(): void
    {
        $this->reportable(function (Throwable $e) {
            $this->auditLogException($e);
        });
    }
}
```

**Manual error logging:**

```
use Campelo\AuditLog\Facades\AuditLog;

try {
    // Some operation that might fail
    $this->processPayment($order);
} catch (PaymentException $e) {
    // Log the error with additional context
    AuditLog::logError($e, request(), [
        'order_id' => $order->id,
        'amount' => $order->total,
    ]);

    throw $e;
}
```

API Endpoints
-------------

[](#api-endpoints)

The package provides built-in API endpoints to query audit logs:

### List Audit Logs

[](#list-audit-logs)

```
GET /api/audit-logs

```

**Query Parameters:**

ParameterDescriptionExample`user_id`Filter by user ID`?user_id=1``event`Filter by event type`?event=updated` or `?event=error``events`Multiple events (comma-separated)`?events=created,updated``table`Filter by table name`?table=users``model`Filter by model class`?model=App\Models\User``model_id`Filter by model ID (requires model)`?model=App\Models\User&model_id=1``method`Filter by HTTP method`?method=POST``ip`Filter by IP address`?ip=192.168.1.1``route`Filter by route name`?route=users.update``response_code`Filter by HTTP response code`?response_code=500``date_from`Filter from date`?date_from=2024-01-01``date_to`Filter to date`?date_to=2024-12-31``search`Search in description, URL, user name/email`?search=john``per_page`Items per page (max 100)`?per_page=50``sort`Sort field`?sort=performed_at`**Examples:**

```
# Get all error logs
GET /api/audit-logs?event=error

# Get only server errors (500)
GET /api/audit-logs?event=error&response_code=500

# Get errors from today
GET /api/audit-logs?event=error&date_from=2024-01-15

# Get all CRUD operations (exclude errors)
GET /api/audit-logs?events=created,updated,deleted
```

| `order` | Sort order (asc/desc) | `?order=desc` |

### Get Single Entry

[](#get-single-entry)

```
GET /api/audit-logs/{id}

```

### Get Logs for Model

[](#get-logs-for-model)

```
GET /api/audit-logs/model/{model}/{id}
GET /api/audit-logs/model/App%5CModels%5CUser/1

```

### Get Logs for User

[](#get-logs-for-user)

```
GET /api/audit-logs/user/{userId}

```

### Get Statistics

[](#get-statistics)

```
GET /api/audit-logs/stats
GET /api/audit-logs/stats?date_from=2024-01-01&date_to=2024-01-31

```

Returns:

- Total count
- Count by event type
- Count by table
- Count by HTTP method
- Top 10 users by activity
- Daily activity for last 30 days

### Get Filter Options

[](#get-filter-options)

```
GET /api/audit-logs/filters

```

Returns available values for events, tables, methods, and users.

### Cleanup Old Logs

[](#cleanup-old-logs)

```
DELETE /api/audit-logs/cleanup?days=365

```

Automatic Cleanup
-----------------

[](#automatic-cleanup)

The package includes a command to clean up old audit logs based on retention policy.

### Configuration

[](#configuration)

```
# Global retention (days)
AUDIT_LOG_RETENTION_DAYS=365

# Error logs retention (if different from global)
AUDIT_LOG_ERRORS_RETENTION_DAYS=90

# Enable automatic cleanup
AUDIT_LOG_CLEANUP_ENABLED=true
AUDIT_LOG_CLEANUP_SCHEDULE=02:00
```

### Automatic Cleanup (Recommended)

[](#automatic-cleanup-recommended)

Enable automatic cleanup in your `.env`:

```
AUDIT_LOG_CLEANUP_ENABLED=true
AUDIT_LOG_CLEANUP_SCHEDULE=02:00
```

The package will automatically register the cleanup command in Laravel's scheduler. Make sure your server has cron configured:

```
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```

### Manual Cleanup

[](#manual-cleanup)

Run the cleanup command manually:

```
# Clean all logs based on config retention
php artisan audit-log:cleanup

# Preview what would be deleted (dry run)
php artisan audit-log:cleanup --dry-run

# Override retention days
php artisan audit-log:cleanup --days=30

# Different retention for errors
php artisan audit-log:cleanup --days=365 --error-days=30

# Clean only error logs
php artisan audit-log:cleanup --type=errors

# Clean only operation logs (exclude errors)
php artisan audit-log:cleanup --type=operations
```

### Manual Scheduler Registration

[](#manual-scheduler-registration)

If you prefer to register the command manually in your `app/Console/Kernel.php`:

```
protected function schedule(Schedule $schedule): void
{
    // Daily cleanup at 2 AM
    $schedule->command('audit-log:cleanup')->dailyAt('02:00');

    // Or weekly on Sunday
    $schedule->command('audit-log:cleanup')->weeklyOn(0, '03:00');

    // With custom retention
    $schedule->command('audit-log:cleanup --days=90 --error-days=30')->daily();
}
```

Notifications
-------------

[](#notifications)

Get notified via Email and/or Slack when critical errors (5xx) occur.

### Configuration

[](#configuration-1)

```
# Enable notifications
AUDIT_LOG_NOTIFICATIONS_ENABLED=true

# Choose channels: mail, slack, or both
AUDIT_LOG_NOTIFY_CHANNELS=mail          # Only email
AUDIT_LOG_NOTIFY_CHANNELS=slack         # Only Slack
AUDIT_LOG_NOTIFY_CHANNELS=mail,slack    # Both

# Email recipient (uses Laravel's mail config)
AUDIT_LOG_NOTIFY_EMAIL=admin@example.com

# Slack webhook URL
AUDIT_LOG_SLACK_WEBHOOK=https://hooks.slack.com/services/xxx/yyy/zzz
```

### Requirements

[](#requirements)

- **Email**: Uses Laravel's built-in mail configuration (`config/mail.php`)
- **Slack**: Requires the Slack notification channel package:

```
composer require laravel/slack-notification-channel
```

### Throttling

[](#throttling)

To prevent notification spam, the package throttles repeated errors:

- Same error (same exception class + file + line) will only notify 5 times per hour
- Configurable in `config/audit-log.php`:

```
'notifications' => [
    'throttle' => [
        'enabled' => true,
        'max_notifications' => 5,   // Max notifications per error type
        'decay_minutes' => 60,      // Time window
    ],
],
```

### Which errors trigger notifications

[](#which-errors-trigger-notifications)

By default, only server errors (5xx) trigger notifications. You can customize via `.env`:

```
# Default: 500,501,502,503,504
AUDIT_LOG_NOTIFY_ON_CODES=500,502,503

# Include all server errors
AUDIT_LOG_NOTIFY_ON_CODES=500,501,502,503,504,505,506,507,508,510,511

# Include some client errors too
AUDIT_LOG_NOTIFY_ON_CODES=401,403,500,502,503
```

Or in config file:

```
'notifications' => [
    'notify_on_codes' => [500, 501, 502, 503, 504],
],
```

Performance Logging
-------------------

[](#performance-logging)

Track slow database queries and slow HTTP requests for performance monitoring.

### Configuration

[](#configuration-2)

```
# Enable performance logging
AUDIT_LOG_PERFORMANCE_ENABLED=true

# Slow query threshold (milliseconds)
AUDIT_LOG_SLOW_QUERY_THRESHOLD=1000

# Include query bindings in logs
AUDIT_LOG_SLOW_QUERY_BINDINGS=true

# Slow request threshold (milliseconds)
AUDIT_LOG_SLOW_REQUEST_THRESHOLD=2000
```

### Querying Performance Logs

[](#querying-performance-logs)

```
use Campelo\AuditLog\Models\AuditLog;

// Get all slow queries
$slowQueries = AuditLog::slowQueries()->get();

// Get all slow requests
$slowRequests = AuditLog::slowRequests()->get();

// Get all performance logs
$performance = AuditLog::performance()->get();

// Filter by duration (in metadata)
$verySlowQueries = AuditLog::slowQueries()
    ->whereRaw("JSON_EXTRACT(metadata, '$.execution_time_ms') > 5000")
    ->get();
```

### API Endpoints

[](#api-endpoints-1)

```
# Get slow query logs
GET /api/audit-logs?event=slow_query

# Get slow request logs
GET /api/audit-logs?event=slow_request

# Get all performance logs
GET /api/audit-logs?events=slow_query,slow_request
```

### Response Format

[](#response-format)

**Slow Query:**

```
{
    "id": 100,
    "event": "slow_query",
    "performed_at": "2024-01-15T10:30:00+00:00",
    "description": "Slow query (1523.45 ms): SELECT * FROM orders WHERE...",
    "metadata": {
        "query": "SELECT * FROM orders WHERE status = ? AND created_at > ?",
        "execution_time_ms": 1523.45,
        "connection": "mysql",
        "bindings": ["pending", "2024-01-01"]
    }
}
```

**Slow Request:**

```
{
    "id": 101,
    "event": "slow_request",
    "performed_at": "2024-01-15T10:31:00+00:00",
    "description": "Slow request (3245.67 ms): GET /api/reports/sales",
    "metadata": {
        "duration_ms": 3245.67,
        "memory_usage_bytes": 52428800,
        "memory_usage_mb": 50.0,
        "peak_memory_bytes": 67108864,
        "peak_memory_mb": 64.0
    }
}
```

Rollback
--------

[](#rollback)

Revert model changes based on audit log history. Only authorized users can perform rollback.

### Configuration

[](#configuration-3)

```
# Enable rollback feature
AUDIT_LOG_ROLLBACK_ENABLED=true

# User IDs authorized to perform rollback (comma-separated)
AUDIT_LOG_ROLLBACK_ALLOWED_USERS=1,5,10

# Maximum chain length for rollback (0 = unlimited)
AUDIT_LOG_ROLLBACK_MAX_CHAIN=10
```

### Basic Rollback

[](#basic-rollback)

```
use Campelo\AuditLog\Facades\AuditLog;
use Campelo\AuditLog\Models\AuditLog as AuditLogModel;

// Rollback by audit log ID
$rollbackLog = AuditLog::rollback($auditLogId);

// Check if rollback is possible
$result = AuditLog::canRollback($auditLogId);
// Returns: ['can_rollback' => true/false, 'reason' => '...']

// Rollback via model instance
$auditLog = AuditLogModel::find($id);
$rollbackLog = $auditLog->rollback();
```

### Rollback from Model

[](#rollback-from-model)

```
// Rollback to a specific audit log
$user->rollbackTo($auditLogId);

// Rollback to previous state
$user->rollbackToPrevious();
```

### Rollback Chain (Multiple Undos)

[](#rollback-chain-multiple-undos)

```
// Rollback the last 3 changes
$rollbackLogs = AuditLog::rollbackChain($auditLogId, steps: 3);
```

### API Endpoints

[](#api-endpoints-2)

```
# Check if rollback is possible
GET /api/audit-logs/{id}/can-rollback

# Response
{
    "can_rollback": true,
    "reason": null
}

# Perform rollback
POST /api/audit-logs/{id}/rollback

# Response
{
    "success": true,
    "message": "Rollback completed successfully.",
    "rollback_log": { ... }
}

# Rollback chain
POST /api/audit-logs/rollback-chain/{id}
Body: { "steps": 3 }

# Response
{
    "success": true,
    "message": "Rolled back 3 changes.",
    "rollback_logs": [...]
}
```

### Rollback Events

[](#rollback-events)

Each rollback creates a new audit log with event `rollback`:

```
{
    "id": 150,
    "event": "rollback",
    "description": "Rolled back updated on User #1 (from audit log #42)",
    "old_values": { "name": "New Name" },
    "new_values": { "name": "Original Name" },
    "metadata": {
        "rolled_back_audit_log_id": 42,
        "rolled_back_event": "updated",
        "rolled_back_at": "2024-01-15T10:00:00+00:00"
    }
}
```

### Querying Rollbacks

[](#querying-rollbacks)

```
// Get all rollback events
$rollbacks = AuditLog::rollbacks()->get();

// Get rollbackable events only
$rollbackable = AuditLog::rollbackable()->get();

// Check if an audit log was rolled back
$auditLog = AuditLogModel::find($id);
if ($auditLog->isRolledBack()) {
    $rollbackLog = $auditLog->getRollbackLog();
}
```

### Limitations

[](#limitations)

- **created**: Rollback deletes the model
- **updated**: Rollback restores old values
- **deleted**: Rollback restores soft-deleted models or recreates with old\_values
- Cannot rollback events without `old_values` (e.g., if not stored)
- Cannot rollback non-model events (e.g., `error`, `slow_query`)
- Each audit log can only be rolled back once

Query Using Model
-----------------

[](#query-using-model)

```
use Campelo\AuditLog\Models\AuditLog;

// Get all logs for a model
$logs = AuditLog::forModel($user)->get();

// Get logs for a specific user
$logs = AuditLog::byUser($user)->get();

// Get logs for a specific event
$logs = AuditLog::event('updated')->get();

// Get logs for a table
$logs = AuditLog::forTable('users')->get();

// Get logs between dates
$logs = AuditLog::between('2024-01-01', '2024-01-31')->get();

// Get logs from IP
$logs = AuditLog::fromIp('192.168.1.1')->get();

// Get only write operations
$logs = AuditLog::writeOperations()->get();

// Combine scopes
$logs = AuditLog::byUser($user)
    ->event(['created', 'updated'])
    ->between($startDate, $endDate)
    ->get();
```

Query Examples
--------------

[](#query-examples)

### Normal Operation Logs (CRUD)

[](#normal-operation-logs-crud)

```
use Campelo\AuditLog\Models\AuditLog;

// All create operations
$created = AuditLog::event('created')->latest('performed_at')->get();

// All update operations for a specific table
$userUpdates = AuditLog::event('updated')
    ->forTable('users')
    ->get();

// All delete operations by a specific user
$deletedByAdmin = AuditLog::event('deleted')
    ->byUser($adminId)
    ->get();

// All write operations (POST, PUT, PATCH, DELETE) today
$todayWrites = AuditLog::writeOperations()
    ->whereDate('performed_at', today())
    ->get();

// All read operations (GET) - if enabled in config
$reads = AuditLog::readOperations()->get();

// History of a specific record
$orderHistory = AuditLog::forModel(Order::class, $orderId)
    ->oldest('performed_at')
    ->get();

// Activity by user in a date range
$userActivity = AuditLog::byUser($userId)
    ->between('2024-01-01', '2024-01-31')
    ->get();
```

### Error Logs

[](#error-logs)

```
use Campelo\AuditLog\Models\AuditLog;

// All errors
$allErrors = AuditLog::errors()->latest('performed_at')->get();

// Only server errors (500-599)
$serverErrors = AuditLog::serverErrors()->get();

// Only client errors (400-499)
$clientErrors = AuditLog::clientErrors()->get();

// Errors by response code
$notFound = AuditLog::errors()->responseCode(404)->get();
$forbidden = AuditLog::errors()->responseCode(403)->get();

// Errors in a specific route
$apiErrors = AuditLog::errors()
    ->where('url', 'like', '%/api/payments%')
    ->get();

// Errors by a specific user
$userErrors = AuditLog::errors()
    ->byUser($userId)
    ->get();

// Recent errors (last 24 hours)
$recentErrors = AuditLog::errors()
    ->where('performed_at', '>=', now()->subDay())
    ->get();

// Errors with specific exception class
$paymentErrors = AuditLog::errors()
    ->whereJsonContains('metadata->exception_class', 'App\\Exceptions\\PaymentException')
    ->get();

// Error statistics by day
$errorsByDay = AuditLog::errors()
    ->selectRaw('DATE(performed_at) as date, COUNT(*) as count')
    ->groupBy('date')
    ->orderBy('date', 'desc')
    ->get();

// Top error types
$topErrors = AuditLog::errors()
    ->selectRaw("JSON_EXTRACT(metadata, '$.exception_class') as exception, COUNT(*) as count")
    ->groupBy('exception')
    ->orderBy('count', 'desc')
    ->limit(10)
    ->get();
```

### Combined Queries

[](#combined-queries)

```
// All activity (normal + errors) by a user
$allActivity = AuditLog::byUser($userId)
    ->latest('performed_at')
    ->get();

// Separate normal logs from errors
$normalLogs = AuditLog::where('event', '!=', 'error')->get();
$errorLogs = AuditLog::errors()->get();

// Dashboard statistics
$stats = [
    'total_operations' => AuditLog::where('event', '!=', 'error')->count(),
    'total_errors' => AuditLog::errors()->count(),
    'server_errors' => AuditLog::serverErrors()->count(),
    'client_errors' => AuditLog::clientErrors()->count(),
    'creates_today' => AuditLog::event('created')->whereDate('performed_at', today())->count(),
    'updates_today' => AuditLog::event('updated')->whereDate('performed_at', today())->count(),
    'deletes_today' => AuditLog::event('deleted')->whereDate('performed_at', today())->count(),
    'errors_today' => AuditLog::errors()->whereDate('performed_at', today())->count(),
];
```

Accessing Audit Logs from Models
--------------------------------

[](#accessing-audit-logs-from-models)

```
// Get all audit logs
$user->auditLogs;

// Get last audit log
$user->lastAuditLog();

// Get logs for specific event
$user->getAuditLogsForEvent('updated');
```

Configuration
-------------

[](#configuration-4)

```
// config/audit-log.php

return [
    // Enable/disable globally
    'enabled' => env('AUDIT_LOG_ENABLED', true),

    // Database connection (null = default)
    'connection' => null,

    // Table name
    'table' => 'audit_logs',

    // HTTP methods to log
    'log_methods' => ['POST', 'PUT', 'PATCH', 'DELETE'],

    // Model events to log
    'log_events' => ['created', 'updated', 'deleted', 'restored'],

    // Routes to exclude
    'excluded_routes' => [
        'telescope/*',
        'horizon/*',
        '_debugbar/*',
    ],

    // Fields to redact
    'excluded_fields' => [
        'password',
        'password_confirmation',
        'secret',
        'token',
        'api_key',
    ],

    // Queue configuration
    'queue' => [
        'enabled' => env('AUDIT_LOG_QUEUE', false),
        'connection' => 'default',
        'queue' => 'audit-logs',
    ],

    // Data retention (days, null = forever)
    'retention_days' => 365,

    // API routes
    'routes_enabled' => true,
    'route_prefix' => 'api/audit-logs',
    'route_middleware' => ['api', 'auth'],

    // Automatic cleanup
    'cleanup' => [
        'enabled' => env('AUDIT_LOG_CLEANUP_ENABLED', false),
        'schedule' => env('AUDIT_LOG_CLEANUP_SCHEDULE', '02:00'),
    ],

    // Error logging configuration
    'errors' => [
        'enabled' => env('AUDIT_LOG_ERRORS_ENABLED', true),
        'log_4xx' => env('AUDIT_LOG_ERRORS_4XX', false),
        'log_5xx' => env('AUDIT_LOG_ERRORS_5XX', true),
        'log_stack_trace' => true,
        'max_stack_trace_length' => 5000,
        'excluded_exceptions' => [
            \Illuminate\Auth\AuthenticationException::class,
            \Illuminate\Validation\ValidationException::class,
            \Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class,
        ],
        'retention_days' => env('AUDIT_LOG_ERRORS_RETENTION_DAYS', null),
    ],

    // Notifications
    'notifications' => [
        'enabled' => env('AUDIT_LOG_NOTIFICATIONS_ENABLED', false),
        'channels' => explode(',', env('AUDIT_LOG_NOTIFY_CHANNELS', 'mail')),
        'mail' => [
            'to' => env('AUDIT_LOG_NOTIFY_EMAIL', null),
        ],
        'slack' => [
            'webhook_url' => env('AUDIT_LOG_SLACK_WEBHOOK', null),
        ],
        'throttle' => [
            'enabled' => true,
            'max_notifications' => 5,
            'decay_minutes' => 60,
        ],
        // Configurable via AUDIT_LOG_NOTIFY_ON_CODES=500,502,503
        'notify_on_codes' => env('AUDIT_LOG_NOTIFY_ON_CODES')
            ? array_map('intval', explode(',', env('AUDIT_LOG_NOTIFY_ON_CODES')))
            : [500, 501, 502, 503, 504],
    ],

    // Performance logging
    'performance' => [
        'enabled' => env('AUDIT_LOG_PERFORMANCE_ENABLED', false),
        'slow_queries' => [
            'enabled' => env('AUDIT_LOG_SLOW_QUERIES_ENABLED', true),
            'threshold' => env('AUDIT_LOG_SLOW_QUERY_THRESHOLD', 1000),
            'log_bindings' => env('AUDIT_LOG_SLOW_QUERY_BINDINGS', true),
        ],
        'slow_requests' => [
            'enabled' => env('AUDIT_LOG_SLOW_REQUESTS_ENABLED', true),
            'threshold' => env('AUDIT_LOG_SLOW_REQUEST_THRESHOLD', 2000),
            'log_memory' => true,
        ],
    ],

    // Rollback
    'rollback' => [
        'enabled' => env('AUDIT_LOG_ROLLBACK_ENABLED', true),
        // Configurable via AUDIT_LOG_ROLLBACK_ALLOWED_USERS=1,5,10
        'allowed_users' => env('AUDIT_LOG_ROLLBACK_ALLOWED_USERS')
            ? array_map('intval', explode(',', env('AUDIT_LOG_ROLLBACK_ALLOWED_USERS')))
            : [],
        'rollbackable_events' => ['created', 'updated', 'deleted'],
        'max_chain_length' => env('AUDIT_LOG_ROLLBACK_MAX_CHAIN', 10),
        'log_rollback' => true,
    ],
];
```

Customization
-------------

[](#customization)

### Custom User Resolver

[](#custom-user-resolver)

```
// config/audit-log.php
'user_resolver' => App\Services\CustomUserResolver::class,

// App/Services/CustomUserResolver.php
class CustomUserResolver
{
    public function resolve(): ?int
    {
        return auth('admin')->id() ?? auth()->id();
    }
}
```

### Custom Audit Data

[](#custom-audit-data)

```
class Order extends Model
{
    use Auditable;

    public function getAuditCustomData(): array
    {
        return [
            'total' => $this->total,
            'items_count' => $this->items->count(),
        ];
    }

    public function getAuditDescription(string $event): ?string
    {
        return "Order #{$this->id} was {$event}";
    }

    public function shouldBeAudited(): bool
    {
        // Don't audit draft orders
        return $this->status !== 'draft';
    }
}
```

Response Format
---------------

[](#response-format-1)

### Normal Operation Log

[](#normal-operation-log)

```
{
    "id": 1,
    "user": {
        "id": 1,
        "type": "App\\Models\\User",
        "name": "John Doe",
        "email": "john@example.com"
    },
    "performed_at": "2024-01-15T10:30:00+00:00",
    "performed_at_human": "2 hours ago",
    "request": {
        "ip": "192.168.1.1",
        "user_agent": "Mozilla/5.0...",
        "url": "https://example.com/api/users/1",
        "method": "PUT",
        "route": "users.update"
    },
    "event": "updated",
    "model": {
        "type": "App\\Models\\User",
        "id": 1,
        "table": "users"
    },
    "changes": {
        "old": { "name": "John" },
        "new": { "name": "John Doe" },
        "fields": ["name"],
        "diff": {
            "name": { "old": "John", "new": "John Doe" }
        }
    },
    "summary": "Updated User #1 by John Doe"
}
```

### Error Log

[](#error-log)

```
{
    "id": 42,
    "user": {
        "id": 1,
        "type": "App\\Models\\User",
        "name": "John Doe",
        "email": "john@example.com"
    },
    "performed_at": "2024-01-15T14:22:00+00:00",
    "performed_at_human": "5 minutes ago",
    "request": {
        "ip": "192.168.1.1",
        "user_agent": "Mozilla/5.0...",
        "url": "https://example.com/api/orders/process",
        "method": "POST",
        "route": "orders.process"
    },
    "event": "error",
    "response_code": 500,
    "description": "[500] PaymentException: Payment gateway timeout",
    "metadata": {
        "exception_class": "App\\Exceptions\\PaymentException",
        "exception_code": 0,
        "file": "/var/www/app/Services/PaymentService.php",
        "line": 142,
        "stack_trace": "#0 /var/www/app/Http/Controllers/OrderController.php(85): App\\Services\\PaymentService->process()...",
        "context": {
            "order_id": 123,
            "amount": 99.99
        }
    },
    "summary": "Error by John Doe"
}
```

License
-------

[](#license)

MIT

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance82

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

4

Last Release

93d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9f3acde28c4144b8432fbcd2fbaeaeb877c63519b556724f7f4d920842a9eb81?d=identicon)[campeloneto1](/maintainers/campeloneto1)

---

Tags

loglaraveltrackingactivityAudithistory

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/campelo-laravel-audit-log/health.svg)

```
[![Health](https://phpackages.com/badges/campelo-laravel-audit-log/health.svg)](https://phpackages.com/packages/campelo-laravel-audit-log)
```

###  Alternatives

[spatie/laravel-activitylog

A very simple activity logger to monitor the users of your website or application

5.8k45.4M309](/packages/spatie-laravel-activitylog)[owen-it/laravel-auditing

Audit changes of your Eloquent models in Laravel

3.4k33.0M95](/packages/owen-it-laravel-auditing)[yadahan/laravel-authentication-log

Laravel Authentication Log provides authentication logger and notification for Laravel.

416632.8k5](/packages/yadahan-laravel-authentication-log)[msonowal/laravel-auditor

A simple mongo activity logger to record various events of your laravel application

1030.2k1](/packages/msonowal-laravel-auditor)[hryha/laravel-request-logger

A Laravel package to log requests and responses

102.2k](/packages/hryha-laravel-request-logger)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
