Driver-agnostic activity and audit logging for Laravel.
Eagle Eye records what happens in your application (HTTP requests, model changes, logins, jobs, commands, mail, notifications, outbound API calls, exceptions) without any application code, links everything that belongs to one request into a trace, redacts personal data before it is stored, and writes it to the database or Grafana Loki through one stable entry format.
- Zero-code capture. Install, migrate, and every request, model change, and login is in the log. Add your own domain events with one line.
- One envelope, any storage. The same
ActivityEntryis stored in SQL, Loki, or your own driver, and read through the same query API. - Privacy by default. Passwords, tokens, and card data are masked; emails, phone numbers, and names are partially masked; secrets can be encrypted and revealed only through an authorised, audited call. Subject erasure and retention are built in.
- Traces, not just rows. Every entry of a request, the jobs it dispatched, and the outbound calls it made share a trace id and a causal chain.
- Off the hot path. Entries are buffered and written after the response is sent, with bounded memory and a disk spool when storage is down.
- Automatic capture of HTTP, Eloquent, auth, queue, console and scheduler, mail, notifications, outbound HTTP (Laravel
Httpand Guzzle), exceptions, and slow queries, plus a per-request SQL summary - Manual recording through a facade, helper, or fluent
ActivityDraft - Drivers:
database,loki,multi(Loki + SQL index),index,memory,null, and custom drivers with a conformance test suite - Redaction modes
mask,partial,hash,encrypt,drop,keep, path and key rules, per-model privacy declarations, IP truncation - Audited secret reveal, subject erasure with replay barriers, retention by channel/severity/tag, optional HMAC integrity ledger
- W3C
traceparentsupport, queue trace propagation, causal trace trees - Deterministic per-trace sampling and deny-first filtering with per-route overrides
- Fluent queries, cursor pagination, aggregation and time series,
activityTrail()on every model - Optional JSON API with a TypeScript contract, localised human-readable titles
EagleEye::fake()for tests, and 14activity-log:*Artisan commands
- PHP 8.4 or 8.5 with
ext-mbstring - Laravel 12 or 13
ext-curlfor the Loki driver's HTTP push and query API
composer require dotswan/eagle-eye
php artisan vendor:publish --tag=eagle-eye-migrations
php artisan migrateOptionally publish the configuration and title translations:
php artisan vendor:publish --tag=eagle-eye-config
php artisan vendor:publish --tag=eagle-eye-langSee Installation for the full guide, including scheduling and verification.
EAGLE_EYE_DRIVER=database
# Required outside local/testing: 32+ random bytes, never rotated with APP_KEY
EAGLE_EYE_SECURITY_KEY= # php -r 'echo base64_encode(random_bytes(32)), PHP_EOL;'That is all. Open a page, edit a model, log in, then:
php artisan activity-log:tailWrite one JSON line per entry to stdout for your log collector, and read back through the Loki API:
EAGLE_EYE_DRIVER=loki
EAGLE_EYE_LOKI_WRITE=stdout
EAGLE_EYE_LOKI_READ_SELECTOR={namespace="my-app-prod",container="app"}
LOKI_QUERY_URL=http://loki:3100
EAGLE_EYE_SECURITY_KEY=...Or push directly to Loki:
EAGLE_EYE_DRIVER=loki
EAGLE_EYE_LOKI_WRITE=push
LOKI_PUSH_URL=http://loki:3100
LOKI_TENANT_ID=my-app
EAGLE_EYE_SECURITY_KEY=...Run the migration with Loki too: privacy and integrity state is kept in SQL. See Loki.
use Dotswan\EagleEye\Facades\EagleEye;
// Record a domain event
EagleEye::record('invoice.approved', ['invoice_id' => 42]);
// Same, through the helper
eagleEye()->record('invoice.approved', ['invoice_id' => 42]);
// Tag everything recorded inside the callback (including captured model changes)
EagleEye::withTags(['tenant:42'], fn () => $importer->run());
// Record nothing inside the callback
EagleEye::withoutLogging(fn () => $seeder->run());
// Read activity
$history = $invoice->activityTrail()->limit(50)->get();
$recent = EagleEye::query()->forActor('user', 8821)->last('7 days')->get();Describe your models with attributes and contracts:
use Dotswan\EagleEye\Attributes\ActivityLabel;
use Dotswan\EagleEye\Attributes\ActivityTags;
use Dotswan\EagleEye\Contracts\DeclaresActivityPrivacy;
use Dotswan\EagleEye\Enums\RedactionMode;
#[ActivityLabel('number')]
#[ActivityTags('billing')]
final class Invoice extends Model implements DeclaresActivityPrivacy
{
public function activityPrivacy(): array
{
return ['iban' => RedactionMode::Encrypt, 'customer_email' => RedactionMode::Partial];
}
}Test it:
$fake = EagleEye::fake();
$this->post('/invoices/42/approve');
$fake->assertLogged(fn ($entry) => $entry->action === 'invoice.approved');See Usage for drafts, subjects, queries, pagination, and testing.
| Page | Contents |
|---|---|
| Installation | Requirements, setup, security key, scheduling, verification |
| Configuration | Every configuration key and environment variable |
| Usage | Recording, model attributes, trails, queries, testing |
| Integration | Everything the package registers (routes, tables, commands, helpers, bindings) and coexistence with other packages |
| Performance | Per-request cost, buffering, transports, memory bounds, production tuning, Octane |
| Drivers | Shipped drivers, capabilities, custom drivers |
| Loki | Loki write modes, collector setup, LogQL translation, retention |
| Filtering | Filter rules, overrides, request parts, custom rules |
| Privacy | Redaction, encryption and reveal, erasure, retention, integrity |
| Correlation | Trace ids, causal chains, W3C propagation, queue propagation |
| Queries | Query API, pagination, aggregation, time series |
| API | Optional JSON API and TypeScript contract |
| Extending | Pipes, enrichers, title resolvers, policies, resolvers |
| Architecture | How the pieces fit together, ADRs |
| Upgrading | Versioning policy and upgrade checklist |
activity-log:doctor, stats, tail, trail, trace, export, prune, forget, verify, ship, loki-ship, loki-config, cache, make-driver. See Integration.
composer install
composer check # audits, Deptrac, Rector, Pint, PHPStan, Pest
composer test # Pest onlySee CONTRIBUTING.md for running the Loki and MySQL integration suites.
See CHANGELOG.md.
Contributions are welcome. Please read CONTRIBUTING.md.
Please report vulnerabilities by email to tech@dotswan.com instead of opening an issue. See SECURITY.md.
Eagle Eye is open-source software licensed under the MIT license.