Arganoの池田です。 本記事ではオブザーバビリティプラットフォームであるNew RelicをNext.jsアプリケーションに導入する手順の説明と、実際にNext.jsアプリケーションに組み込むデモを行います。

New Relic とは

New Relicはオブザーバビリティプラットフォームと呼ばれるシステムです。ITシステムに対して、エンドユーザーの体験からシステム内部の処理までを網羅して可視化することで、エンドユーザーへ提供しているサービスの品質低下や、障害発生などへの素早い対処を可能にします。 アプリケーションパフォーマンス管理やインフラ監視の機能を備えているだけでなく、それらのシステムから得られるデータの把握・分析を行うことでシステムへの理解を深めたり、運用の助けになるような総合的なサービスを提供しています。

https://newrelic.com/

以降の内容では、New Relicの様々な機能を試すことができるように、デモ用のNext.jsアプリケーションを作成してNew Relicの導入を行います。

デモ用アプリケーションのセットアップ

Next.jsアプリケーションの作成

create-next-app を利用してプロジェクトを作成します。

npx create-next-app@latest newrelic-demo --yes
cd newrelic-demo
npm run dev

この状態で http://localhost:3000 でアプリケーションが起動することを確認します。

New Relicの導入

License Keyの作成

New Relicのwebページからアカウントを作成後、 Integrations & Agents から Node.js を選択します。 その後の Choose your instrumentation method では On a host を選択します。

select-instrumentation-method

次に Create a new key でLicense Keyを作成します。このLicense Keyは後ほどNext.jsプロジェクトへ設定します。

enter-your-credentials

Next.jsプロジェクトの設定

Next.jsプロジェクトにNew Relic Node.js (APM) agent をインストールします。

npm install newrelic
npm install -D @types/newrelic

その後、下記のディレクトリに生成された構成ファイルをプロジェクトのルートディレクトリにコピーします。

cp ./node_modules/newrelic/newrelic.js ./

構成ファイルに先程のLicense Keyをコピーします。今回はデモなので構成ファイルに書き込んで動かしてみますが、実運用の際には機密情報として扱いgitの管理下などには置かないようにご注意ください。

次に、next.config.js を以下のように変更します。

"use strict";

const nrExternals = require("newrelic/load-externals");

module.exports = {
  serverExternalPackages: ["newrelic"],
  turbopack: (config) => {
    nrExternals(config);
    return config;
  }
};

ビルド後、 NODE_OPTIONS='-r newrelic' next start でアプリケーションを起動します。 起動後に、ページにアクセスするなどしてから数分待つと、New RelicのAPMのダッシュボードに計測データが流れ始めることを確認してください。 これによりサーバーサイドのパフォーマンス監視が可能になります。

apm

次にクライアントサイドのパフォーマンス監視の設定を行います。作成したNext.jsアプリケーションには src/app/layout.tsx が存在しているはずなので、そちらに計測用のスクリプトを埋め込むように処理を追加します。

import Script from "next/script";
import newrelic from "newrelic";

...

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  if ((newrelic as any).agent.collector.isConnected() === false) {
    await new Promise((resolve) => {
      (newrelic as any).agent.on("connected", resolve);
    });
  }

  const browserTimingHeader = newrelic.getBrowserTimingHeader({
    hasToRemoveScriptWrapper: true,
    allowTransactionlessInjection: true,
  });

  return (
    <html lang="en">
      <Script
        id="nr-browser-agent"
        dangerouslySetInnerHTML={{ __html: browserTimingHeader }}
      />
      ...
    </html>
  );
};

この記事を執筆した時点では newrelic.agent が型上では存在せず、型エラーを回避するために as any を追加しています。 この設定を追加後、アプリケーションを再起動し何度かページにアクセスした後、New RelicのBrowserの項目から計測したデータを見ると、計測したデータが流れてくることが確認できます。

browser

ここまでNext.jsアプリケーションにNew Relicを組み込む際の手順の紹介をしました。これらの機能はNew Relicが持つ機能のほんの一部に過ぎないため、今回触れていない機能についても今後紹介していければと思います。最後まで本記事をお読みいただき、ありがとうございました。