# Logs

Source: https://laraport.app/docs/logs/

> Search, filter and follow Laravel, Docker and service logs in the terminal, follow a whole project in one stream and group errors by kind.

*Screen: A Laravel log followed live*

The **Logs** tab offers three sources, plus a summary of the errors:

- **Laravel logs**: the log files in `storage/logs`;
- **Errors**: the [errors summary](#errors-summary) of the newest Laravel log;
- **Docker logs**: the container's stdout and stderr;
- **Service logs**: nginx, PHP-FPM, supervisor and the other files in `/var/log`, plus the `custom_logs` of the container.

The pickers list files at once with their size and dates. Line counts fill in afterwards in the background. The Laravel logs picker leaves out dotfiles such as `.gitignore` and compressed rotations. `e` on a file there opens its errors summary.

## Search and levels

| Key | Action |
|---|---|
| `/` | Search as you type, case-insensitively. Matches are highlighted and counted (`match 3/17`) |
| `enter` | Jump to the newest match |
| `n` / `N` | Next / previous match |
| `l` | Level filter: all, warnings and up, errors only |
| `]` / `[` | Next / previous error |
| `f` or `end` | Follow new lines |
| `f2` | Wrap long lines |
| `esc` | Clear the search, then leave |

For Laravel logs the level comes from the entry (`production.ERROR:`), and stack traces stay with their entry. Other logs are classified by their level words (`[error]`, `level=warn`, `Fatal error`).

## Errors summary

The errors summary answers "what is failing, and how often?" without scrolling through the log. It lists every kind of error and warning once.

*Screen: The exceptions of a log file, grouped by kind*

Open it with **Errors** on the Logs tab, for the newest log, or with `e` on a file in **Laravel logs**.

Each row shows the count, the level, the exception class, the message, where it was thrown, and the first and last time it happened. Errors come before warnings.

| Key | Action |
|---|---|
| `enter` | The latest occurrence, with its stack trace |
| `o` | Order by count, or by the latest occurrence |
| `a` | Read the whole file (shown when the log is over 64 MB) |
| `l` | Open the log itself |
| `r` | Read again |

Entries are the same kind when they have the same level, exception class, file and line, and the same message once numbers, IDs and quoted values are blanked out. So "Card declined for order SH-49231" and "Card declined for order SH-50117" count as one kind.

Entries whose message spans several lines, such as a `QueryException` with its SQL error, are read whole: their exception and location are found further down.

The grouping runs inside the container with `awk`, over the last 64 MB of the file unless you press `a`. Only the summary travels to your computer, even from a log of several gigabytes.

## Group logs

`l` on a group header in the container list follows all running containers of that project in one stream, up to 16. Each line starts with a coloured label: the service, or its display name. The recent lines of each are merged in time order, then new lines follow as they come. Search, levels and error jumps work as for one container.

## Large files

Log files are read by byte offset, never line by line, so opening a 1 GB log takes as long as a 1 MB one.

- Opening reads the last 256 KB, then follows new lines from exactly where that chunk ended. Nothing is lost or repeated.
- Scrolling up loads the 256 KB before the earliest loaded line.
- The status bar shows the position in bytes and percent. Docker logs have no file, so they show the line count instead.
