# 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`


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.controltheory.com/controltheory-documentation/gonzo-docs/integration-examples/vercel-logs.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
