OpenTelemetry
可观测性对于理解和优化你的 Next.js 应用的行为和性能至关重要。
随着应用程序变得越来越复杂,识别和诊断可能出现的问题变得越来越困难。通过利用可观测性工具,例如日志记录和指标,开发人员可以深入了解其应用程序的行为并确定需要优化的领域。通过可观测性,开发人员可以在问题变成重大问题之前主动解决问题,并提供更好的用户体验。因此,强烈建议在你的 Next.js 应用程序中使用可观测性,以提高性能、优化资源并增强用户体验。
我们建议使用 OpenTelemetry 来检测你的应用程序。这是一种与平台无关的检测应用程序的方式,它允许你更改可观测性提供商而无需更改你的代码。阅读 官方 OpenTelemetry 文档 以获取有关 OpenTelemetry 及其工作原理的更多信息。
本文档在全文中使用诸如 Span、Trace 或 Exporter 等术语,所有这些都可以在 OpenTelemetry 可观测性入门指南 中找到。
Next.js 开箱即用地支持 OpenTelemetry 检测,这意味着我们已经检测了 Next.js 本身。当你启用 OpenTelemetry 时,我们将自动将你所有的代码(如 getStaticProps
)包裹在带有有用属性的 span 中。
开始使用
OpenTelemetry 是可扩展的,但正确设置它可能会非常繁琐。这就是为什么我们准备了一个包 @vercel/otel
,它可以帮助你快速入门。
使用 @vercel/otel
要开始使用,请安装以下软件包
npm install @vercel/otel @opentelemetry/sdk-logs @opentelemetry/api-logs @opentelemetry/instrumentation
接下来,在项目的根目录(或者如果使用 src
文件夹,则在其中)中创建一个自定义的 instrumentation.ts
(或 .js
) 文件
import { registerOTel } from '@vercel/otel'
export function register() {
registerOTel({ serviceName: 'next-app' })
}
有关其他配置选项,请参阅 @vercel/otel
文档。
须知:
instrumentation
文件应该位于项目的根目录中,而不是在app
或pages
目录中。如果你正在使用src
文件夹,则将该文件放在src
内部,与pages
和app
并列。- 如果你使用
pageExtensions
配置选项 添加后缀,你还需要更新instrumentation
文件名以匹配。- 我们创建了一个基本的 with-opentelemetry 示例,你可以使用它。
手动 OpenTelemetry 配置
@vercel/otel
包提供了许多配置选项,应该可以满足大多数常见用例。但是,如果它不能满足你的需求,你可以手动配置 OpenTelemetry。
首先,你需要安装 OpenTelemetry 包
npm install @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http
现在你可以在你的 instrumentation.ts
中初始化 NodeSDK
。与 @vercel/otel
不同,NodeSDK
与边缘运行时不兼容,因此你需要确保仅在 process.env.NEXT_RUNTIME === 'nodejs'
时导入它们。我们建议创建一个新的文件 instrumentation.node.ts
,仅在使用 node 时有条件地导入它
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./instrumentation.node.ts')
}
}
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
import { Resource } from '@opentelemetry/resources'
import { NodeSDK } from '@opentelemetry/sdk-node'
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node'
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'
const sdk = new NodeSDK({
resource: new Resource({
[ATTR_SERVICE_NAME]: 'next-app',
}),
spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter()),
})
sdk.start()
这样做等同于使用 @vercel/otel
,但是可以修改和扩展 @vercel/otel
未公开的某些功能。如果需要边缘运行时支持,你将必须使用 @vercel/otel
。
测试你的检测
你需要一个带有兼容后端的 OpenTelemetry Collector 来在本地测试 OpenTelemetry 追踪。我们建议使用我们的 OpenTelemetry 开发环境。
如果一切正常,你应该能够看到标记为 GET /requested/pathname
的根服务器 span。来自该特定追踪的所有其他 span 将嵌套在它之下。
Next.js 追踪的 span 比默认情况下发出的 span 更多。要查看更多 span,你必须设置 NEXT_OTEL_VERBOSE=1
。
部署
使用 OpenTelemetry Collector
当你使用 OpenTelemetry Collector 部署时,你可以使用 @vercel/otel
。它在 Vercel 和自托管环境下都有效。
在 Vercel 上部署
我们确保了 OpenTelemetry 在 Vercel 上开箱即用。
请按照 Vercel 文档 将你的项目连接到可观测性提供商。
自托管
部署到其他平台也很简单。你将需要启动你自己的 OpenTelemetry Collector 以接收和处理来自你的 Next.js 应用程序的遥测数据。
为此,请按照 OpenTelemetry Collector 入门指南 进行操作,该指南将引导你完成设置 collector 并配置它以接收来自你的 Next.js 应用程序的数据。
一旦你的 collector 启动并运行,你就可以按照他们各自的部署指南将你的 Next.js 应用程序部署到你选择的平台。
自定义导出器
OpenTelemetry Collector 不是必需的。你可以将自定义 OpenTelemetry 导出器与 @vercel/otel
或 手动 OpenTelemetry 配置 一起使用。
自定义 Span
你可以使用 OpenTelemetry API 添加自定义 span。
npm install @opentelemetry/api
以下示例演示了一个函数,该函数获取 GitHub 星星并添加一个自定义 fetchGithubStars
span 以跟踪 fetch 请求的结果
import { trace } from '@opentelemetry/api'
export async function fetchGithubStars() {
return await trace
.getTracer('nextjs-example')
.startActiveSpan('fetchGithubStars', async (span) => {
try {
return await getValue()
} finally {
span.end()
}
})
}
register
函数将在你的代码在新环境中运行之前执行。你可以开始创建新的 span,并且它们应该被正确地添加到导出的追踪中。
Next.js 中的默认 Span
Next.js 自动检测多个 span,以便为你提供有关应用程序性能的有用见解。
span 上的属性遵循 OpenTelemetry 语义约定。我们还在 next
命名空间下添加了一些自定义属性
next.span_name
- 复制 span 名称next.span_type
- 每种 span 类型都有唯一的标识符next.route
- 请求的路由模式(例如,/[param]/user
)。next.rsc
(true/false) - 请求是否为 RSC 请求,例如预取。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
此 span 表示每个传入 Next.js 应用程序的请求的根 span。它跟踪请求的 HTTP 方法、路由、目标和状态代码。
属性
- 通用 HTTP 属性
http.method
http.status_code
- 服务器 HTTP 属性
http.route
http.target
next.span_name
next.span_type
next.route
render route (app) [next.route]
next.span_type
:AppRender.getBodyResult
。
此 span 表示在应用程序路由器中渲染路由的过程。
属性
next.span_name
next.span_type
next.route
fetch [http.method] [http.url]
next.span_type
:AppRender.fetch
此 span 表示在你的代码中执行的 fetch 请求。
属性
- 通用 HTTP 属性
http.method
- 客户端 HTTP 属性
http.url
net.peer.name
net.peer.port
(仅在指定时)
next.span_name
next.span_type
可以通过在你的环境中设置 NEXT_OTEL_FETCH_DISABLED=1
来关闭此 span。 当你想使用自定义 fetch 检测库时,这很有用。
executing api route (app) [next.route]
next.span_type
:AppRouteRouteHandlers.runHandler
。
此 span 表示应用程序路由器中 API 路由处理程序的执行。
属性
next.span_name
next.span_type
next.route
getServerSideProps [next.route]
next.span_type
:Render.getServerSideProps
。
此 span 表示特定路由的 getServerSideProps
的执行。
属性
next.span_name
next.span_type
next.route
getStaticProps [next.route]
next.span_type
:Render.getStaticProps
。
此 span 代表为特定路由执行 getStaticProps
。
属性
next.span_name
next.span_type
next.route
render route (pages) [next.route]
next.span_type
:Render.renderDocument
。
此 span 代表为特定路由渲染文档的过程。
属性
next.span_name
next.span_type
next.route
generateMetadata [next.page]
next.span_type
:ResolveMetadata.generateMetadata
。
此 span 代表为特定页面生成元数据的过程(单个路由可以有多个此类 span)。
属性
next.span_name
next.span_type
next.page
resolve page components
next.span_type
:NextNodeServer.findPageComponents
。
此 span 代表为特定页面解析页面组件的过程。
属性
next.span_name
next.span_type
next.route
resolve segment modules
next.span_type
:NextNodeServer.getLayoutOrPageModule
。
此 span 代表加载布局或页面的代码模块。
属性
next.span_name
next.span_type
next.segment
start response
next.span_type
:NextNodeServer.startResponse
。
此零长度 span 代表响应中第一个字节发送的时间。
这有帮助吗?