Next.js に Datadog APM を導入する際の注意点
この記事は AoTo Advent Calendar 2023 6日目の記事です。
TL;DR
Next.js のうち、サーバーサイドで動いているモジュール群で Node.js APM を利用する方法をまとめています。
前提として、Datadog Node.js APM には互換性要件が定められており、Next.js は Standalone
や AppRouter
を利用していている場合に、サーバーサイドのモジュール群をトレース可能です。[1]
ただし、愚直に/app/page.js
に対してimport dd-trace
のように実装すれば良いのではなく、Node.js APM ライブラリであるdd-trace
が Next.js のサーバーサイドモジュール群にインポートされる前にロードされる必要があります。
そのため、最初にdd-trace
をロードする方法として、このような方法が考えられます。
- カスタムサーバーによるエントリポイントの指定
-
next start
時に Node.js CLI の--require module
オプションの指定
今回は、Node.js への APM の実装方法から簡単に解説をしていきます。
前提条件
Datadog Node.js APM はdd-trace
(GitHub, npm) というトレーシングライブラリを提供しています。このライブラリにより、npm install
によるインストールとdd-trace.init()
による初期化を行うことで、Node.js アプリケーションの自動計装を開始できます。
初期化の方法としては公式ドキュメントでは、大きく2通りの方法を案内しています。
- パッケージのインポートとトレーサーの初期化を初めに行う
// `dd-trace`パッケージを要求(require)し、その`init`メソッドを呼び出してトレーサーを初期化
const tracer = require('dd-trace').init();
- 初めに
dd-trace
を初期化できるよう、tracer.js
のように別ファイルを作成する
import tracer from 'dd-trace';
tracer.init();
export default tracer;
コードの保守性の観点からも、本番環境では後者を採用することが多いように思います。
以下では、こちらの前提で Next.js におけるプリロード方法を解説します。
プリロードの実装と注意点
カスタムサーバー
Next.js 通常next start
により独自のサーバーを起動することができます。しかし、next start
を行う場合、計装対象のアプリケーションより先に起動している必要のある dd-trace
が先に読み込まれず、適切にアプリケーションを計装できません。
ここで、カスタムサーバー を利用することで、エントリポイントにdd-trace
を初期化するコードを指定することができます。
{
"scripts": {
"dev": "node tracer.js",
"build": "next build",
"start": "NODE_ENV=production node tracer.js"
}
}
しかし、カスタムサーバーは Next.js のメリットでもあるパフォーマンス最適化の機能が利用できなくなる注意点があります。
カスタムサーバーの使用を決定する前に、Next.js の統合ルーターがアプリの要件を満たせない場合にのみ使用すべきことを気に留めてください。カスタムサーバーでは、サーバーレス関数や Automatic Static Optimization などの重要なパフォーマンス最適化が削除されます。
これらの最適化による恩恵を受けていて、Datadog APM を利用するためだけにこれらのメリットを諦めるのは難しいという場合は、この方法が向いていないということがわかります。
Node.js CLI の --require-module オプション
--require module
オプションは、起動時に指定されたモジュールをプリロードするための Node.js CLI のオプションです。node --require モジュール名
またはnode -r モジュール名
の形式で指定できます。
{
"scripts": {
"dev": "node tracer.js",
"build": "next build",
"start": "node --require ./tracer.js ./node_modules/.bin/next start"
}
}
これにより、next start
によるパフォーマンス最適化のメリットを享受しつつ、dd-trace
をプリロードすることができます。
補足
tracer.js
のように別ファイルを作成することで、Node.js トレーシングライブラリの構成管理しやすくなります。使用されることが多い構成は、runtimeMetrics: true
やlogInjection: true
などではないでしょうか。
これらを SetUpDatadogTracing()
のように名前付き関数でまとめることで、Datadog Node.js APM の処理をカプセル化して可読性を高めることができます。
function setUpDatadogTracing() {
const { tracer: Tracer } = require('dd-trace')
const tracer = Tracer.init({
runtimeMetrics: true,
logInjection: true,
})
}
setUpDatadogTracing()
-
クライアントサイドの動作は Datadog Browser RUM により取得できます。 Datadog Browser RUM は Core Web Vitals をはじめ各コンポーネントの表示パフォーマンスなどを測定できます。 ↩︎
Discussion