Laravel and Horizon log parsing
Log Lens reads Laravel and Horizon log files line by line and turns them into structured events, so a single error, its stack trace, and any trailing context all become one entry you can search, group, and resolve.
The header format
Every Laravel event starts with a header line. Log Lens matches this exact shape:
[2026-07-25 14:03:11] production.ERROR: Something went wrong
That line is split into four parts:
| Part | Example | Becomes |
|---|---|---|
| Timestamp | 2026-07-25 14:03:11 | when the event occurred |
| Environment | production | the environment field |
| Level | ERROR | the severity |
| Message | Something went wrong | the start of the body |
The level is normalized to a standard set: WARN becomes WARNING, ERR and FATAL become ERROR, TRACE becomes DEBUG, and a missing level defaults to INFO.
Multiline bodies and stack traces
A new header line begins a new event. Any line that does not match the header format is treated as a continuation and appended to the current event's body. This is how full exception stack traces, {"exception":...} context, and wrapped messages stay attached to the event that produced them, instead of scattering into dozens of fragments.
Each event records the exact byte range it spans in the file, so Log Lens can later show you the untouched original text. See byte-range storage and read a raw event.
To keep a single runaway trace from consuming memory, the captured body is capped. Once a body reaches the limit (ingestion.capture_limit, default 4,194,304 bytes / 4 MiB) it stops growing, though the event's byte range still covers the full extent on disk.
Detection
Log Lens decides which parser handles a file by name and content:
- Horizon files are matched by filename and framing - any file whose name contains
horizonand whose sample matches either the Laravel header format above or one of the two shapeshorizon/queue:workprint to the console. A horizon-named file in neither shape falls through to the console parser rather than parsing to nothing. - Laravel files are files whose name does not contain
horizonand whose first line matches the header format above.
Horizon console output
A worker log captured from the console has no Laravel framing and no level:
[2026-08-20 03:00:02][7f3a1c2e] Failed: App\Jobs\SyncCustomer
2026-08-20 03:00:02 App\Jobs\SyncCustomer .................... 1s FAIL
Because the format carries no level, the verb is the level: Failed/FAIL, or an exception class where the verb would be, is an ERROR; every other line is INFO progress. Unheaded lines still append to the event above them, so a failed job keeps the trace that explains it. Events are stored with the horizon log type and the horizon environment.
The channel is taken from the file name, so laravel.log and laravel-2026-07-25.log are distinguished automatically. This ties into log rotation and generations and which files count as logs.