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
與 edge runtime 不相容,因此您需要確保僅在 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
未公開的某些功能。如果需要 edge runtime 支援,您將必須使用 @vercel/otel
。
測試您的檢測
您需要一個具有相容後端的 OpenTelemetry 收集器,才能在本機測試 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 入門指南,其中將引導您完成設定收集器並將其設定為接收來自您的 Next.js 應用程式的資料。
在您啟動並執行收集器後,您可以依照其各自的部署指南,將您的 Next.js 應用程式部署到您選擇的平台。
自訂 Exporter
OpenTelemetry Collector 不是必要的。您可以將自訂 OpenTelemetry exporter 與 @vercel/otel
或 手動 OpenTelemetry 設定 搭配使用。
自訂 Span
您可以使用 OpenTelemetry API 來新增自訂 span。
npm install @opentelemetry/api
以下範例示範了一個函式,該函式會抓取 GitHub 星星並新增自訂的 fetchGithubStars
span 以追蹤抓取請求的結果
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
- 這是 app router 使用的內部值。
- 您可以將其視為特殊檔案(例如
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
渲染路由 (app) [next.route]
next.span_type
:AppRender.getBodyResult
。
此 span 代表在 app router 中渲染路由的過程。
屬性
next.span_name
next.span_type
next.route
fetch [http.method] [http.url]
next.span_type
:AppRender.fetch
此 span 代表在您的程式碼中執行的抓取請求。
屬性
- 常見 HTTP 屬性
http.method
- 客戶端 HTTP 屬性
http.url
net.peer.name
net.peer.port
(僅在指定時)
next.span_name
next.span_type
可以透過在您的環境中設定 NEXT_OTEL_FETCH_DISABLED=1
來關閉此 span。當您想要使用自訂抓取檢測函式庫時,這非常有用。
執行 api 路由 (app) [next.route]
next.span_type
:AppRouteRouteHandlers.runHandler
。
此 span 代表在 app router 中執行 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
渲染路由 (pages) [next.route]
next.span_type
:Render.renderDocument
。
此 span 代表針對特定路由渲染文件 (document) 的過程。
屬性
next.span_name
next.span_type
next.route
generateMetadata [next.page]
next.span_type
:ResolveMetadata.generateMetadata
。
此 span 代表針對特定頁面產生 metadata 的過程 (單一路由可以有多個這些 span)。
屬性
next.span_name
next.span_type
next.page
解析頁面元件
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 代表回應中第一個位元組已傳送的時間。
這有幫助嗎?