New RelicをNext.js App Routerに導入する

# New Relicとは

いわゆる監視ツールになるのですが、
単なる監視ツールではなく、`All-in-one observability`を提供するプラットフォームになっています。
https://newrelic.com/jp

これまで、サーバーやWeb、インフラなど別々のツールで監視していたものを１つのプラットフォームで統合的かつトレーサブルに扱うことができ、俯瞰したモニタリングが可能になるツールです。

無料枠でも使える程度の機能を提供してくれていますので、１人で複数環境をモニタリングしなければいけない個人開発者の方などにはかなり嬉しいツールかと思います。
![New Relic無料枠](https://storage.googleapis.com/zenn-user-upload/9076b8c02ff0-20240824.png)

今回の記事では、このNew RelicをNext.js App Routerに設定していく手順を簡潔に紹介して行きます。

# 導入手順
今回の手順では、サーバーサイドとクライアントサイド側の監視を設定していきます。

## 1. New Relicでアカウントを作成

### 1-1. 下記より、New Relicのアカウント作成を進めて行きます。
https://newrelic.com/jp/sign-up-japan

## 2. ライセンスキーの取得

### 2-1. 画面下のアカウントから、"API Keys"を選択します。
![](https://storage.googleapis.com/zenn-user-upload/e0f0ee19a5b0-20240824.png)

### 2-2. 遷移した先のAPI KeysからLicense Keyを探し、左のメニューボタンから"Copy Key"を選択して、キーを保存しておきます。
![](https://storage.googleapis.com/zenn-user-upload/e8121e34ca22-20240824.png)

## 3. NPMインストール

### 3-1. `newrelic`と`@newrelic/next`をインストールします。

```bash
bun add newrelic @newrelic/next
```
(npm i, yarn add, pnpm add, etc...)

## 4. Next.jsへの適用 (サーバーサイド)

### 4-1. package.jsonのスクリプトでnewrelicを読み込ませます。

__AsIs__
```json
{
  name: "New Relic DEMO",
  ...
  "scripts": {
    "dev": "dotenv -e ./.env -- next dev",
    "start": "next start",
    ...
  },
  ...
}
```

__ToBe__

```json
{
  name: "New Relic DEMO",
  ...
  "scripts": {
    "dev": "NODE_OPTIONS='-r @newrelic/next' dotenv -e ./.env -- next dev",
    "start": "NODE_OPTIONS='-r @newrelic/next' next start",
    ...
  },
  ...
}
```
※僕のアプリでは諸事情により、dotenvを使っていますがdotenvは不要です。

### 4-3. next.config.jsに追加します。

:::message
next.config.jsを設定していないと下記の様なエラーでつまづくケースがあります。
https://forum.newrelic.com/s/hubtopic/aAXPh00000018gHOAQ/unable-to-integrate-the-newrelic-with-nextjs-14-application
:::

```js
const nrExternals = require('@newrelic/next/load-externals')

const nextConfig = {
  experimental: {
    // Without this setting, the Next.js compilation step will routinely
    // try to import files such as `LICENSE` from the `newrelic` module.
    // See https://nextjs.org/docs/app/api-reference/next-config-js/serverComponentsExternalPackages.
    serverComponentsExternalPackages: ['newrelic'],
  },
  webpack: (config) => {
    // In order for newrelic to effectively instrument a Next.js application,
    // the modules that newrelic supports should not be mangled by webpack. Thus,
    // we need to "externalize" all of the modules that newrelic supports.
    nrExternals(config)
    return config
  },
  ...,
}

module.exports = nextConfig
```

## 5. Next.jsへの適用 (クライアントサイド)

### 5-1. Layout.jsで下記の様に定義します。

```ts
import newrelic from 'newrelic'
import Script from 'next/script'

...

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const browserTimingHeader = newrelic.getBrowserTimingHeader({
    hasToRemoveScriptWrapper: true,
  })
  return (
    <html lang="ja">
      ...
      <Script
        id='nr-browser-agent'
        strategy='beforeInteractive'
        dangerouslySetInnerHTML={{ __html: browserTimingHeader }}
      />
    </html>
  )
}
```

## 6. 実行！

### 6-1. ローカルで実行&アクセスして、実際にデータが送信されているかチェックします。

```bash
bun dev
```
(npm run dev, )

### 6-3. サーバーサイドのデータが送信されてるか確認

サーバーサイドのデータは、 __AMP & Services__ から確認できます。

![](https://storage.googleapis.com/zenn-user-upload/a488c813c866-20240824.png)

### 6-3. クライアントサイドのデータが送信されてるか確認

クライアントサイドのデータは、 __Browser__ から確認できます。
![](https://storage.googleapis.com/zenn-user-upload/39887d654867-20240824.png)


---

以上です！
簡単に導入できるのに加え、設定なしでもかなりのメトリクスが見れていい感じでした！