OpenTelemetry
须知:此功能目前为实验性,您需要在
next.config.js
中明确启用experimental.instrumentationHook = true;
。
可观测性对于理解和优化 Next.js 应用的行为与性能至关重要。
随着应用程序日益复杂,识别和诊断潜在问题变得愈发困难。通过利用日志记录和指标等可观测性工具,开发者可以洞察应用行为并找到优化方向。借助可观测性,开发者能主动解决问题,防患于未然,从而提供更佳的用户体验。因此,强烈建议在 Next.js 应用中采用可观测性来提升性能、优化资源并改善用户体验。
我们推荐使用 OpenTelemetry 来实现应用监控。
这是一种与平台无关的监控方案,允许您在不修改代码的情况下更换观测服务提供商。
更多关于 OpenTelemetry 及其工作原理的信息,请参阅 OpenTelemetry 官方文档。
本文档中使用的术语如 Span(跨度)、Trace(追踪)或 Exporter(导出器)均可在 OpenTelemetry 可观测性入门 中找到定义。
Next.js 已内置支持 OpenTelemetry 监控,这意味着我们已为 Next.js 核心功能添加了监控支持。
当您启用 OpenTelemetry 后,我们将自动为所有代码(如 getStaticProps
)包裹具有实用属性的 spans。
须知:当前我们仅支持在无服务器函数中使用 OpenTelemetry 绑定,暂不支持
edge
运行时或客户端代码。
快速开始
OpenTelemetry 具有高度可扩展性,但初始配置可能较为繁琐。
为此我们提供了 @vercel/otel
包来帮助您快速上手。
该方案不可扩展,如需自定义配置请手动设置 OpenTelemetry。
使用 @vercel/otel
首先安装依赖:
接着在项目根目录(若使用 src
目录则放在其中)创建 instrumentation.ts
(或 .js
)文件:
须知
instrumentation
文件应位于项目根目录,而非app
或pages
目录内。若使用src
文件夹,请将其与pages
和app
并列放置- 若使用
pageExtensions
配置选项 添加后缀,需同步更新instrumentation
文件名- 我们提供了基础示例 with-opentelemetry 供参考
手动配置 OpenTelemetry
若 @vercel/otel
不能满足需求,可手动配置 OpenTelemetry。
首先安装所需依赖:
然后在 instrumentation.ts
中初始化 NodeSDK
。
由于 OpenTelemetry API 不兼容 edge 运行时,需确保仅在 process.env.NEXT_RUNTIME === 'nodejs'
时导入。建议创建新文件 instrumentation.node.ts
并按条件导入:
此配置等同于使用 @vercel/otel
,但允许自由修改扩展。例如可替换为 @opentelemetry/exporter-trace-otlp-grpc
或添加更多资源属性。
测试监控配置
本地测试 OpenTelemetry 追踪需要配合收集器与兼容的后端系统。
推荐使用我们的 OpenTelemetry 开发环境。
配置成功后,您将看到标记为 GET /请求路径
的根服务端跨度,该追踪下的所有其他跨度将嵌套其下。
Next.js 默认会追踪比实际输出更多的跨度。
如需查看完整跨度,需设置 NEXT_OTEL_VERBOSE=1
。
部署
使用 OpenTelemetry 收集器
当使用 OpenTelemetry 收集器部署时,可继续使用 @vercel/otel
。
此方案在 Vercel 和自托管环境中均适用。
部署至 Vercel
我们已确保 OpenTelemetry 在 Vercel 上开箱即用。
按照 Vercel 文档 将项目连接至观测服务提供商。
自托管部署
部署到其他平台也很简单。您需要自行搭建 OpenTelemetry 收集器来接收和处理来自 Next.js 应用的遥测数据。
具体步骤请参考 OpenTelemetry 收集器入门指南,该指南将引导您完成收集器设置与数据接收配置。
自定义导出器
我们推荐使用 OpenTelemetry 收集器。
若平台不支持,可通过 手动配置 OpenTelemetry 使用自定义导出器。
自定义跨度
您可以通过 OpenTelemetry API 添加自定义跨度。
以下示例展示如何为获取 GitHub star 数的函数添加 fetchGithubStars
跨度来追踪请求结果:
register
函数会在新环境运行代码前执行。此时创建的新跨度将被正确添加到导出的追踪中。
Next.js 默认跨度
Next.js 自动生成多个跨度以提供应用性能洞察。
跨度属性遵循 OpenTelemetry 语义约定,同时我们在 next
命名空间下添加了自定义属性:
next.span_name
- 重复跨度名称next.span_type
- 每个跨度类型的唯一标识符next.route
- 请求的路由模式(如/[param]/user
)next.page
- 应用路由使用的内部值
- 可视为特殊文件的路由(如
page.ts
、layout.ts
、loading.ts
等) - 需与
next.route
配合才能作为唯一标识,因为/layout
可能同时对应/(groupA)/layout.ts
和/(groupB)/layout.ts
[http.method] [next.route]
next.span_type
:BaseServer.handleRequest
此跨度代表每个传入请求的根跨度,追踪 HTTP 方法、路由、目标和状态码。
属性:
- HTTP 通用属性
http.method
http.status_code
- 服务端 HTTP 属性
http.route
http.target
next.span_name
next.span_type
next.route
渲染路由 (app) [next.route]
next.span_type
:AppRender.getBodyResult
此跨度代表应用路由中的路由渲染过程。
属性:
next.span_name
next.span_type
next.route
获取 [http.method] [http.url]
next.span_type
:AppRender.fetch
此跨度代表代码中执行的 fetch 请求。
属性:
- HTTP 通用属性
http.method
- 客户端 HTTP 属性
http.url
net.peer.name
net.peer.port
(如指定)
next.span_name
next.span_type
执行 API 路由 (app) [next.route]
next.span_type
:AppRouteRouteHandlers.runHandler
此跨度代表应用路由中 API 路由处理程序的执行过程。
属性:
next.span_name
next.span_type
next.route
getServerSideProps [next.route]
next.span_type
:Render.getServerSideProps
此跨度代表特定路由的 getServerSideProps
执行过程。
属性:
next.span_name
next.span_type
next.route
getStaticProps [next.route]
next.span_type
:Render.getStaticProps
此跨度代表特定路由的 getStaticProps
执行过程。
属性:
next.span_name
next.span_type
next.route
渲染路由 (pages) [next.route]
next.span_type
:Render.renderDocument
此跨度代表特定路由的文档渲染过程。
属性:
next.span_name
next.span_type
next.route
generateMetadata [next.page]
next.span_type
:ResolveMetadata.generateMetadata
此跨度代表为特定页面生成元数据的过程(单个路由可能包含多个此类跨度)。
属性:
next.span_name
next.span_type
next.page