rajmundtoth0/laravel-auditing-elasticsearch-driver
An Elasticsearch driver for the Laravel Auditing package. Store and query model audit trails in Elasticsearch instead of a relational database, giving you fast, scalable, full-text search over your application's change history with minimal configuration.
This package plugs Elasticsearch in as a storage driver for owen-it/laravel-auditing. The 2.0.0 release is a major refactor: configuration is now explicit PHP config rather than deprecated JSON definitions, setup/data-stream behavior has changed, and the Elasticsearch PHP client is expected to match your Elasticsearch server minor version.
Minimal path to first audit:
Install the driver alongside Laravel Auditing:
composer require rajmundtoth0/laravel-auditing-elasticsearch-driver
Pin elasticsearch/elasticsearch to the same minor as your cluster. The 2.0 CI matrix uses Elasticsearch 8.19.12 with client ^8.19, and Elasticsearch 9.3.1 with client ^9.3.
Publish/inspect the auditing config, then set the driver to Elasticsearch:
// config/audit.php
return [
'driver' => 'elasticsearch',
'drivers' => [
'elasticsearch' => [
'hosts' => [env('ELASTICSEARCH_HOST', 'http://localhost:9200')],
// v2: define storage/index/data-stream/mapping config here,
// not through the removed JSON definition approach.
],
],
];
Run the package setup command to create the required index template/data stream. The command class is ElasticsearchSetupCommand; confirm the exact signature with:
php artisan list | grep -i elastic
Typical usage is a one-off or deploy-step command such as php artisan elasticsearch:setup.
Add the standard Laravel Auditing trait to a model:
use OwenIt\Auditing\Contracts\Auditable;
class Post extends Model implements Auditable
{
use \OwenIt\Auditing\Auditable;
}
Make a change and verify the document lands in Elasticsearch via Kibana Dev Tools or _search.
Where to look first: the published config/audit.php driver block, ElasticsearchSetupCommand, the driver class itself, and the package tests under tests/ — v2 uses fixture files for config and mappings, which are the clearest examples of the new configuration shape.
First real use case: audit one low-risk model in a development environment, confirm the document shape and date fields, then expand to the models that matter for compliance or debugging.
Configuration-driven storage. Treat the new config structure as the source of truth. v2 removed the deprecated JSON definition path, so index/data-stream names, mappings, and client settings should live in PHP config and environment variables. Keep host lists and credentials in .env, and commit the structural config.
Data streams for append-only audit history. The release emphasizes better Elasticsearch setup and data-stream handling. Use data streams for audit events where possible: they fit append-only audit logs, support rollover, and align with modern Elasticsearch retention patterns. Make the setup command part of deployment, before the app starts writing audits:
php artisan elasticsearch:setup
Run it idempotently in staging first; confirm it creates or updates templates without destroying existing backing indices.
Model-level auditing stays familiar. Day-to-day usage is still Laravel Auditing: implement Auditable, use $auditInclude, $auditExclude, $auditEvents, and transformAudit() as usual. The driver’s job is persisting those audit records to Elasticsearch. Keep transformations small and stable — they become your Elasticsearch document schema.
Query through Elasticsearch, not Eloquent. Audits are stored in Elasticsearch, so reporting and investigation should use the Elasticsearch client, Kibana, or a small repository/service layer:
$response = app(\Elastic\Elasticsearch\Client::class)->search([
'index' => 'audits', // use your configured index/data stream
'body' => [
'query' => [
'term' => ['auditable_type' => App\Models\Post::class],
],
'sort' => [['@timestamp' => 'desc']],
],
]);
Build dashboards for “who changed what, when” rather than trying to query audits like normal Eloquent models.
Custom mappings belong in the new config model. If you override mappings, express them in the v2 config structure and verify date fields explicitly. The deprecated date format has been removed, so any mapping override copied from a v1 project is suspect. After mapping changes, plan for rollover/reindex because data-stream backing indices have immutable mappings.
Testing pattern. v2’s test suite uses fixture files for configuration and mappings, including invalid JSON fixtures for failure modes. Mirror that:
Operational integration. Give the application a dedicated Elasticsearch user with only the privileges it needs: write to the audit data stream, and template/setup permissions only during deployment. Monitor indexing failures separately from application errors — audit writes should not silently disappear.
2.0 is a migration, not a patch. The removed JSON definitions are the big breaking change. Search your project and deploy configuration for old JSON definition paths/keys and move them into the new config structure. Do not assume a v1 config will boot correctly under v2.
Mapping overrides may fail after upgrade. The deprecated date format was removed from mappings. If you ship custom mappings, check every date field and any override copied from v1. A mapping rejection during setup or first write is easy to miss if the app swallows audit exceptions.
Match Elasticsearch and client minors. CI pins client ^8.19 to Elasticsearch 8.19.12 and ^9.3 to Elasticsearch 9.3.1. Composer can resolve a client that is technically installable but incompatible with your cluster. Explicitly constrain elasticsearch/elasticsearch in composer.json, and verify the same pairing locally that CI enforces.
Setup command container behavior changed. ElasticsearchSetupCommand now resolves services via app() and no longer performs instance-forget cleanup. In tests, this means container bindings and mocks can leak between cases. Prefer a fresh application per test, and avoid globally binding a mocked client unless the test explicitly owns that lifecycle.
Data-stream mappings are immutable. Changing a mapping is not a simple config deploy. Create/update the index template, then roll over the data stream or reindex into a new one. Plan index lifecycle management and retention before audit volume grows.
Config caching. After changing config/audit.php, run php artisan config:cache in deployments and clear it during rollback. A cached old driver config is a common reason setup appears to work while the app writes to the wrong place.
Debugging checklist. Enable Elasticsearch client logging, run the setup command verbosely, and inspect _index_template and _data_stream directly:
curl "$ELASTICSEARCH_HOST/_index_template"
curl "$ELASTICSEARCH_HOST/_data_stream"
Then query recent audit documents in Kibana. If writes fail only for some models, compare their transformed audit payloads and mapping fields first.
Retries help with transient failures, not schema errors. v2 improves retry coverage, but retrying a mapping conflict or permission error just delays the failure. Configure timeouts/retries for network blips, and alert on persistent indexing errors.
Do not treat Elasticsearch as your only audit copy without a retention plan. Snapshots, ILM, and access controls are your responsibility. If audits are compliance-relevant, document the retention policy and test restore procedures before relying on this driver in production.
Upgrade path. Pin v1 while you migrate config and mappings in a branch, run the package’s integration tests against your target Elasticsearch version, then deploy v2 with the setup command as an explicit release step. The release notes are high-level; review the 2.0 commit and test fixtures for the exact new config keys before cutting over.
How can I help you explore Laravel packages today?