跳转到内容
Telemetry
浏览文档

指南更新于 2026年10月3日阅读约需 4 分钟

让编程智能体使用这篇文档

打开 Claude Code、Codex、Cursor 或其他编码代理的集中提示包,然后将其适应此处介绍的工作流程。

本页内容
  1. 修改路由之前
  2. 添加服务器辅助函数
  3. 包装现有处理器
  4. 验证实际调用
  5. 不保证什么
  6. 框架参考与后续步骤

观察一条现有的 Next.js 路由

本示例用于现有 Next.js App Router 应用,请使用已安装最新补丁的当前版本及受支持的 Node.js 部署。after API 自 Next.js 15.1 起稳定;这个 API 最低版本并不表示建议安装未修补的旧版本。它观察处理器返回 Response 或抛出的情况,不代表浏览器收到响应、流式响应完成或后台业务任务完成。

修改路由之前

选择你控制的路由及已获授权、可安全执行的操作。保留认证、校验和业务逻辑。TELEMETRY_API_KEY 只放在服务器环境中,不要使用 NEXT_PUBLIC_ 前缀。首页匿名密钥可发送和查询;账户密钥在验证时需要 read-and-write 权限。只发送事件的应用可使用仅摄取密钥。

添加服务器辅助函数

保存为 lib/with-telemetry.js。使用不含客户标识符的固定路由模板。生成的调用 ID 仅标识一次处理器调用,不代表用户或逻辑任务。不发送 URL、请求体、Cookie、请求头或错误信息。

import { after } from 'next/server';
import { randomUUID } from 'node:crypto';

function warnTelemetry(message) {
  try {
    console.warn(message);
  } catch {
    // Diagnostic failure must not change the application outcome.
  }
}

export function withTelemetry(handler, routeTemplate) {
  return async function observedHandler(request, context) {
    const started = performance.now();
    const invocationId = randomUUID();
    let outcome = 'threw';
    let statusCode = null;
    try {
      const response = await handler(request, context);
      outcome = 'returned_response';
      statusCode = response.status;
      return response;
    } finally {
      const event = {
        invocation_id: invocationId,
        route_template: routeTemplate,
        method: request.method,
        handler_outcome: outcome,
        status_code: statusCode,
        latency_ms: performance.now() - started,
        environment: process.env.NODE_ENV || 'development',
      };
      try {
        after(async () => {
          const key = process.env.TELEMETRY_API_KEY;
          if (!key) {
            warnTelemetry('Telemetry key missing; event not sent');
            return;
          }
          try {
            const response = await fetch('https://api.telemetry.sh/log', {
              method: 'POST',
              headers: {
                Authorization: `Bearer ${key}`,
                'Content-Type': 'application/json',
              },
              cache: 'no-store',
              signal: AbortSignal.timeout(2000),
              body: JSON.stringify({ table: 'nextjs_route_observed', data: event }),
            });
            if (!response.ok) warnTelemetry('Telemetry event send rejected');
          } catch {
            warnTelemetry('Telemetry event send failed');
          }
        });
      } catch {
        warnTelemetry('Telemetry background scheduling failed');
      }
    }
  };
}

包装现有处理器

将现有导出的 GET 函数改名为 existingGET,保持函数体不变,再导出下方包装器。按实际路由调整方法和固定模板;不要通过新建始终成功的虚构处理器完成设置。

import { withTelemetry } from "@/lib/with-telemetry";

export const GET = withTelemetry(existingGET, "/api/reports/:id");

验证实际调用

通过应用执行获授权的操作,再查询 Telemetry 表。核对路由、方法、时间、结果和状态是否对应刚才的操作。HTTP 接收不等于验证。离线测试、演示路由或代理 QA 运行不是客户集成;虚构发送应使用 telemetry_quickstart。

SELECT invocation_id, route_template, method, handler_outcome,
       status_code, latency_ms, environment, timestamp_utc
FROM nextjs_route_observed
WHERE timestamp_utc >= now() - INTERVAL '15 minutes'
ORDER BY timestamp_utc DESC
LIMIT 20;

不保证什么

Next.js after 在响应结束后调度发送。它不是持久队列:平台时限、关机、超时和网络故障可能造成事件丢失。发送超时为两秒,警告为不含私密数据的固定文本;不承诺自动重试或去重。保留现有日志,必需的审计记录应使用持久投递路径。

latency_ms 到处理器返回或抛出时结束,不含事件发送时间。returned_response 也可能是 4xx 或 5xx。threw 可能是框架重定向或控制流,不能自动当作服务器故障。缺少密钥或遥测失败不得替换原响应或原异常。上线前在自己的运行环境中检查此函数。

框架参考与后续步骤

Next.js after 参考文档说明版本及部署支持。不支持静态导出;适配器需要明确支持。响应保留、抛出的异常及遥测发送失败已在隔离的 Next.js 16.3.8 开发模式 App Router 应用中检查,事件发送被拦截且外部网络已禁用。这不验证真实的 Telemetry 摄入或你的生产主机。继续阅读事件摄入验证及 JavaScript SDK 指南以扩展埋点。

相关功能

记录稳定的事件名称、类型明确的字段,以及经过隐私审核的上下文。

页面作者和参考资料

Telemetry 编辑团队负责维护本文;产品团队审核功能行为、示例和适用范围。

我们如何审核文档