## The commands worth memorizing

```bash
bin/kamal app logs --follow
bin/kamal app logs --lines 500 --grep "Completed 500"
bin/kamal app logs --lines 500 --grep "<request-id>"
```

The third one is the one that turns a wall of text into a story. Every log line in production
carries the request id, so grepping it gives you the request, the SQL it ran, the job it enqueued
and the mail it sent, in order.

## Find the request id from the outside

```bash
curl -sI https://yourdomain.com/up | grep -i x-request-id
```

Rails echoes the id in a response header, so a user who can reproduce a problem can hand you the id
from their browser's network tab and you can pull exactly their request.

## Logs are not a monitoring system

Container logs rotate and are lost when the container is replaced, which happens on every deploy.
For anything you need after the fact, send it somewhere durable. One Shot has an error reporter seam
at `app/adapters/error_reporter.rb` that follows the same adapter and fake pattern as the rest of the
kit: it no-ops without credentials and reports to a real service with them. That is where an
exception tracker plugs in, not into a log grep.

## Turn down the noise before you need it

Production defaults to `:info`, which includes every request. The level is set in
`config/environments/production.rb`. If the log is unreadable, that is usually assets or health
checks rather than your app. The health check route is declared at the top of `config/routes.rb` and
is hit every few seconds by design, so filtering it out is the first thing worth doing:

```bash
bin/kamal app logs --lines 500 | grep -v "/up"
```

## When the container will not start at all

`kamal app logs` reads a running container. If the deploy failed on the health check, the container
already exited, and the same command still shows its final output. That is where the boot error is,
and it is almost always a secret that did not arrive. See
[First Deploy Checklist](/docs/deployment/first-deploy-checklist).
