# Vercel Logs

Stream Vercel deployment logs into Gonzo for real-time terminal analysis — with your app-level fields (service, level, message) unwrapped from Vercel's double-encoded JSON and merged with platform metadata (domain, route, status code).

### How It Works

The Vercel CLI's `-j` flag outputs each log line as JSON, but the actual app log is buried inside the `message` field as a stringified JSON object with a `[function-name]` prefix (e.g. `[orders]` for `/api/orders`). A `jq` normalizer in the pipe strips the prefix, parses the inner JSON, and merges it with the Vercel envelope — so Gonzo sees a flat, clean log line with all fields at the top level.

When you specify a deployment URL, Vercel auto-follows (streams in real time) by default.

### Quick Start

#### Prerequisites

* Gonzo installed
* jq installed (`brew install jq`)
* Vercel CLI installed and authenticated (`npm i -g vercel && vercel login`)
* A Vercel deployment receiving traffic

#### Stream Logs

```bash
vercel logs <deployment_url_or_id> -j | jq --unbuffered '
  (.message | sub("^\\[.*?\\] "; "") | fromjson) + {source, requestPath, domain, requestMethod, responseStatusCode}
' | gonzo
```

Replace `<deployment_url_or_id>` with your deployment URL or ID. Find this in the Vercel dashboard or via `vercel ls`.

> **⚠️ `--unbuffered` on jq is mandatory.** Without it, jq buffers output and the pipe appears to stall. This is the #1 setup issue.

### What Gets Unwrapped

The normalizer produces a flat JSON line combining fields from two layers:

| Source                  | Fields                                                                   | Description                                 |
| ----------------------- | ------------------------------------------------------------------------ | ------------------------------------------- |
| Your app (inner JSON)   | `ts`, `level`, `service`, `msg`, `reqId`, `value`                        | The actual structured log your code emitted |
| Vercel envelope (outer) | `source`, `requestPath`, `domain`, `requestMethod`, `responseStatusCode` | Platform metadata from the edge             |

Gonzo sees the app-level `level` field, not Vercel's outer classification — so severity filtering reflects what your code actually logged.

### Usage Patterns

#### Batch fetch (no streaming):

```bash
vercel logs <deployment_url_or_id> -j --no-follow | jq --unbuffered '
  (.message | sub("^\\[.*?\\] "; "") | fromjson) + {source, requestPath, domain, requestMethod, responseStatusCode}
' | gonzo
```

#### Write to file for external analysis:

```bash
vercel logs <deployment_url_or_id> -j --no-follow | jq --unbuffered '
  (.message | sub("^\\[.*?\\] "; "") | fromjson) + {source, requestPath, domain, requestMethod, responseStatusCode}
' > /tmp/vercel-logs.jsonl
```

#### With AI analysis:

```bash
export OPENAI_API_KEY="sk-your-key"
vercel logs <deployment_url_or_id> -j | jq --unbuffered '
  (.message | sub("^\\[.*?\\] "; "") | fromjson) + {source, requestPath, domain, requestMethod, responseStatusCode}
' | gonzo --ai-model="gpt-4"
```

#### Filter by branch:

```bash
vercel logs --follow -j -b main | jq --unbuffered '
  (.message | sub("^\\[.*?\\] "; "") | fromjson) + {source, requestPath, domain, requestMethod, responseStatusCode}
' | gonzo
```

### Filtering in Gonzo

Press `/` to filter. Useful patterns:

| Filter          | What you'll see                                 |
| --------------- | ----------------------------------------------- |
| `error`         | App-level errors (from the inner `level` field) |
| `payments`      | Logs from the payments service                  |
| `auth`          | Authentication-related logs                     |
| `/api/orders`   | Requests to a specific route                    |
| `edge-function` | Edge function logs only                         |
| `timeout`       | Timeout-related messages                        |

### The `[prefix]` Explained

Vercel prepends the API route name to the `message` field as a bracket prefix:

* `/api/noise` → `[noise] {...}`
* `/api/orders` → `[orders] {...}`
* `/api/auth/login` → `[auth/login] {...}`

The normalizer's `sub("^\\[.*?\\] "; "")` strips any `[...]` prefix automatically, regardless of the route name.

### Notes

* **The `-j` flag is required.** Without it, Vercel outputs plain text and the normalizer has nothing to parse.
* **No log drain required.** This uses the Vercel CLI directly, which is currently free on Hobby and Pro tiers. No Vercel-side configuration needed.
* **Vercel log retention is limited.** Runtime logs are retained for 1 hour (Hobby), 3 days (Pro/Enterprise). For longer retention, consider forwarding to Dstl8.
* **Non-function logs may not have the `[prefix] {json}` format.** Build logs or platform-level messages can appear in the stream without inner JSON. These will cause a `jq` parse error — they're safe to ignore.

### Troubleshooting

| Problem                         | Fix                                                                                                             |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Pipe appears to stall           | Make sure `--unbuffered` is on the jq call                                                                      |
| No logs appearing               | Check you're authenticated (`vercel whoami`) and the deployment is receiving traffic                            |
| `vercel: command not found`     | Install the CLI: `npm i -g vercel`                                                                              |
| `jq: error - Could not parse`   | A log line doesn't have the expected `[prefix] {json}` format — likely a build or platform log. Safe to ignore. |
| Logs appear but no inner fields | Make sure you're using the `-j` flag                                                                            |
| Ctrl+C not killing the pipe     | Use `ctrl+\` (SIGQUIT) or `kill $(pgrep -f "vercel logs")` from another terminal                                |

Time to complete: 5 minutes | Prerequisites: Vercel CLI, `jq`, Gonzo installed | Full guide: `guides/VERCEL_USAGE_GUIDE.md`
