PHPackages                             ayup-creative/event-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. ayup-creative/event-log

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

ayup-creative/event-log
=======================

Event log package for models in a Laravel application.

v2.1.1(2mo ago)030PHPPHP &gt;=8.3CI passing

Since Mar 18Pushed 2mo agoCompare

[ Source](https://github.com/Ayup-Creative/laravel-event-log)[ Packagist](https://packagist.org/packages/ayup-creative/event-log)[ RSS](/packages/ayup-creative-event-log/feed)WikiDiscussions main Synced today

READMEChangelog (4)Dependencies (4)Versions (6)Used By (0)

Laravel Event Logger
====================

[](#laravel-event-logger)

[![CI/CD](https://github.com/Ayup-Creative/laravel-event-log/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/ayup-creative/laravel-event-log/actions/workflows/ci-cd.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/3f293a30795c90a2493d5ac1a9362860ff7ca3f68648a60c669e69bfc88e0e28/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f617975702d63726561746976652f6576656e742d6c6f672e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ayup-creative/event-log)[![Total Downloads](https://camo.githubusercontent.com/8ede5baf82973789be7890b0cea1d7afc7248b73e67629cf26e859e44cf2e737/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f617975702d63726561746976652f6576656e742d6c6f672e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ayup-creative/event-log)[![License](https://camo.githubusercontent.com/0a999c302f2c12c8e0a4cab515941bb82908efaa68371cff88b8d30996336c7e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f617975702d63726561746976652f6576656e742d6c6f672e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/ayup-creative/event-log)

A high-performance, structured, asynchronous, and relational event logging package for Laravel. Designed for auditability, traceability, and cross-service correlation without storing sensitive payload data.

Core Design Goals
-----------------

[](#core-design-goals)

- **Log Facts, Not State**: Records what happened (the event), not the resulting state of the model.
- **Privacy by Design**: Avoids storing sensitive data, JSON blobs, or PII. It links to models instead of copying their data.
- **Async-First**: All event persistence is handled via Laravel's queue system to ensure zero impact on request performance.
- **Exactly-Once Delivery**: Built-in idempotency ensures that retried queue jobs do not create duplicate event records.
- **Relational Graph**: Supports a primary "subject" and multiple "related" models per event, allowing for complex traceability.
- **Audit Ready**: Captures causers (users, system, jobs), correlation IDs, and transaction IDs.
- **OpenTelemetry Ready**: Seamlessly integrates with distributed tracing systems.

---

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

[](#installation)

You can install the package via composer:

```
composer require ayup-creative/event-log
```

The service provider will automatically register itself.

You should publish and run the migrations:

```
php artisan vendor:publish --tag="event-log-migrations"
php artisan migrate
```

You can optionally publish the config file:

```
php artisan vendor:publish --tag="event-log-config"
```

---

Versions
--------

[](#versions)

The package follows semantic versioning. Major version changes indicate breaking changes, while minor and patch versions introduce new features and bug fixes, respectively.

VersionLaravel1.x12.x2.x13.x---

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

[](#configuration)

The published config file `config/event-log.php` allows you to customize the models used by the package:

```
return [
    /*
     * The model used to represent users in your application.
     * This is used for the 'causer' relationship.
     */
    'user_model' => \App\Models\User::class,

    /*
     * The Eloquent models used for event logs and their relations.
     * You can extend these to add your own logic or relationships.
     */
    'event_model' => \AyupCreative\EventLog\Models\EventLog::class,
    'relation_model' => \AyupCreative\EventLog\Models\EventLogRelation::class,

    /*
     * The name of the queue that event log jobs should be sent to.
     * It is recommended to use a lower priority queue.
     */
    'queue' => 'event-log',
];
```

---

Usage
-----

[](#usage)

### 1. Manual Domain Events

[](#1-manual-domain-events)

Use the `log_event` helper to record significant domain events asynchronously. It is recommended to use the namespaced `log_event()` function.

```
use function AyupCreative\EventLog\log_event;

// Basic event
log_event('organisation.created', $organisation);

// Event with related models
log_event('user.enrolled', $user, [$organisation, $course]);

// Event with additional metadata (e.g., tracking reasons, API errors)
log_event('payment.failed', $payment, metadata: [
    'error_reason' => 'Insufficient funds',
    'provider' => 'Stripe'
]);
```

#### Event Enums

[](#event-enums)

The `log_event` helper also supports `BackedEnum` for event names, providing better type safety and IDE autocompletion.

```
use function AyupCreative\EventLog\log_event;
use App\Enums\EventName;

log_event(EventName::ORGANISATION_CREATED, $organisation);
```

- **Event Name**: A human-readable dot-notation string or a `BackedEnum`.
    - **Subject**: The primary Eloquent model the event is about.
    - **Related**: (Optional) An array of additional Eloquent models linked to this event.
    - **Causer Type**: (Optional) Explicitly set the type of actor ('user', 'system', 'worker', 'cron').
    - **Metadata**: (Optional) Key-value pairs of additional context for the event.

### 2. Automatic Lifecycle Logging

[](#2-automatic-lifecycle-logging)

Add the `LogsEvents` trait to any Eloquent model to automatically log lifecycle events (`created`, `updated`, `deleted`, `restored`).

```
use AyupCreative\EventLog\Features\LogsEvents;
use Illuminate\Database\Eloquent\Model;

class Mandate extends Model
{
    use LogsEvents;
}
```

#### Customizing Trait Behavior

[](#customizing-trait-behavior)

You can override these methods in your model:

```
class Mandate extends Model
{
    use LogsEvents;

    // Change the dot-notation prefix (defaults to snake_case of class name)
    public function eventNamespace(): string
    {
        return 'billing.mandate';
    }

    // Filter which events should be logged
    public function shouldLogEvent(string $event): bool
    {
        return $event !== 'mandate.updated';
    }

    // Attach related models to automatic lifecycle events
    public function eventRelations(string $event): array
    {
        return [$this->organisation];
    }

    // Include automatic metadata in lifecycle logs
    public function eventMetadata(string $event): array
    {
        return ['type' => $this->type];
    }
}
```

### 3. Custom Actor &amp; Causer Resolution

[](#3-custom-actor--causer-resolution)

By default, the package uses `auth()->id()` to identify the current user and determines if the action was triggered by a 'user' (web request) or 'worker' (CLI).

You can customize this behavior using the `EventLog` Facade in your `AppServiceProvider`:

```
use AyupCreative\EventLog\Facades\EventLog;

public function boot()
{
    // Resolve the current actor ID (e.g., from a custom auth system)
    EventLog::resolveActorWith(function ($app) {
        return auth('api')->id();
    });

    // Determine the type of causer based on context
    EventLog::determineCauserTypeWith(function ($app) {
        if ($app->runningInConsole()) {
            return 'cron';
        }
        return 'user';
    });
}
```

### 4. Grouping Events with Transactions

[](#4-grouping-events-with-transactions)

Use the `WithEventTransaction` wrapper to group multiple events occurring within a single database transaction. This assigns a shared `transaction_id` to all events logged inside the closure.

```
use AyupCreative\EventLog\Support\WithEventTransaction;

WithEventTransaction::run(function () use ($user, $org) {
    $org->save();
    $user->organisations()->attach($org);

    \AyupCreative\EventLog\log_event('organisation.created', $org);
    \AyupCreative\EventLog\log_event('user.enrolled', $user, [$org]);
});
```

### 5. Correlation IDs &amp; Middleware

[](#5-correlation-ids--middleware)

Correlation IDs allow you to trace a logical action across multiple services and background jobs.

#### Global Middleware

[](#global-middleware)

Add the `EventCorrelationMiddleware` to your global or web/api middleware stack to automatically capture or generate a correlation ID for every request.

```
// app/Http/Kernel.php or bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\AyupCreative\EventLog\Http\Middleware\EventCorrelationMiddleware::class);
})
```

#### Propagation via HTTP Client

[](#propagation-via-http-client)

The package adds a macro to the Laravel HTTP client to easily propagate the correlation ID:

```
use Illuminate\Support\Facades\Http;

Http::withEventContext()->post('https://api.other-service.com/data');
```

### 6. Human-Readable Event Formatting

[](#6-human-readable-event-formatting)

You can map internal dot-notation event names (e.g., `user.created`) to human-readable strings (e.g., `A new user was created`). This is useful for displaying a timeline of events to end-users.

#### Using the Facade (Closure-based)

[](#using-the-facade-closure-based)

Register a formatter in your `AppServiceProvider`:

```
use AyupCreative\EventLog\Facades\EventLog;

public function boot()
{
    EventLog::formatEventsWith(function ($eventLog) {
        return match ($eventLog->event) {
            'user.created' => "User {$eventLog->subject->name} joined the platform",
            'payment.failed' => "Payment failed: {$eventLog->meta->error_reason}",
            default => $eventLog->event,
        };
    });
}
```

#### Using a Formatter Class (Cache-friendly)

[](#using-a-formatter-class-cache-friendly)

For better performance and to keep your `AppServiceProvider` clean, you can use a dedicated class. This is also required if you want to use `php artisan config:cache`, as closures cannot be serialized.

1. Create your formatter class:

```
namespace App\Support;

class MyEventFormatter
{
    public function __invoke($eventLog)
    {
        // Custom logic to return a human-readable string
        return "Action: " . $eventLog->event;
    }
}
```

2. Register it in `config/event-log.php`:

```
'event_formatter' => \App\Support\MyEventFormatter::class,
```

#### Accessing the Formatted Description

[](#accessing-the-formatted-description)

Once a formatter is registered, you can access the human-readable string via the `description` attribute on the `EventLog` model:

```
$eventLog = EventLog::getFor($user)->first();
echo $eventLog->description; // "User John Doe joined the platform"
```

---

Querying Events
---------------

[](#querying-events)

You can retrieve a unified timeline of events for any model using the `EventLog` Facade. This returns events where the model is either the **subject** or a **related** model.

```
use AyupCreative\EventLog\Facades\EventLog;

// Get all events for a model
$events = EventLog::getFor($organisation);

foreach ($events as $log) {
    echo "{$log->description} caused by {$log->causerLabel()}";

    // Access metadata
    echo $log->meta->error_reason;
}

// Paginated version
$paginatedEvents = EventLog::getForPaginated($organisation);
```

### Causer Labels

[](#causer-labels)

The `EventLog` model provides a `causerLabel()` helper to identify the actor:

- `user`: Returns the user's name (if authenticated).
- `system`: Internal system action.
- `job`: Action triggered by a background job.
- `webhook`: Action triggered by an external service.

### Metadata Helper

[](#metadata-helper)

The `meta` attribute provides a shorthand for the metadata collection, allowing you to access values directly as properties:

```
echo $log->meta->error_reason;
```

Alternatively, you can access the full `metadata` relationship, which returns an Eloquent collection of metadata models.

---

Advanced Features
-----------------

[](#advanced-features)

### Idempotency

[](#idempotency)

To prevent duplicate logs during queue retries, the package generates a deterministic `idempotency_key` for every event. If a job runs twice, the database uniqueness constraint will silently prevent the second record from being created.

### OpenTelemetry Bridge

[](#opentelemetry-bridge)

If the `open-telemetry/opentelemetry` package is installed, the logger will automatically create spans for each event. The `correlation_id` is used to maintain trace context.

---

Testing
-------

[](#testing)

The package includes a comprehensive test suite. To run the tests:

```
composer test
```

Or manually:

```
vendor/bin/phpunit
```

License
-------

[](#license)

The MIT License (MIT).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance84

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 92.5% of commits — single point of failure

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 ~8 days

Total

4

Last Release

81d ago

Major Versions

v1.0.0 → v2.0.02026-04-10

### Community

Maintainers

![](https://www.gravatar.com/avatar/494de8188ad97403b72e40e385235a74ef6331aa2710b3727193f646189af9fc?d=identicon)[mykemeynell](/maintainers/mykemeynell)

---

Top Contributors

[![mykemeynell](https://avatars.githubusercontent.com/u/1590190?v=4)](https://github.com/mykemeynell "mykemeynell (37 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (3 commits)")

---

Tags

asyncaudit-logevent-logevent-logginglaravel

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/ayup-creative-event-log/health.svg)

```
[![Health](https://phpackages.com/badges/ayup-creative-event-log/health.svg)](https://phpackages.com/packages/ayup-creative-event-log)
```

###  Alternatives

[psr/log

Common interface for logging libraries

10.4k1.2B11.5k](/packages/psr-log)[open-telemetry/api

API for OpenTelemetry PHP.

1941.5M276](/packages/open-telemetry-api)[open-telemetry/sdk

SDK for OpenTelemetry PHP.

2328.5M343](/packages/open-telemetry-sdk)

PHPackages © 2026

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