observability
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVercel 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 — a streaming response where each line is a separate JSON object.
application/stream+jsonbash
undefined以编程方式查询部署的运行时日志。该端点返回格式的流式响应,每行是一个独立的JSON对象。
application/stream+jsonbash
undefinedStream 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
"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: Usevia the Vercel MCP server for agent-friendly log queries without managing streams directly. Seeget_runtime_logs.⤳ skill: vercel-api
curl -N -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v3/deployments/<deployment-id>/events"
--max-time 120
"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/analyticsbash
npm install @vercel/analyticsSetup (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-insightsbash
npm install @vercel/speed-insightsSetup (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
追踪的指标
| Metric | What It Measures | Good Threshold |
|---|---|---|
| LCP | Largest Contentful Paint | < 2.5s |
| INP | Interaction to Next Paint | < 200ms |
| CLS | Cumulative Layout Shift | < 0.1 |
| FCP | First Contentful Paint | < 1.8s |
| TTFB | Time 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 Type | What It Contains | Use Case |
|---|---|---|
| Logs | Runtime function logs, build logs, static access logs | Centralized log aggregation |
| Traces | OpenTelemetry-compatible distributed traces | End-to-end request tracing |
| Speed Insights | Core Web Vitals and performance metrics | Performance monitoring pipelines |
| Web Analytics | Pageviews, custom events, visitor data | Analytics data warehousing |
Drains可转发多种类别的遥测数据:
| 数据类型 | 包含内容 | 使用场景 |
|---|---|---|
| 日志 | 运行时函数日志、构建日志、静态资源访问日志 | 集中式日志聚合 |
| 追踪 | 兼容OpenTelemetry的分布式追踪 | 端到端请求追踪 |
| Speed Insights | Core Web Vitals和性能指标 | 性能监控流水线 |
| Web Analytics | 页面浏览、自定义事件、访问者数据 | 分析数据仓库 |
Supported Formats
支持的格式
| Format | Protocol | Best For |
|---|---|---|
| JSON | HTTPS POST | Custom backends, generic log collectors |
| NDJSON | HTTPS POST | Streaming-friendly consumers, high-volume pipelines |
| Syslog | TLS syslog | Traditional log management (rsyslog, syslog-ng) |
| 格式 | 协议 | 最佳适用场景 |
|---|---|---|
| JSON | HTTPS POST | 自定义后端、通用日志收集器 |
| NDJSON | HTTPS POST | 流式处理消费者、高容量流水线 |
| Syslog | TLS syslog | 传统日志管理系统(rsyslog、syslog-ng) |
Setting Up Drains
配置Drains
Drains are configured via the Vercel Dashboard at or the REST API.
https://vercel.com/dashboard/{team}/~/settings/log-drainsDrains可通过Vercel仪表板(地址:)或REST API进行配置。
https://vercel.com/dashboard/{team}/~/settings/log-drainsVia Dashboard
通过仪表板
- Open (replace
https://vercel.com/dashboard/{team}/~/settings/log-drainswith your team slug){team} - Click Add Log Drain
- Select the drain type (JSON, NDJSON, or syslog) and enter the endpoint URL
- Choose which environments and sources to include
- Click Create to activate the drain
- 打开(将
https://vercel.com/dashboard/{team}/~/settings/log-drains替换为您的团队别名){team} - 点击添加日志 Drain
- 选择Drain类型(JSON、NDJSON或syslog)并输入端点URL
- 选择要包含的环境和数据源
- 点击创建以激活Drain
Via REST API (/v1/drains
)
/v1/drains通过REST API(/v1/drains
)
/v1/drainsbash
undefinedbash
undefinedList all drains
列出所有Drains
curl -s -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v1/drains?teamId=$TEAM_ID" | jq
"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
"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"] }'
-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"] }'
-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"
"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"
"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"] }'
-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"] }'
-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"
"https://api.vercel.com/v1/drains/<drain-id>?teamId=$TEAM_ID"
undefinedcurl -X DELETE -H "Authorization: Bearer $VERCEL_TOKEN"
"https://api.vercel.com/v1/drains/<drain-id>?teamId=$TEAM_ID"
"https://api.vercel.com/v1/drains/<drain-id>?teamId=$TEAM_ID"
undefinedWeb 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 header. Always verify signatures in production to prevent spoofed data.
x-vercel-signatureCritical: 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.,). If lost, delete and recreate the drain.DRAIN_SECRET
Vercel会在头中使用HMAC-SHA1签名每个Drain负载。生产环境中务必验证签名以防止伪造数据。
x-vercel-signature关键提示: 您必须针对原始请求体进行验证(而非解析后重新序列化的版本)。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。DRAIN_SECRET
OpenTelemetry Integration
OpenTelemetry集成
Vercel exports traces in OpenTelemetry-compatible format via Drains. Configure an OTel-compatible drain endpoint at → Add Log Drain → select OTLP format, or via the REST API.
https://vercel.com/dashboard/{team}/~/settings/log-drainsVercel通过Drains以兼容OpenTelemetry的格式导出追踪数据。您可以在 → 添加日志Drain → 选择OTLP格式进行配置,或通过REST API配置。
https://vercel.com/dashboard/{team}/~/settings/log-drainsVendor Integrations
厂商集成
bash
undefinedbash
undefinedInstall 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:
| Need | Alternative | How |
|---|---|---|
| View runtime logs | Vercel Dashboard | |
| Stream logs from terminal | Vercel CLI | |
| Query logs programmatically | MCP / REST API | |
| Monitor errors post-deploy | CLI | |
| Web Analytics data | Dashboard only | |
| Performance metrics | Dashboard only | |
Upgrade path: When ready for centralized observability, upgrade to Pro and configure drains ator via REST API. The drain setup is typically < 5 minutes.https://vercel.com/dashboard/{team}/~/settings/log-drains
如果无法使用Drains(免费版套餐或尚未配置),请使用以下替代方案:
| 需求 | 替代方案 | 操作方式 |
|---|---|---|
| 查看运行时日志 | Vercel仪表板 | |
| 从终端流式查看日志 | Vercel CLI | |
| 以编程方式查询日志 | MCP / REST API | 使用 |
| 部署后监控错误 | CLI | |
| Web Analytics数据 | 仅仪表板 | |
| 性能指标 | 仅仪表板 | |
升级路径: 当需要集中式可观测性时,升级到专业版套餐并在或通过REST API配置Drains。配置Drains通常只需不到5分钟。https://vercel.com/dashboard/{team}/~/settings/log-drains
Deploy Preflight Observability
部署前可观测性检查
Before promoting to production, verify observability readiness:
- Drains check: Query configured drains via MCP or REST API. If no drains are configured on a Pro/Enterprise plan, warn:
list_drains⚠️ 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 ), or
vercel integration lsin the project.@vercel/analytics - These are warnings, not blockers — the user may proceed after acknowledgment.
在将部署推广到生产环境之前,请验证可观测性是否就绪:
- Drains检查:通过MCP的工具或REST API查询已配置的Drains。如果专业版/企业版套餐下未配置Drains,请发出警告:
list_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 1hOr via MCP if available: use with level filter .
get_runtime_logserrorInterpret results:
| Finding | Action |
|---|---|
| No errors | ✓ Clean deploy — no runtime errors in first hour |
| Errors detected | List error count and first 5 unique error messages. Suggest: check drain payloads for correlated traces, review function logs in Dashboard |
| 500 status codes in logs | Correlate timestamps with drain data (if configured) or |
| Timeout errors | Check function duration limits in |
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_logserror结果解读:
| 发现 | 操作建议 |
|---|---|
| 无错误 | ✓ 部署干净 —— 第一小时内无运行时错误 |
| 检测到错误 | 列出错误数量和前5条唯一错误信息。建议:检查Drains负载中的相关追踪,在仪表板中查看函数日志 |
| 日志中存在500状态码 | 将时间戳与Drains数据(已配置的话)或 |
| 超时错误 | 检查 |
备选方案(无Drains):
如果未配置Drains,错误扫描依赖于CLI和仪表板:
bash
undefinedStream 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:
- Measure first: Check Speed Insights dashboard for real-user CWV data
- Identify LCP element: Use Chrome DevTools → Performance → identify the LCP element
- Audit : Every
'use client'file ships JS to the browser — minimize'use client' - Check images: All above-fold images use with
next/imagepriority - Check fonts: All fonts loaded via (zero CLS)
next/font - Check third-party scripts: All use with correct strategy
next/script - Check data fetching: Server Components fetch in parallel, no waterfalls
- Check caching: Cache Components used for expensive operations
- Check bundle: Run analyzer, look for low-hanging fruit
- Check infrastructure: Functions in correct region, Fluid Compute enabled
当被要求优化Vercel应用时,请按以下步骤执行:
- 先测量:查看Speed Insights仪表板获取真实用户的CWV数据
- 识别LCP元素:使用Chrome DevTools → 性能面板 → 识别LCP元素
- 审核:每个
'use client'文件都会向浏览器发送JS —— 尽量减少使用'use client' - 检查图片:所有首屏图片都使用并设置
next/imagepriority - 检查字体:所有字体都通过加载(零CLS)
next/font - 检查第三方脚本:所有脚本都使用并设置正确的策略
next/script - 检查数据获取:服务器组件并行获取数据,避免瀑布流
- 检查缓存:对执行昂贵操作的组件进行缓存
- 检查打包文件:运行分析工具,寻找容易优化的点
- 检查基础设施:函数部署在正确的区域,启用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使用waitUntil
实现自定义监控
waitUntilFire-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 nextjsVercel市场原生集成,自动配置源映射和版本追踪。
bash
npx @sentry/wizard@latest -i nextjsOr 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-rumts
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-rumts
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 datadogCheckly — Synthetic Monitoring & Testing
Checkly —— 合成监控与测试
API and browser checks that run continuously against your deployments.
bash
npm install -D checkly
npx checkly initCheckly 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 initCheckly与Vercel部署事件集成,每次部署时自动触发检查。
通过市场安装:
vercel integration add checklyNew Relic — Application Performance Monitoring
New Relic —— 应用性能监控
Full-stack observability with distributed tracing and alerting.
bash
npm install newrelicRequires a config file at the project root. Install via Marketplace:
newrelic.jsvercel integration add newrelic提供全栈可观测性,支持分布式追踪和告警。
bash
npm install newrelic需要在项目根目录创建配置文件。通过市场安装:
newrelic.jsvercel integration add newrelicDecision Matrix
决策矩阵
| Need | Use | Why |
|---|---|---|
| Page views, traffic sources | Web Analytics | First-party, privacy-friendly |
| Business event tracking | Web Analytics custom events | Track conversions, feature usage |
| Core Web Vitals monitoring | Speed Insights | Real user data per route |
| Function debugging | Runtime Logs (CLI | Real-time, per-invocation logs |
| Export logs to external platform | Drains (JSON/NDJSON/Syslog) | Centralize observability (Pro+) |
| Export analytics data | Drains (Web Analytics type) | Warehouse pageviews + custom events (Pro+) |
| OpenTelemetry traces | Drains (OTel-compatible endpoint) | Standards-based distributed tracing (Pro+) |
| Post-response telemetry | | Non-blocking metrics |
| Server-side event tracking | | Track API-triggered events |
| Hobby plan log access | CLI | No drains needed |
| 需求 | 使用工具 | 原因 |
|---|---|---|
| 页面浏览、流量来源 | Web Analytics | 第一方数据,隐私友好 |
| 业务事件追踪 | Web Analytics自定义事件 | 追踪转化、功能使用情况 |
| Core Web Vitals监控 | Speed Insights | 基于真实用户的路由级数据 |
| 函数调试 | 运行时日志(CLI | 实时、按调用维度的日志 |
| 将日志导出到外部平台 | Drains(JSON/NDJSON/Syslog) | 集中式可观测性(专业版+) |
| 导出分析数据 | Drains(Web Analytics类型) | 存储页面浏览+自定义事件数据(专业版+) |
| OpenTelemetry追踪 | Drains(兼容OTel的端点) | 基于标准的分布式追踪(专业版+) |
| 响应后遥测 | | 非阻塞式指标上报 |
| 服务端事件追踪 | | 追踪API触发的事件 |
| 免费版套餐日志访问 | CLI | 无需Drains |
Cross-References
交叉引用
- Drains REST API & runtime logs endpoint → (Observability APIs section)
⤳ skill: vercel-api - CLI log streaming (,
--follow,--since) →--level(Logs & Inspection section)⤳ skill: vercel-cli - Marketplace vendor integrations →
⤳ skill: marketplace
- Drains REST API & 运行时日志端点 → (可观测性API部分)
⤳ skill: vercel-api - CLI日志流式处理(,
--follow,--since) →--level(日志与检查部分)⤳ skill: vercel-cli - 市场厂商集成 →
⤳ skill: marketplace