Skip to content

Commit 168e320

Browse files
adriancooneyclaude
andauthored
[cli] Add logsv2 command (#14656)
## Summary Adds a new hidden `vercel logsv2` command that uses the newer `/api/logs/request-logs` endpoint (same as the Vercel dashboard). This provides project-scoped log querying with extensive filtering options, designed to eventually replace the existing `logs` command. ## New Features - **Project-scoped logs**: Query logs across all deployments in a project (vs deployment-only in v1) - **Rich filtering**: Level, source, status code, environment, time range, request ID, and full-text search - **Agent-native output**: JSON Lines format for easy piping to `jq` and automation tools - **Historical data**: Query past logs with `--since`/`--until` (vs real-time only in v1) ## New Options | Option | Type | Description | |--------|------|-------------| | `--project, -p` | string | Project ID or name (defaults to linked project) | | `--deployment, -d` | string | Filter to specific deployment ID or URL | | `--environment` | string | `production` or `preview` | | `--level` | string[] | `error`, `warning`, `info`, `fatal` (repeatable) | | `--status-code` | string | HTTP status code filter (e.g., `500`, `4xx`) | | `--source` | string[] | `serverless`, `edge-function`, `edge-middleware`, `static` | | `--since` | string | Start time (ISO date or relative: `1h`, `30m`, `2d`) | | `--until` | string | End time (default: now) | | `--limit, -n` | number | Maximum results (default: 100) | | `--json, -j` | boolean | Output as JSON Lines for piping | | `--query, -q` | string | Full-text search query | | `--request-id` | string | Filter by request ID | ## Agent-Native Design The command follows CLI best practices for automation: - **JSON Lines output** (`--json`): Each log entry is a separate JSON object on its own line - **stdout/stderr separation**: Log data to stdout, status messages to stderr - **Clear exit codes**: 0 = success, 1 = error, 2 = help displayed - **TTY detection**: Pretty output for terminals, plain for pipes - **NO_COLOR support**: Respects color preferences ## Usage Examples ```bash # View recent errors for linked project vercel logsv2 --level error --since 1h # Search logs with JSON output for jq processing vercel logsv2 --json --query "timeout" | jq '.statusCode' # Filter by deployment and status code vercel logsv2 --deployment dpl_abc123 --status-code 500 # Production errors in the last day vercel logsv2 --environment production --level error --since 1d # Filter by specific request ID vercel logsv2 --request-id req_xxxxx ``` ## Comparison: logs vs logsv2 | Feature | `logs` (v1) | `logsv2` (new) | |---------|-------------|----------------| | Scope | Single deployment | Project-wide (+ optional deployment filter) | | Data access | Real-time streaming | Historical via pagination | | Filtering | None (use jq) | level, source, status, environment, request ID, search | | Time range | "now" only | `--since` / `--until` | | API | `/v1/.../runtime-logs` (streaming) | `/api/logs/request-logs` (REST) | | Timeout | 5 minutes auto-abort | None | ## Breaking Changes None - this is a new hidden command. The existing `logs` command is unchanged. ## Rollout Strategy 1. **Phase 1 (this PR)**: Hidden `vercel logsv2` command for testing 2. **Phase 2**: Feature flag to redirect `vercel logs` → `logsv2` 3. **Phase 3**: Promote to default, deprecate v1 ## Test Plan - [x] Unit tests for `logs-v2.ts` utility (18 tests) - [x] Unit tests for `logsv2` command (34 tests) - [x] Manual testing with linked project - [x] Manual testing with `--project` flag - [x] Verify JSON output pipes correctly to `jq` - [ ] Test all filter combinations --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3bf2458 commit 168e320

File tree

13 files changed

+1709
-0
lines changed

13 files changed

+1709
-0
lines changed

.changeset/logsv2-command.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"vercel": patch
3+
---
4+
5+
Add hidden `logsv2` command with request-logs API support

packages/cli/src/commands/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { listCommand } from './list/command';
2222
import { loginCommand } from './login/command';
2323
import { logoutCommand } from './logout/command';
2424
import { logsCommand } from './logs/command';
25+
import { logsv2Command } from './logsv2/command';
2526
import { mcpCommand } from './mcp/command';
2627
import { microfrontendsCommand } from './microfrontends/command';
2728
import { openCommand } from './open/command';
@@ -67,6 +68,7 @@ const commandsStructs = [
6768
loginCommand,
6869
logoutCommand,
6970
logsCommand,
71+
logsv2Command,
7072
mcpCommand,
7173
microfrontendsCommand,
7274
openCommand,
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { packageName } from '../../util/pkg-name';
2+
3+
export const logsv2Command = {
4+
name: 'logsv2',
5+
aliases: [],
6+
description: 'Display request logs for a project using the new logs API.',
7+
hidden: true,
8+
arguments: [],
9+
options: [
10+
{
11+
name: 'project',
12+
shorthand: 'p',
13+
type: String,
14+
deprecated: false,
15+
description: 'Project ID or name (defaults to linked project)',
16+
},
17+
{
18+
name: 'deployment',
19+
shorthand: 'd',
20+
type: String,
21+
deprecated: false,
22+
description: 'Filter logs to a specific deployment ID or URL',
23+
},
24+
{
25+
name: 'environment',
26+
shorthand: null,
27+
type: String,
28+
deprecated: false,
29+
description: 'Filter by environment: production or preview',
30+
},
31+
{
32+
name: 'level',
33+
shorthand: null,
34+
type: [String],
35+
deprecated: false,
36+
description: 'Filter by log level: error, warning, info, fatal',
37+
},
38+
{
39+
name: 'status-code',
40+
shorthand: null,
41+
type: String,
42+
deprecated: false,
43+
description: 'Filter by HTTP status code (e.g., 500, 4xx)',
44+
},
45+
{
46+
name: 'source',
47+
shorthand: null,
48+
type: [String],
49+
deprecated: false,
50+
description:
51+
'Filter by source: serverless, edge-function, edge-middleware, static',
52+
},
53+
{
54+
name: 'since',
55+
shorthand: null,
56+
type: String,
57+
deprecated: false,
58+
description: 'Start time (ISO format or relative: 1h, 30m)',
59+
},
60+
{
61+
name: 'until',
62+
shorthand: null,
63+
type: String,
64+
deprecated: false,
65+
description: 'End time (ISO format or relative, default: now)',
66+
},
67+
{
68+
name: 'limit',
69+
shorthand: 'n',
70+
type: Number,
71+
deprecated: false,
72+
description: 'Maximum number of results (default: 100)',
73+
},
74+
{
75+
name: 'json',
76+
shorthand: 'j',
77+
type: Boolean,
78+
deprecated: false,
79+
description: 'Output logs as JSON Lines for piping to other tools',
80+
},
81+
{
82+
name: 'query',
83+
shorthand: 'q',
84+
type: String,
85+
deprecated: false,
86+
description: 'Full-text search query',
87+
},
88+
{
89+
name: 'request-id',
90+
shorthand: null,
91+
type: String,
92+
deprecated: false,
93+
description: 'Filter by request ID',
94+
},
95+
],
96+
examples: [
97+
{
98+
name: 'Display recent logs for the linked project',
99+
value: `${packageName} logsv2`,
100+
},
101+
{
102+
name: 'Display error logs from the last hour',
103+
value: `${packageName} logsv2 --level error --since 1h`,
104+
},
105+
{
106+
name: 'Display logs for a specific deployment',
107+
value: `${packageName} logsv2 --deployment dpl_xxxxx`,
108+
},
109+
{
110+
name: 'Filter logs by status code and output as JSON',
111+
value: `${packageName} logsv2 --status-code 500 --json`,
112+
},
113+
{
114+
name: 'Search logs and pipe to jq',
115+
value: `${packageName} logsv2 --query "timeout" --json | jq '.message'`,
116+
},
117+
{
118+
name: 'Display production logs only',
119+
value: `${packageName} logsv2 --environment production`,
120+
},
121+
{
122+
name: 'Display logs for a specific request',
123+
value: `${packageName} logsv2 --request-id req_xxxxx`,
124+
},
125+
],
126+
} as const;

0 commit comments

Comments
 (0)