elastic/ecs-logging
ECS Logging for PHP transforms application logs into structured logs that comply with Elastic Common Schema. Supports Monolog 3, works with Filebeat, Elasticsearch, and Kibana, and helps correlate logs with APM traces for better observability.
ElasticCommonSchemaFormatter, which plugs into any Monolog handler. The decision it supports is "do we pick one log schema now, or let each team invent one?" ECS is an open schema under Apache-2.0, so the answer can be yes without buying Elastic.@timestamp formatting (timezone bug fixed in 1.0.2), label key sanitization, and dot-key expansion behavior. That's a small but permanent maintenance tax for zero differentiation. Buying here is composer require plus wiring.log.level, log.logger, service.name, service.version) instead of regex-scraping free text.Elastic\Types\User ships a setHash method for obfuscating user.id/user.name, plus first-class error, service, user, and tracing context objects. This directly supports data-minimization obligations rather than leaving redaction to ad-hoc preg_replace.Elastic\Types\Tracing injects trace.id/transaction.id, so a log line links to an APM trace. This is the highest-leverage feature for any team already running Elastic APM.labels gives a sanctioned place for tenant.id/environment, which matters if you ever split indices or enforce access control at the log-store layer.ndjson parsing plus expand_keys/overwrite_keys, or Docker/Kubernetes hints annotations, to land this JSON correctly. Budget that work in the same decision.Consider it when most of these are true:
Look elsewhere, or defer, when:
config/logging.php and set the formatter on the handler yourself. That's roughly a day of work including tests — acceptable, but it's yours to own.docs/reference/setup.md carries a note that ECS logging for PHP is "currently only available for Monolog v2.*" and imports Elastic\Monolog\v2\Formatter\ElasticCommonSchemaFormatter, while docs/Monolog_v3.md imports Elastic\Monolog\Formatter\ElasticCommonSchemaFormatter. Two namespaces, two claims. Make engineering confirm the shipped namespace against the installed tag before you commit to a plan.Two smaller checks worth doing: the examples emit "ecs.version":"1.2.0", so confirm which ECS spec version the tag you install targets and whether your index templates expect it; and confirm the formatter behaves acceptably under Laravel's exception handler, since uncaught exceptions are the logs you'll care most about during an incident.
To executives (one paragraph): We can make every Laravel service emit logs in a single industry-standard format for the cost of a Composer dependency and about a day of wiring. That buys faster incident diagnosis, consistent audit trails, and the ability to correlate a log line to a specific user and request trace — the foundation for the reliability and observability work already on the roadmap. No license cost, no vendor lock-in, open schema. The main caveat is that it's a small Elastic-maintained library with minimal external adoption, so we should treat it as a thin adapter we could replace in a day rather than infrastructure we depend on.
To engineering (the ask): Add elastic/ecs-logging, set ElasticCommonSchemaFormatter on the Monolog handler for the channels we want structured, and use the provided Error, Service, User, and Tracing context objects instead of hand-rolled arrays. Rough scope: one custom log channel in config/logging.php, a base service provider to attach service name/version, an exception-handling hook, and tests asserting the JSON shape. Before sizing, resolve the docs conflict — the README claims Monolog 3-only while the setup guide claims v2-only and uses a v2 namespace. Ship behind a single channel first, validate the parsed output in Kibana, then migrate the rest.
Positioning line: Not a logging platform — a one-day adapter that makes our existing logs queryable, correlatable, and compliant, with an exit ramp we control.
How can I help you explore Laravel packages today?