observability

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Vercel Observability

Vercel可观测性

You are an expert in Vercel's observability stack — runtime logs, structured logging, Drains, Web Analytics, Speed Insights, and monitoring integrations. Always start with logging. When something is stuck, slow, or broken, the first step is always to check or add logs.
您是Vercel可观测性技术栈的专家 —— 涵盖运行时日志、结构化日志、Drains、Web Analytics、Speed Insights以及监控集成。始终从日志排查入手。 当应用出现卡顿、缓慢或故障时,第一步永远是检查或添加日志。

Structured Logging Baseline

结构化日志基准

Add this to every API route and server action as a minimum. If the user reports something stuck, hanging, or slow, verify this baseline exists first:
ts
const start = Date.now();
console.log(JSON.stringify({ level: "info", msg: "start", route: "/api/example", requestId: req.headers.get("x-vercel-id") }));
// ... your logic ...
console.log(JSON.stringify({ level: "info", msg: "done", route: "/api/example", ms: Date.now() - start }));
// On error:
console.error(JSON.stringify({ level: "error", msg: "failed", route: "/api/example", error: err.message, ms: Date.now() - start }));
请将此作为最低要求添加到每个API路由和服务器操作中。如果用户反馈应用出现卡顿、挂起或缓慢的情况,请首先确认是否已配置此基准:
ts
const start = Date.now();
console.log(JSON.stringify({ level: "info", msg: "start", route: "/api/example", requestId: req.headers.get("x-vercel-id") }));
// ... 您的业务逻辑 ...
console.log(JSON.stringify({ level: "info", msg: "done", route: "/api/example", ms: Date.now() - start }));
// 错误处理:
console.error(JSON.stringify({ level: "error", msg: "failed", route: "/api/example", error: err.message, ms: Date.now() - start }));

Runtime Logs

运行时日志

Vercel provides real-time logs for all function invocations.
Vercel为所有函数调用提供实时日志。

Structured Logging

结构化日志

ts
// app/api/process/route.ts
export async function POST(req: Request) {
  const start = Date.now()
  const data = await req.json()

  // Structured logs appear in Vercel's log viewer
  console.log(JSON.stringify({
    level: 'info',
    message: 'Processing request',
    requestId: req.headers.get('x-vercel-id'),
    payload_size: JSON.stringify(data).length,
  }))

  try {
    const result = await processData(data)
    console.log(JSON.stringify({
      level: 'info',
      message: 'Request completed',
      duration_ms: Date.now() - start,
    }))
    return Response.json(result)
  } catch (error) {
    console.error(JSON.stringify({
      level: 'error',
      message: 'Processing failed',
      error: error instanceof Error ? error.message : String(error),
      duration_ms: Date.now() - start,
    }))
    return Response.json({ error: 'Internal error' }, { status: 500 })
  }
}
ts
// app/api/process/route.ts
export async function POST(req: Request) {
  const start = Date.now()
  const data = await req.json()

  // 结构化日志会显示在Vercel的日志查看器中
  console.log(JSON.stringify({
    level: 'info',
    message: 'Processing request',
    requestId: req.headers.get('x-vercel-id'),
    payload_size: JSON.stringify(data).length,
  }))

  try {
    const result = await processData(data)
    console.log(JSON.stringify({
      level: 'info',
      message: 'Request completed',
      duration_ms: Date.now() - start,
    }))
    return Response.json(result)
  } catch (error) {
    console.error(JSON.stringify({
      level: 'error',
      message: 'Processing failed',
      error: error instanceof Error ? error.message : String(error),
      duration_ms: Date.now() - start,
    }))
    return Response.json({ error: 'Internal error' }, { status: 500 })
  }
}

Next.js Instrumentation

Next.js 观测配置

ts
// instrumentation.ts (Next.js 16)
export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    // Initialize monitoring on server startup
    const { initMonitoring } = await import('./lib/monitoring')
    initMonitoring()
  }
}
ts
// instrumentation.ts (Next.js 16)
export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    // 在服务器启动时初始化监控
    const { initMonitoring } = await import('./lib/monitoring')
    initMonitoring()
  }
}

Runtime Logs via REST API

通过REST API获取运行时日志

Query deployment runtime logs programmatically. The endpoint returns
application/stream+json
— a streaming response where each line is a separate JSON object.
bash
undefined
以编程方式查询部署的运行时日志。该端点返回
application/stream+json
格式的流式响应,每行是一个独立的JSON对象。
bash
undefined

Stream runtime logs for a deployment (returns application/stream+json)

流式获取部署的运行时日志(返回application/stream+json格式)

curl -N -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v3/deployments/<deployment-id>/events"
--max-time 120

> **Streaming guidance:** The response is unbounded — always set a timeout (`--max-time` in curl, `AbortController` with `setTimeout` in fetch). Parse line-by-line as NDJSON. Each line contains `{ timestamp, text, level, source }`.

```ts
// Programmatic streaming with timeout
const controller = new AbortController()
const timeout = setTimeout(() => controller.abort(), 60_000) // 60s max

const res = await fetch(
  `https://api.vercel.com/v3/deployments/${deploymentId}/events`,
  {
    headers: { Authorization: `Bearer ${process.env.VERCEL_TOKEN}` },
    signal: controller.signal,
  }
)

const reader = res.body!.getReader()
const decoder = new TextDecoder()
let buffer = ''

try {
  while (true) {
    const { done, value } = await reader.read()
    if (done) break
    buffer += decoder.decode(value, { stream: true })
    const lines = buffer.split('\n')
    buffer = lines.pop()! // keep incomplete line in buffer
    for (const line of lines) {
      if (!line.trim()) continue
      const event = JSON.parse(line)
      console.log(`[${event.level}] ${event.text}`)
    }
  }
} finally {
  clearTimeout(timeout)
}
MCP alternative: Use
get_runtime_logs
via the Vercel MCP server for agent-friendly log queries without managing streams directly. See
⤳ skill: vercel-api
.
curl -N -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v3/deployments/<deployment-id>/events"
--max-time 120

> **流式处理指南:** 响应是无界的 —— 务必设置超时时间(curl中使用`--max-time`,fetch中使用`AbortController`结合`setTimeout`)。按行解析NDJSON格式内容,每行包含`{ timestamp, text, level, source }`字段。

```ts
// 带超时的编程式流式处理
const controller = new AbortController()
const timeout = setTimeout(() => controller.abort(), 60_000) // 最大60秒

const res = await fetch(
  `https://api.vercel.com/v3/deployments/${deploymentId}/events`,
  {
    headers: { Authorization: `Bearer ${process.env.VERCEL_TOKEN}` },
    signal: controller.signal,
  }
)

const reader = res.body!.getReader()
const decoder = new TextDecoder()
let buffer = ''

try {
  while (true) {
    const { done, value } = await reader.read()
    if (done) break
    buffer += decoder.decode(value, { stream: true })
    const lines = buffer.split('\n')
    buffer = lines.pop()! // 保留不完整的行在缓冲区
    for (const line of lines) {
      if (!line.trim()) continue
      const event = JSON.parse(line)
      console.log(`[${event.level}] ${event.text}`)
    }
  }
} finally {
  clearTimeout(timeout)
}
MCP替代方案: 通过Vercel MCP服务器使用
get_runtime_logs
工具,无需直接管理流即可方便地查询日志。详见
⤳ skill: vercel-api

Web Analytics

Web Analytics

Privacy-friendly, first-party analytics with no cookie banners required.
隐私友好的第一方分析工具,无需Cookie提示横幅。

Installation

安装

bash
npm install @vercel/analytics
bash
npm install @vercel/analytics

Setup (Next.js App Router)

配置(Next.js App Router)

tsx
// app/layout.tsx
import { Analytics } from '@vercel/analytics/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
      </body>
    </html>
  )
}
tsx
// app/layout.tsx
import { Analytics } from '@vercel/analytics/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
      </body>
    </html>
  )
}

Custom Events (Pro/Enterprise)

自定义事件(专业版/企业版)

Track business-specific events beyond pageviews.
ts
import { track } from '@vercel/analytics'

// Track a conversion
track('purchase', {
  product: 'pro-plan',
  value: 20,
  currency: 'USD',
})

// Track a feature usage
track('feature_used', {
  name: 'ai-chat',
  duration_ms: 3200,
})
追踪页面浏览之外的业务特定事件。
ts
import { track } from '@vercel/analytics'

// 追踪转化事件
track('purchase', {
  product: 'pro-plan',
  value: 20,
  currency: 'USD',
})

// 追踪功能使用情况
track('feature_used', {
  name: 'ai-chat',
  duration_ms: 3200,
})

Server-Side Tracking

服务端追踪

ts
import { track } from '@vercel/analytics/server'

export async function POST(req: Request) {
  const data = await req.json()
  await processOrder(data)

  track('order_completed', {
    order_id: data.id,
    total: data.total,
  })

  return Response.json({ success: true })
}
ts
import { track } from '@vercel/analytics/server'

export async function POST(req: Request) {
  const data = await req.json()
  await processOrder(data)

  track('order_completed', {
    order_id: data.id,
    total: data.total,
  })

  return Response.json({ success: true })
}

Speed Insights

Speed Insights

Real-user performance monitoring built on Core Web Vitals.
基于Core Web Vitals的真实用户性能监控工具。

Installation

安装

bash
npm install @vercel/speed-insights
bash
npm install @vercel/speed-insights

Setup (Next.js App Router)

配置(Next.js App Router)

tsx
// app/layout.tsx
import { SpeedInsights } from '@vercel/speed-insights/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <SpeedInsights />
      </body>
    </html>
  )
}
tsx
// app/layout.tsx
import { SpeedInsights } from '@vercel/speed-insights/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <SpeedInsights />
      </body>
    </html>
  )
}

Metrics Tracked

追踪的指标

MetricWhat It MeasuresGood Threshold
LCPLargest Contentful Paint< 2.5s
INPInteraction to Next Paint< 200ms
CLSCumulative Layout Shift< 0.1
FCPFirst Contentful Paint< 1.8s
TTFBTime to First Byte< 800ms
指标测量内容良好阈值
LCP最大内容绘制< 2.5秒
INP交互到下一次绘制的时间< 200毫秒
CLS累积布局偏移< 0.1
FCP首次内容绘制< 1.8秒
TTFB首字节时间< 800毫秒

Performance Attribution

性能归因

Speed Insights attributes metrics to specific routes and pages, letting you identify which pages are slow and why.
Speed Insights会将指标关联到特定路由和页面,帮助您识别哪些页面缓慢以及原因。

Drains

Drains

Drains forward observability data from Vercel to external endpoints. They are the primary mechanism for exporting logs, traces, Speed Insights, and Web Analytics data to third-party platforms.
Plan requirement: Drains require a Pro or Enterprise plan. For Hobby plans, see the Fallback Guidance section below.
Drains可将Vercel的可观测性数据转发到外部端点,是将日志、追踪、Speed Insights和Web Analytics数据导出到第三方平台的主要机制。
套餐要求: Drains需要专业版或企业版套餐。对于免费版套餐,请查看下方的备选方案部分。

Data Types

数据类型

Drains can forward multiple categories of telemetry:
Data TypeWhat It ContainsUse Case
LogsRuntime function logs, build logs, static access logsCentralized log aggregation
TracesOpenTelemetry-compatible distributed tracesEnd-to-end request tracing
Speed InsightsCore Web Vitals and performance metricsPerformance monitoring pipelines
Web AnalyticsPageviews, custom events, visitor dataAnalytics data warehousing
Drains可转发多种类别的遥测数据:
数据类型包含内容使用场景
日志运行时函数日志、构建日志、静态资源访问日志集中式日志聚合
追踪兼容OpenTelemetry的分布式追踪端到端请求追踪
Speed InsightsCore Web Vitals和性能指标性能监控流水线
Web Analytics页面浏览、自定义事件、访问者数据分析数据仓库

Supported Formats

支持的格式

FormatProtocolBest For
JSONHTTPS POSTCustom backends, generic log collectors
NDJSONHTTPS POSTStreaming-friendly consumers, high-volume pipelines
SyslogTLS syslogTraditional log management (rsyslog, syslog-ng)
格式协议最佳适用场景
JSONHTTPS POST自定义后端、通用日志收集器
NDJSONHTTPS POST流式处理消费者、高容量流水线
SyslogTLS syslog传统日志管理系统(rsyslog、syslog-ng)

Setting Up Drains

配置Drains

Drains are configured via the Vercel Dashboard at
https://vercel.com/dashboard/{team}/~/settings/log-drains
or the REST API.
Drains可通过Vercel仪表板(地址:
https://vercel.com/dashboard/{team}/~/settings/log-drains
)或REST API进行配置。

Via Dashboard

通过仪表板

  1. Open
    https://vercel.com/dashboard/{team}/~/settings/log-drains
    (replace
    {team}
    with your team slug)
  2. Click Add Log Drain
  3. Select the drain type (JSON, NDJSON, or syslog) and enter the endpoint URL
  4. Choose which environments and sources to include
  5. Click Create to activate the drain
  1. 打开
    https://vercel.com/dashboard/{team}/~/settings/log-drains
    (将
    {team}
    替换为您的团队别名)
  2. 点击添加日志 Drain
  3. 选择Drain类型(JSON、NDJSON或syslog)并输入端点URL
  4. 选择要包含的环境和数据源
  5. 点击创建以激活Drain

Via REST API (
/v1/drains
)

通过REST API(
/v1/drains

bash
undefined
bash
undefined

List all drains

列出所有Drains

curl -s -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v1/drains?teamId=$TEAM_ID" | jq
curl -s -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v1/drains?teamId=$TEAM_ID" | jq

Create a JSON drain

创建一个JSON格式的Drain

curl -X POST -H "Authorization: Bearer $VERCEL_TOKEN"
-H "Content-Type: application/json"
"https://api.vercel.com/v1/drains?teamId=$TEAM_ID"
-d '{ "url": "https://your-endpoint.example.com/logs", "type": "json", "sources": ["lambda", "edge", "static"], "environments": ["production"] }'
curl -X POST -H "Authorization: Bearer $VERCEL_TOKEN"
-H "Content-Type: application/json"
"https://api.vercel.com/v1/drains?teamId=$TEAM_ID"
-d '{ "url": "https://your-endpoint.example.com/logs", "type": "json", "sources": ["lambda", "edge", "static"], "environments": ["production"] }'

Test a drain (sends a test payload to your endpoint)

测试Drain(向您的端点发送测试负载)

curl -X POST -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v1/drains/<drain-id>/test?teamId=$TEAM_ID"
curl -X POST -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v1/drains/<drain-id>/test?teamId=$TEAM_ID"

Update a drain (change URL, sources, or environments)

更新Drain(修改URL、数据源或环境)

curl -X PATCH -H "Authorization: Bearer $VERCEL_TOKEN"
-H "Content-Type: application/json"
"https://api.vercel.com/v1/drains/<drain-id>?teamId=$TEAM_ID"
-d '{ "url": "https://new-endpoint.example.com/logs", "environments": ["production", "preview"] }'
curl -X PATCH -H "Authorization: Bearer $VERCEL_TOKEN"
-H "Content-Type: application/json"
"https://api.vercel.com/v1/drains/<drain-id>?teamId=$TEAM_ID"
-d '{ "url": "https://new-endpoint.example.com/logs", "environments": ["production", "preview"] }'

Delete a drain

删除Drain

curl -X DELETE -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v1/drains/<drain-id>?teamId=$TEAM_ID"
undefined
curl -X DELETE -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v1/drains/<drain-id>?teamId=$TEAM_ID"
undefined

Web Analytics Drains Reference

Web Analytics Drains参考

When a drain is configured to receive Web Analytics data, payloads arrive as batched events. The format depends on your drain type.
当Drain配置为接收Web Analytics数据时,负载会以批量事件的形式到达,格式取决于您选择的Drain类型。

JSON Payload Schema

JSON负载结构

json
[
  {
    "type": "pageview",
    "url": "https://example.com/blog/post-1",
    "referrer": "https://google.com",
    "timestamp": 1709568000000,
    "geo": { "country": "US", "region": "CA", "city": "San Francisco" },
    "device": { "os": "macOS", "browser": "Chrome", "isBot": false },
    "projectId": "prj_xxxxx",
    "environment": "production"
  },
  {
    "type": "custom_event",
    "name": "purchase",
    "url": "https://example.com/checkout",
    "properties": { "product": "pro-plan", "value": 20 },
    "timestamp": 1709568100000,
    "geo": { "country": "US" },
    "device": { "os": "macOS", "browser": "Chrome", "isBot": false },
    "projectId": "prj_xxxxx",
    "environment": "production"
  }
]
json
[
  {
    "type": "pageview",
    "url": "https://example.com/blog/post-1",
    "referrer": "https://google.com",
    "timestamp": 1709568000000,
    "geo": { "country": "US", "region": "CA", "city": "San Francisco" },
    "device": { "os": "macOS", "browser": "Chrome", "isBot": false },
    "projectId": "prj_xxxxx",
    "environment": "production"
  },
  {
    "type": "custom_event",
    "name": "purchase",
    "url": "https://example.com/checkout",
    "properties": { "product": "pro-plan", "value": 20 },
    "timestamp": 1709568100000,
    "geo": { "country": "US" },
    "device": { "os": "macOS", "browser": "Chrome", "isBot": false },
    "projectId": "prj_xxxxx",
    "environment": "production"
  }
]

NDJSON Payload Format

NDJSON负载格式

Each line is a separate JSON object (one event per line):
{"type":"pageview","url":"https://example.com/","timestamp":1709568000000,"geo":{"country":"US"},"device":{"browser":"Chrome"},...}
{"type":"pageview","url":"https://example.com/about","timestamp":1709568001000,"geo":{"country":"DE"},"device":{"browser":"Firefox"},...}
{"type":"custom_event","name":"signup","url":"https://example.com/register","timestamp":1709568002000,...}
Ingestion tip: For NDJSON, process line-by-line as events arrive. This format is preferred for high-volume pipelines where batch parsing overhead matters.
每行是一个独立的JSON对象(每行一个事件):
{"type":"pageview","url":"https://example.com/","timestamp":1709568000000,"geo":{"country":"US"},"device":{"browser":"Chrome"},...}
{"type":"pageview","url":"https://example.com/about","timestamp":1709568001000,"geo":{"country":"DE"},"device":{"browser":"Firefox"},...}
{"type":"custom_event","name":"signup","url":"https://example.com/register","timestamp":1709568002000,...}
摄入提示: 对于NDJSON格式,事件到达时按行处理。这种格式适用于高容量流水线,因为批量解析的开销更低。

Security: Signature Verification

安全:签名验证

Vercel signs every drain payload with an HMAC-SHA1 signature in the
x-vercel-signature
header. Always verify signatures in production to prevent spoofed data.
Critical: You must verify against the raw request body (not a parsed/re-serialized version). JSON parsing and re-stringifying can change key order or whitespace, breaking the signature match.
ts
import { createHmac, timingSafeEqual } from 'crypto'

function verifyDrainSignature(rawBody: string, signature: string, secret: string): boolean {
  const expected = createHmac('sha1', secret).update(rawBody).digest('hex')
  // Use timing-safe comparison to prevent timing attacks
  if (expected.length !== signature.length) return false
  return timingSafeEqual(Buffer.from(expected), Buffer.from(signature))
}
Usage in a drain endpoint:
ts
// app/api/drain/route.ts
export async function POST(req: Request) {
  const rawBody = await req.text()
  const signature = req.headers.get('x-vercel-signature')
  const secret = process.env.DRAIN_SECRET!

  if (!signature || !verifyDrainSignature(rawBody, signature, secret)) {
    return new Response('Unauthorized', { status: 401 })
  }

  const events = JSON.parse(rawBody)
  // Process verified events...
  return new Response('OK', { status: 200 })
}
Secret management: The drain signing secret is shown once when you create the drain. Store it in an environment variable (e.g.,
DRAIN_SECRET
). If lost, delete and recreate the drain.
Vercel会在
x-vercel-signature
头中使用HMAC-SHA1签名每个Drain负载。生产环境中务必验证签名以防止伪造数据。
关键提示: 您必须针对原始请求体进行验证(而非解析后重新序列化的版本)。JSON解析和重新序列化可能会改变键的顺序或空格,导致签名匹配失败。
ts
import { createHmac, timingSafeEqual } from 'crypto'

function verifyDrainSignature(rawBody: string, signature: string, secret: string): boolean {
  const expected = createHmac('sha1', secret).update(rawBody).digest('hex')
  // 使用时序安全的比较以防止时序攻击
  if (expected.length !== signature.length) return false
  return timingSafeEqual(Buffer.from(expected), Buffer.from(signature))
}
在Drain端点中的使用示例:
ts
// app/api/drain/route.ts
export async function POST(req: Request) {
  const rawBody = await req.text()
  const signature = req.headers.get('x-vercel-signature')
  const secret = process.env.DRAIN_SECRET!

  if (!signature || !verifyDrainSignature(rawBody, signature, secret)) {
    return new Response('Unauthorized', { status: 401 })
  }

  const events = JSON.parse(rawBody)
  // 处理已验证的事件...
  return new Response('OK', { status: 200 })
}
密钥管理: Drain签名密钥在您创建Drain时仅显示一次。请将其存储在环境变量中(例如
DRAIN_SECRET
)。如果丢失,请删除并重新创建Drain。

OpenTelemetry Integration

OpenTelemetry集成

Vercel exports traces in OpenTelemetry-compatible format via Drains. Configure an OTel-compatible drain endpoint at
https://vercel.com/dashboard/{team}/~/settings/log-drains
Add Log Drain → select OTLP format, or via the REST API.
Vercel通过Drains以兼容OpenTelemetry的格式导出追踪数据。您可以在
https://vercel.com/dashboard/{team}/~/settings/log-drains
添加日志Drain → 选择OTLP格式进行配置,或通过REST API配置。

Vendor Integrations

厂商集成

bash
undefined
bash
undefined

Install via Marketplace (recommended — auto-configures drain)

通过市场安装(推荐 —— 自动配置Drain)

vercel integration add datadog

Or manually create a drain at `https://vercel.com/dashboard/{team}/~/settings/log-drains` → **Add Log Drain**, or via REST API, pointing to:

| Vendor | Endpoint | Auth Header |
|--------|----------|-------------|
| **Datadog** | `https://http-intake.logs.datadoghq.com/api/v2/logs` | `DD-API-KEY` |
| **Honeycomb** | `https://api.honeycomb.io/1/batch/<dataset>` | `X-Honeycomb-Team` |
vercel integration add datadog

或者手动在`https://vercel.com/dashboard/{team}/~/settings/log-drains` → **添加日志Drain**创建Drain,或通过REST API将其指向以下端点:

| 厂商 | 端点 | 认证头 |
|--------|----------|-------------|
| **Datadog** | `https://http-intake.logs.datadoghq.com/api/v2/logs` | `DD-API-KEY` |
| **Honeycomb** | `https://api.honeycomb.io/1/batch/<dataset>` | `X-Honeycomb-Team` |

Fallback Guidance (No Drains)

备选方案(无Drains)

If drains are unavailable (Hobby plan or not yet configured), use these alternatives:
NeedAlternativeHow
View runtime logsVercel Dashboard
https://vercel.com/{team}/{project}/deployments
→ select deployment → Logs tab
Stream logs from terminalVercel CLI
vercel logs <deployment-url> --follow
(see
⤳ skill: vercel-cli
)
Query logs programmaticallyMCP / REST API
get_runtime_logs
tool or
/v3/deployments/:id/events
(see
⤳ skill: vercel-api
)
Monitor errors post-deployCLI
vercel logs <url> --level error --since 1h
Web Analytics dataDashboard only
https://vercel.com/{team}/{project}/analytics
Performance metricsDashboard only
https://vercel.com/{team}/{project}/speed-insights
Upgrade path: When ready for centralized observability, upgrade to Pro and configure drains at
https://vercel.com/dashboard/{team}/~/settings/log-drains
or via REST API. The drain setup is typically < 5 minutes.
如果无法使用Drains(免费版套餐或尚未配置),请使用以下替代方案:
需求替代方案操作方式
查看运行时日志Vercel仪表板
https://vercel.com/{team}/{project}/deployments
→ 选择部署 → 日志标签页
从终端流式查看日志Vercel CLI
vercel logs <deployment-url> --follow
(详见
⤳ skill: vercel-cli
以编程方式查询日志MCP / REST API使用
get_runtime_logs
工具或
/v3/deployments/:id/events
端点(详见
⤳ skill: vercel-api
部署后监控错误CLI
vercel logs <url> --level error --since 1h
Web Analytics数据仅仪表板
https://vercel.com/{team}/{project}/analytics
性能指标仅仪表板
https://vercel.com/{team}/{project}/speed-insights
升级路径: 当需要集中式可观测性时,升级到专业版套餐并在
https://vercel.com/dashboard/{team}/~/settings/log-drains
或通过REST API配置Drains。配置Drains通常只需不到5分钟。

Deploy Preflight Observability

部署前可观测性检查

Before promoting to production, verify observability readiness:
  • Drains check: Query configured drains via MCP
    list_drains
    or REST API. If no drains are configured on a Pro/Enterprise plan, warn:
    ⚠️ No drains configured. Production errors won't be forwarded to external monitoring. Configure drains via Dashboard or REST API before promoting. See
    ⤳ skill: observability
    .
  • Errored drains: If any drain is in error state, warn and suggest remediation before deploying:
    ⚠️ Drain "<url>" is errored. Fix or recreate before production deploy to avoid monitoring gaps.
  • Error monitoring: Check that at least one of these is in place: configured drains, an error tracking integration (e.g., Sentry, Datadog via
    vercel integration ls
    ), or
    @vercel/analytics
    in the project.
  • These are warnings, not blockers — the user may proceed after acknowledgment.
在将部署推广到生产环境之前,请验证可观测性是否就绪:
  • Drains检查:通过MCP的
    list_drains
    工具或REST API查询已配置的Drains。如果专业版/企业版套餐下未配置Drains,请发出警告:
    ⚠️ 未配置Drains。生产环境中的错误不会转发到外部监控系统。 请在推广前通过仪表板或REST API配置Drains。详见
    ⤳ skill: observability
  • 异常Drains:如果任何Drains处于错误状态,请发出警告并建议在部署前进行修复:
    ⚠️ Drain "<url>" 处于错误状态。请在生产部署前修复或重新创建,以避免监控中断。
  • 错误监控:确保至少配置了以下其中一项:已配置的Drains、错误追踪集成(例如Sentry、Datadog,可通过
    vercel integration ls
    查看),或项目中已安装
    @vercel/analytics
  • 以上均为警告,而非阻止项 —— 用户确认后可继续操作。

Post-Deploy Error Scan

部署后错误扫描

For production deployments, wait 60 seconds after READY state, then scan for early runtime errors:
bash
vercel logs <deployment-url> --level error --since 1h
Or via MCP if available: use
get_runtime_logs
with level filter
error
.
Interpret results:
FindingAction
No errors✓ Clean deploy — no runtime errors in first hour
Errors detectedList error count and first 5 unique error messages. Suggest: check drain payloads for correlated traces, review function logs in Dashboard
500 status codes in logsCorrelate timestamps with drain data (if configured) or
vercel logs <url> --json
for structured output. Flag for immediate investigation
Timeout errorsCheck function duration limits in
vercel.json
or project settings. Consider increasing
maxDuration
Fallback (no drains):
If no drains are configured, the error scan relies on CLI and Dashboard:
bash
undefined
对于生产环境部署,在应用进入READY状态后等待60秒,然后扫描早期运行时错误:
bash
vercel logs <deployment-url> --level error --since 1h
如果有MCP可用,也可以使用
get_runtime_logs
工具并设置级别过滤器为
error
结果解读:
发现操作建议
无错误✓ 部署干净 —— 第一小时内无运行时错误
检测到错误列出错误数量和前5条唯一错误信息。建议:检查Drains负载中的相关追踪,在仪表板中查看函数日志
日志中存在500状态码将时间戳与Drains数据(已配置的话)或
vercel logs <url> --json
的结构化输出关联。标记为需要立即调查
超时错误检查
vercel.json
或项目设置中的函数时长限制。考虑增加
maxDuration
备选方案(无Drains):
如果未配置Drains,错误扫描依赖于CLI和仪表板:
bash
undefined

Stream live errors

流式查看实时错误

vercel logs <deployment-url> --level error --follow
vercel logs <deployment-url> --level error --follow

JSON output for parsing

输出JSON格式以便解析

vercel logs <deployment-url> --level error --since 1h --json

> For richer post-deploy monitoring, configure drains to forward logs/traces to an external platform. See `⤳ skill: observability`.
vercel logs <deployment-url> --level error --since 1h --json

> 如需更丰富的部署后监控,请配置Drains将日志/追踪转发到外部平台。详见`⤳ skill: observability`。

Performance Audit Checklist

性能审计清单

Run through this when asked to optimize a Vercel application:
  1. Measure first: Check Speed Insights dashboard for real-user CWV data
  2. Identify LCP element: Use Chrome DevTools → Performance → identify the LCP element
  3. Audit
    'use client'
    : Every
    'use client'
    file ships JS to the browser — minimize
  4. Check images: All above-fold images use
    next/image
    with
    priority
  5. Check fonts: All fonts loaded via
    next/font
    (zero CLS)
  6. Check third-party scripts: All use
    next/script
    with correct strategy
  7. Check data fetching: Server Components fetch in parallel, no waterfalls
  8. Check caching: Cache Components used for expensive operations
  9. Check bundle: Run analyzer, look for low-hanging fruit
  10. Check infrastructure: Functions in correct region, Fluid Compute enabled
当被要求优化Vercel应用时,请按以下步骤执行:
  1. 先测量:查看Speed Insights仪表板获取真实用户的CWV数据
  2. 识别LCP元素:使用Chrome DevTools → 性能面板 → 识别LCP元素
  3. 审核
    'use client'
    :每个
    'use client'
    文件都会向浏览器发送JS —— 尽量减少使用
  4. 检查图片:所有首屏图片都使用
    next/image
    并设置
    priority
  5. 检查字体:所有字体都通过
    next/font
    加载(零CLS)
  6. 检查第三方脚本:所有脚本都使用
    next/script
    并设置正确的策略
  7. 检查数据获取:服务器组件并行获取数据,避免瀑布流
  8. 检查缓存:对执行昂贵操作的组件进行缓存
  9. 检查打包文件:运行分析工具,寻找容易优化的点
  10. 检查基础设施:函数部署在正确的区域,启用Fluid Compute

Monitoring Dashboard Patterns

监控仪表板模式

Full-Stack Observability Setup

全栈可观测性配置

Combine all Vercel observability tools for comprehensive coverage.
tsx
// app/layout.tsx — complete observability setup
import { Analytics } from '@vercel/analytics/next'
import { SpeedInsights } from '@vercel/speed-insights/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
        <SpeedInsights />
      </body>
    </html>
  )
}
结合所有Vercel可观测性工具实现全面覆盖。
tsx
// app/layout.tsx —— 完整的可观测性配置
import { Analytics } from '@vercel/analytics/next'
import { SpeedInsights } from '@vercel/speed-insights/next'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
        <SpeedInsights />
      </body>
    </html>
  )
}

Custom Monitoring with
waitUntil

使用
waitUntil
实现自定义监控

Fire-and-forget telemetry that doesn't block responses.
ts
import { waitUntil } from '@vercel/functions'

export async function GET(req: Request) {
  const start = Date.now()
  const result = await fetchData()

  // Send response immediately
  const response = Response.json(result)

  // Report metrics in background
  waitUntil(async () => {
    await reportMetric('api_latency', Date.now() - start, {
      route: '/api/data',
      status: 200,
    })
  })

  return response
}
发送无需阻塞响应的即发即弃式遥测数据。
ts
import { waitUntil } from '@vercel/functions'

export async function GET(req: Request) {
  const start = Date.now()
  const result = await fetchData()

  // 立即发送响应
  const response = Response.json(result)

  // 在后台上报指标
  waitUntil(async () => {
    await reportMetric('api_latency', Date.now() - start, {
      route: '/api/data',
      status: 200,
    })
  })

  return response
}

Error Tracking Pattern

错误追踪模式

ts
// lib/error-reporting.ts
export async function reportError(error: unknown, context: Record<string, unknown>) {
  const payload = {
    message: error instanceof Error ? error.message : String(error),
    stack: error instanceof Error ? error.stack : undefined,
    timestamp: new Date().toISOString(),
    ...context,
  }

  // Log for Vercel's runtime logs
  console.error(JSON.stringify(payload))

  // Also send to external service if configured
  if (process.env.ERROR_WEBHOOK_URL) {
    await fetch(process.env.ERROR_WEBHOOK_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    })
  }
}
ts
// lib/error-reporting.ts
export async function reportError(error: unknown, context: Record<string, unknown>) {
  const payload = {
    message: error instanceof Error ? error.message : String(error),
    stack: error instanceof Error ? error.stack : undefined,
    timestamp: new Date().toISOString(),
    ...context,
  }

  // 记录到Vercel的运行时日志
  console.error(JSON.stringify(payload))

  // 如果已配置,同时发送到外部服务
  if (process.env.ERROR_WEBHOOK_URL) {
    await fetch(process.env.ERROR_WEBHOOK_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    })
  }
}

Marketplace Observability Integrations

市场可观测性集成

Sentry — Error & Performance Monitoring

Sentry —— 错误与性能监控

Native Vercel Marketplace integration. Auto-configures source maps and release tracking.
bash
npx @sentry/wizard@latest -i nextjs
Vercel市场原生集成,自动配置源映射和版本追踪。
bash
npx @sentry/wizard@latest -i nextjs

Or install manually:

或手动安装:

npm install @sentry/nextjs

Sentry wizard creates `sentry.client.config.ts`, `sentry.server.config.ts`, and `sentry.edge.config.ts`. It also wraps `next.config.js` with `withSentryConfig`.

Install via Marketplace: `vercel integration add sentry`
npm install @sentry/nextjs

Sentry向导会创建`sentry.client.config.ts`、`sentry.server.config.ts`和`sentry.edge.config.ts`文件,并使用`withSentryConfig`包装`next.config.js`。

通过市场安装:`vercel integration add sentry`

Datadog — Full-Stack Monitoring

Datadog —— 全栈监控

APM, logs, and Real User Monitoring (RUM). Auto-configures log drain on Marketplace install.
bash
npm install @datadog/browser-rum
ts
import { datadogRum } from '@datadog/browser-rum'

datadogRum.init({
  applicationId: process.env.NEXT_PUBLIC_DD_APPLICATION_ID!,
  clientToken: process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN!,
  site: 'datadoghq.com',
  service: 'my-app',
  sessionSampleRate: 100,
  trackResources: true,
  trackLongTasks: true,
})
Install via Marketplace:
vercel integration add datadog
提供APM、日志和真实用户监控(RUM),市场安装时自动配置日志Drain。
bash
npm install @datadog/browser-rum
ts
import { datadogRum } from '@datadog/browser-rum'

datadogRum.init({
  applicationId: process.env.NEXT_PUBLIC_DD_APPLICATION_ID!,
  clientToken: process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN!,
  site: 'datadoghq.com',
  service: 'my-app',
  sessionSampleRate: 100,
  trackResources: true,
  trackLongTasks: true,
})
通过市场安装:
vercel integration add datadog

Checkly — Synthetic Monitoring & Testing

Checkly —— 合成监控与测试

API and browser checks that run continuously against your deployments.
bash
npm install -D checkly
npx checkly init
Checkly integrates with Vercel deployment events to trigger checks on every deploy.
Install via Marketplace:
vercel integration add checkly
持续对您的部署运行API和浏览器检查。
bash
npm install -D checkly
npx checkly init
Checkly与Vercel部署事件集成,每次部署时自动触发检查。
通过市场安装:
vercel integration add checkly

New Relic — Application Performance Monitoring

New Relic —— 应用性能监控

Full-stack observability with distributed tracing and alerting.
bash
npm install newrelic
Requires a
newrelic.js
config file at the project root. Install via Marketplace:
vercel integration add newrelic
提供全栈可观测性,支持分布式追踪和告警。
bash
npm install newrelic
需要在项目根目录创建
newrelic.js
配置文件。通过市场安装:
vercel integration add newrelic

Decision Matrix

决策矩阵

NeedUseWhy
Page views, traffic sourcesWeb AnalyticsFirst-party, privacy-friendly
Business event trackingWeb Analytics custom eventsTrack conversions, feature usage
Core Web Vitals monitoringSpeed InsightsReal user data per route
Function debuggingRuntime Logs (CLI
vercel logs
/ Dashboard (
https://vercel.com/{team}/{project}/logs
) / REST)
Real-time, per-invocation logs
Export logs to external platformDrains (JSON/NDJSON/Syslog)Centralize observability (Pro+)
Export analytics dataDrains (Web Analytics type)Warehouse pageviews + custom events (Pro+)
OpenTelemetry tracesDrains (OTel-compatible endpoint)Standards-based distributed tracing (Pro+)
Post-response telemetry
waitUntil
+ custom reporting
Non-blocking metrics
Server-side event tracking
@vercel/analytics/server
Track API-triggered events
Hobby plan log accessCLI
vercel logs
+ Dashboard (
https://vercel.com/{team}/{project}/logs
)
No drains needed
需求使用工具原因
页面浏览、流量来源Web Analytics第一方数据,隐私友好
业务事件追踪Web Analytics自定义事件追踪转化、功能使用情况
Core Web Vitals监控Speed Insights基于真实用户的路由级数据
函数调试运行时日志(CLI
vercel logs
/ 仪表板 (
https://vercel.com/{team}/{project}/logs
) / REST API)
实时、按调用维度的日志
将日志导出到外部平台Drains(JSON/NDJSON/Syslog)集中式可观测性(专业版+)
导出分析数据Drains(Web Analytics类型)存储页面浏览+自定义事件数据(专业版+)
OpenTelemetry追踪Drains(兼容OTel的端点)基于标准的分布式追踪(专业版+)
响应后遥测
waitUntil
+ 自定义上报
非阻塞式指标上报
服务端事件追踪
@vercel/analytics/server
追踪API触发的事件
免费版套餐日志访问CLI
vercel logs
+ 仪表板 (
https://vercel.com/{team}/{project}/logs
)
无需Drains

Cross-References

交叉引用

  • Drains REST API & runtime logs endpoint
    ⤳ skill: vercel-api
    (Observability APIs section)
  • CLI log streaming (
    --follow
    ,
    --since
    ,
    --level
    )
    ⤳ skill: vercel-cli
    (Logs & Inspection section)
  • Marketplace vendor integrations
    ⤳ skill: marketplace
  • Drains REST API & 运行时日志端点
    ⤳ skill: vercel-api
    (可观测性API部分)
  • CLI日志流式处理(
    --follow
    ,
    --since
    ,
    --level
    ⤳ skill: vercel-cli
    (日志与检查部分)
  • 市场厂商集成
    ⤳ skill: marketplace

Official Documentation

官方文档