Node.js アプリケーション向け New Relic APM 設定ガイド

Node.js アプリケーションでの New Relic APM 導入は、非同期処理とイベント駆動アーキテクチャに特化した監視ソリューションを提供します。Node.js エージェントを使用することで、API のレスポンス時間、非同期処理の追跡、マイクロサービス間の連携などを詳細に監視できます。

Node.js エージェントの特徴

Node.js エージェントの概要

New Relic Node.js エージェントは、V8 エンジンと統合して動作し、JavaScript の非同期実行モデルに最適化された監視機能を提供します。Promise、async/await、コールバック関数などの非同期パターンを自動的に追跡し、複雑な実行フローを可視化します。

エージェントは以下の情報を自動的に収集します:

  • HTTP リクエストとレスポンスの処理時間
  • 非同期処理の実行フロー
  • データベースクエリとORMの操作
  • エラーとスタックトレース

事前準備

Node.js エージェントは Node.js 16.x 以降をサポートしており(Node.js 18.x+ LTS 推奨)、最新の LTS バージョンでの使用を推奨します。ES6+ モジュール、TypeScript、CommonJS の各モジュールシステムに対応しています。

サポート環境:

  • Node.js バージョン: 16.x, 18.x, 20.x, 21.x (LTS推奨)
  • フレームワーク: Express 4.x+, Koa 2.x+, Fastify 4.x+, NestJS 8.x+
  • TypeScript: 4.x, 5.x サポート
  • パッケージマネージャー: npm, yarn, pnpm
  • モジュールシステム: CommonJS, ES Modules (ESM)

システム要件

Node.js エージェントを導入する前に、以下の要件を確認してください:

  • Node.js 14.x 以降(LTS バージョンを推奨)
  • npm、yarn、pnpm などのパッケージマネージャー
  • Express、Koa、Fastify などのWebフレームワーク(任意)

New Relic アカウントの準備

New Relic のアカウント作成とライセンスキーの取得が必要です。アカウント作成後、「APM & Services」から新しいアプリケーションを追加し、Node.js を選択してライセンスキーを取得してください。

エージェントのインストール

npm を使用してエージェントをインストールします:

bash
# 最新版のインストール
npm install newrelic@latest

# 特定バージョンの指定(推奨)
npm install [email protected]

yarn を使用する場合:

bash
yarn add newrelic

TypeScript プロジェクトでの型定義

bash
# TypeScriptプロジェクトでの型定義(最新版)
npm install --save-dev @types/newrelic@latest

# または
# TypeScript 5.x 対応の最新版を確認
npm install --save-dev typescript@^5.0.0

基本設定の構成

設定ファイルの作成

プロジェクトルートに newrelic.js 設定ファイルを作成します:

javascript
// newrelic.js - セキュリティ強化版
'use strict'

exports.config = {
  app_name: [process.env.NEW_RELIC_APP_NAME || 'My Node.js Application'],
  license_key: process.env.NEW_RELIC_LICENSE_KEY,
  distributed_tracing: {
    enabled: true
  },
  span_events: {
    enabled: true,
    max_samples_stored: 2000
  },
  logging: {
    level: process.env.NEW_RELIC_LOG_LEVEL || 'info',
    filepath: 'stdout'
  },
  allow_all_headers: true,
  attributes: {
    enabled: true,
    exclude: [
      'request.headers.cookie',
      'request.headers.authorization',
      'request.headers.proxy-authorization',
      'request.headers.set-cookie*',
      'request.headers.x-*',
      'response.headers.cookie',
      'response.headers.authorization',
      'response.headers.proxy-authorization',
      'response.headers.set-cookie*',
      'response.headers.x-*',
      // セキュリティ強化: 機密情報の除外
      'request.parameters.password',
      'request.parameters.token',
      'request.parameters.api_key',
      'request.parameters.secret'
    ]
  },
  security: {
    agent: {
      enabled: true
    }
  }
}

YOUR_LICENSE_KEY_HERE の部分を、取得したライセンスキーに置き換えてください。

環境変数での設定

.env ファイルを使用した設定も可能です:

bash
# .env ファイル (セキュリティ強化)
# 本番環境では環境変数管理システムを使用
NEW_RELIC_APP_NAME="My Node.js Application"
NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY}  # 環境変数から取得
NEW_RELIC_LOG_LEVEL=info
NEW_RELIC_ENABLED=true
NEW_RELIC_DISTRIBUTED_TRACING_ENABLED=true
NEW_RELIC_SPAN_EVENTS_ENABLED=true
NODE_ENV=production

エージェントの初期化

アプリケーション起動時の初期化

アプリケーションファイル(通常は app.js または index.js)の最初に New Relic エージェントを読み込みます:

javascript
// app.js の最上部に記述
require('newrelic');

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

ES6 モジュールでの初期化

ES6 モジュールを使用している場合:

javascript
// main.js
import './newrelic.js';
import express from 'express';

const app = express();

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(3000);

フレームワーク別の設定例

typescript
// main.ts - TypeScript 5.x 対応版
import './newrelic.js';  // ES Modulesでは拡張子が必要
import express, { Request, Response, NextFunction } from 'express';
import * as newrelic from 'newrelic';

const app = express();

// ミドルウェア: JSONパーサー
app.use(express.json({ limit: '10mb' }));

// カスタムミドルウェア: リクエスト情報をNew Relicに追加
app.use((req: Request, res: Response, next: NextFunction) => {
  newrelic.addCustomAttribute('request.method', req.method);
  newrelic.addCustomAttribute('request.url', req.url);
  newrelic.addCustomAttribute('user.ip', req.ip || req.connection.remoteAddress);
  next();
});

app.get('/', (req: Request, res: Response) => {
  res.json({ message: 'Hello World!', timestamp: new Date().toISOString() });
});

// ヘルスチェックエンドポイント
app.get('/health', (req: Request, res: Response) => {
  res.status(200).json({
    status: 'ok',
    service: 'nodejs-app',
    timestamp: new Date().toISOString(),
    newrelic: {
      enabled: process.env.NEW_RELIC_ENABLED === 'true',
      app_name: process.env.NEW_RELIC_APP_NAME
    }
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

export default app;

Fastify アプリケーション

Fastify でも同様に自動監視が開始されます:

javascript
require('newrelic');
const fastify = require('fastify')();

fastify.get('/api/data', async (request, reply) => {
  const data = await fetchData();
  return data;
});

fastify.listen(3000);

非同期処理の監視

Node.js エージェントは非同期処理を自動的に追跡しますが、カスタム監視も簡単に追加できます:

javascript
const newrelic = require('newrelic');

async function processOrder(orderId) {
  try {
    const order = await fetchOrder(orderId);
    const payment = await processPayment(order);
    
    // カスタムイベントの記録
    newrelic.recordCustomEvent('OrderProcessed', {
      orderId: orderId,
      amount: order.amount
    });
    
    return { order, payment };
  } catch (error) {
    newrelic.noticeError(error);
    throw error;
  }
}

カスタム計測の追加

カスタムメトリクスの記録

重要なビジネス指標を記録する場合:

javascript
const newrelic = require('newrelic');

function recordBusinessMetrics(orderData) {
  // カスタムメトリクスの記録
  newrelic.recordMetric('Custom/Revenue', orderData.amount);
  newrelic.recordMetric('Custom/OrdersProcessed', 1);
  
  // カスタムイベントの記録
  newrelic.recordCustomEvent('BusinessEvent', {
    eventType: 'order_completed',
    revenue: orderData.amount,
    customerId: orderData.customerId
  });
}

監視データの確認

New Relic UI でのデータ確認

エージェント導入後、数分で New Relic のダッシュボードにデータが表示されます。確認できる主要な情報:

  • 概要: アプリケーションの全体的なパフォーマンス
  • トランザクション: 各エンドポイントの処理時間
  • データベース: クエリの実行時間とN+1問題の検出
  • エラー: 発生したエラーとその頻度

基本的なメトリクス

自動的に収集される基本メトリクス:

  • 平均レスポンス時間
  • スループット(RPM: Requests Per Minute)
  • エラー率
  • メモリ使用量とガベージコレクション

よくある問題と解決方法

エージェントが動作しない場合

  1. インポート順序: newrelic モジュールが最初に読み込まれているか確認
  2. ライセンスキー: 正しいキーが設定されているか確認
  3. ネットワーク接続: New Relic サーバーへの接続を確認

パフォーマンスへの影響を最小化

本番環境での設定例:

javascript
exports.config = {
  app_name: ['My Node.js App (Production)'],
  license_key: 'your_license_key',
  
  // パフォーマンス設定
  transaction_tracer: {
    enabled: true,
    transaction_threshold: 2.0
  },
  
  error_collector: {
    enabled: true,
    ignore_status_codes: [404, 401]
  }
}

Docker での設定

Docker コンテナでの使用例:

dockerfile
# マルチステージビルドでサイズ最小化
FROM node:20-alpine AS builder

# セキュリティアップデートと必要なパッケージ
RUN apk update && apk add --no-cache \
    dumb-init \
    && apk upgrade

WORKDIR /app

# package.jsonとlockファイルを先にコピー(キャッシュ最適化)
COPY package*.json ./
COPY package-lock.json* ./

# npm ciでセキュリティと速度を向上
RUN npm ci --only=production --audit=false

# 本番用コンテナ
FROM node:20-alpine AS production

# セキュリティ強化: 非特権ユーザー作成
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nextjs -u 1001 -G nodejs

# dumb-initでPID 1問題を解決
RUN apk add --no-cache dumb-init

WORKDIR /app

# node_modulesとアプリケーションコードをコピー
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
COPY --chown=nextjs:nodejs . .

# New Relic設定ファイルが存在することを確認
RUN test -f newrelic.js || (echo "newrelic.js not found" && exit 1)

# 非特権ユーザーに変更
USER nextjs

# ヘルスチェック用のポートを公開
EXPOSE 3000

# 環境変数のデフォルト値
ENV NODE_ENV=production
ENV NEW_RELIC_ENABLED=true
ENV NEW_RELIC_LOG_LEVEL=info

# dumb-initでNew Relicエージェントを含めて起動
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "-r", "./newrelic.js", "app.js"]

まとめ

yaml
# newrelic-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: newrelic-secret
  namespace: production
type: Opaque
data:
  license_key: <base64-encoded-license-key>
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-app
  namespace: production
  labels:
    app: nodejs-app
    version: v1.0.0
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nodejs-app
  template:
    metadata:
      labels:
        app: nodejs-app
        version: v1.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "3000"
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1001
        fsGroup: 1001
      containers:
      - name: app
        image: myapp:v1.0.0
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: false  # Node.jsは一時ファイルが必要
          capabilities:
            drop:
            - ALL
        env:
        - name: NODE_ENV
          value: "production"
        - name: NEW_RELIC_APP_NAME
          value: "MyApp (Kubernetes)"
        - name: NEW_RELIC_LICENSE_KEY
          valueFrom:
            secretKeyRef:
              name: newrelic-secret
              key: license_key
        - name: NEW_RELIC_ENABLED
          value: "true"
        - name: NEW_RELIC_DISTRIBUTED_TRACING_ENABLED
          value: "true"
        - name: NEW_RELIC_LOG_LEVEL
          value: "info"
        ports:
        - containerPort: 3000
          name: http
        resources:
          requests:
            memory: "256Mi"
            cpu: "200m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 10
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        # 一時ファイル用ボリューム
        volumeMounts:
        - name: tmp-volume
          mountPath: /tmp
      volumes:
      - name: tmp-volume
        emptyDir: {}

まずは基本設定でデータ収集を開始し、アプリケーションの特性に応じてカスタム監視を追加することで、効果的なパフォーマンス監視システムを構築できます。

セキュリティとパフォーマンスのベストプラクティス

セキュリティ考慮事項

推奨設定

  1. ライセンスキー管理: 環境変数で管理し、コードにハードコードしない
  2. 機密情報の除外: パスワード、トークン、APIキーをテレメトリから除外
  3. HTTPS通信: New Relicへのデータ送信を暗号化
  4. コンテナセキュリティ: 非特権ユーザーでアプリケーションを実行

初心者向けトラブルシューティング

エージェントがデータを送信しない場合

  1. newrelic.jsが最初に読み込まれているか確認

    javascript
    // app.jsの最初の行
    require('./newrelic');
  2. ライセンスキーの確認

    bash
    echo $NEW_RELIC_LICENSE_KEY
  3. Node.jsバージョンの確認

    bash
    node --version  # 16.x 以上か確認
  4. ネットワーク接続の確認

    bash
    curl -I https://collector.newrelic.com

パフォーマンス最適化

javascript
// newrelic.js - パフォーマンス最適化設定
exports.config = {
  // サンプリング率の調整
  span_events: {
    max_samples_stored: 1000  // デフォルト: 2000
  },
  transaction_tracer: {
    transaction_threshold: 1.0  // 1秒以上のトランザクションのみトレース
  },
  error_collector: {
    max_stack_trace_lines: 50  // スタックトレースの行数制限
  }
};

Node.js エージェント設定パラメータ完全リファレンス

環境変数設定

パラメータ名データ型デフォルト値説明使用例
NEW_RELIC_LICENSE_KEYstringなしNew Relicライセンスキー(必須)your_license_key_here
NEW_RELIC_APP_NAMEstringMy Applicationアプリケーション名(セミコロン区切りで最大3個まで)My Node App;My App (Staging)
NEW_RELIC_ENABLEDbooleantrueエージェント全体の有効化false
NEW_RELIC_LOG_LEVELstringinfoログレベルtrace, debug, info, warn, error
NEW_RELIC_HOMEstringなし設定ファイル(newrelic.js)の場所/path/to/config
NEW_RELIC_USE_ESMbooleanfalseES Moduleサポート有効化true
NEW_RELIC_DISTRIBUTED_TRACING_ENABLEDbooleantrue分散トレーシング有効化true
NEW_RELIC_SPAN_EVENTS_ENABLEDbooleantrueスパンイベント有効化true
NEW_RELIC_NO_CONFIG_FILEbooleanfalse設定ファイル不要モードtrue
NEW_RELIC_NATIVE_METRICS_ENABLEDbooleantrueネイティブメトリクス収集有効化false

プロキシ設定環境変数

パラメータ名データ型デフォルト値説明使用例
NEW_RELIC_PROXY_URLstringなしプロキシURL(他のプロキシ設定をオーバーライド)http://proxy.example.com:8080
NEW_RELIC_PROXY_HOSTstringなしプロキシホスト名proxy.example.com
NEW_RELIC_PROXY_PORTintなしプロキシポート番号8080
NEW_RELIC_PROXY_USERstringなしプロキシ認証ユーザー名proxy_user
NEW_RELIC_PROXY_PASSstringなしプロキシ認証パスワードproxy_password

エラー処理・無視設定

パラメータ名データ型デフォルト値説明使用例
NEW_RELIC_ERROR_COLLECTOR_ENABLEDbooleantrueエラーコレクター有効化true
NEW_RELIC_ERROR_COLLECTOR_IGNORE_ERROR_CODESstringなし無視するHTTPエラーコード(カンマ区切り)404,500,429
NEW_RELIC_IGNORING_RULESstringなし無視するURLパターン(カンマ区切り)^/socket\.io/.*,ignore_me

newrelic.js 設定ファイル

設定項目データ型デフォルト値説明設定例
app_namearray['My Application']アプリケーション名配列['My Node.js App', 'Staging']
license_keystringなしライセンスキーprocess.env.NEW_RELIC_LICENSE_KEY
logging.levelstringinfoログレベルdebug, info, warn, error
logging.filepathstringstdoutログファイルパス/var/log/newrelic.log
allow_all_headersbooleanfalse全HTTPヘッダーの記録許可true
distributed_tracing.enabledbooleantrue分散トレーシング有効化true
span_events.enabledbooleantrueスパンイベント有効化true
span_events.max_samples_storedint2000最大スパンサンプル保存数1000

トランザクション追跡設定

設定項目データ型デフォルト値説明設定例
transaction_tracer.enabledbooleantrueトランザクション追跡有効化true
transaction_tracer.transaction_thresholddouble2.0トランザクション追跡閾値(秒)1.0
transaction_tracer.top_nint20最上位トランザクション数50
transaction_tracer.record_sqlstringobfuscatedSQL記録モードoff, obfuscated, raw

エラー収集設定

設定項目データ型デフォルト値説明設定例
error_collector.enabledbooleantrueエラー収集有効化true
error_collector.ignore_status_codesarray[]無視するHTTPステータスコード[404, 401]
error_collector.expected_messagesobject{}期待されるエラーメッセージ{ 'Error': ['expected message'] }
error_collector.capture_eventsbooleantrueエラーイベント収集true
error_collector.max_event_samples_storedint100最大エラーイベント保存数200

カスタム属性設定

設定項目データ型デフォルト値説明設定例
attributes.enabledbooleantrue属性収集有効化true
attributes.includearray[]含める属性パターン['request.parameters.*']
attributes.excludearrayデフォルト除外設定除外する属性パターン['request.headers.cookie']

セキュリティ設定

設定項目データ型デフォルト値説明設定例
security.agent.enabledbooleantrueセキュリティエージェント有効化true
security.modestringIASTセキュリティモードIAST, RASP
security.validator_service_urlstringデフォルトURLセキュリティ検証サービスURL公式URL

特殊環境設定

設定項目データ型デフォルト値説明設定例
worker_threads.enabledbooleanfalseワーカースレッド対応(v11.3.0+)true
heroku.use_dyno_namesbooleanfalseHeroku dyno名をホスト名として使用true
serverless_mode.enabledbooleanfalseサーバーレスモード有効化true

パフォーマンス最適化設定

設定項目データ型デフォルト値説明推奨値
transaction_tracer.max_segments_webint2000Web最大セグメント数1000
transaction_tracer.max_segments_cliint100000CLI最大セグメント数50000
slow_sql.enabledbooleantrue低速SQL追跡有効化true
slow_sql.max_samplesint10低速SQL最大サンプル数20

関連記事