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 を使用してエージェントをインストールします:
# 最新版のインストール
npm install newrelic@latest
# 特定バージョンの指定(推奨)
npm install [email protected]
yarn を使用する場合:
yarn add newrelic
TypeScript プロジェクトでの型定義
# TypeScriptプロジェクトでの型定義(最新版)
npm install --save-dev @types/newrelic@latest
# または
# TypeScript 5.x 対応の最新版を確認
npm install --save-dev typescript@^5.0.0
基本設定の構成
設定ファイルの作成
プロジェクトルートに newrelic.js
設定ファイルを作成します:
// 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
ファイルを使用した設定も可能です:
# .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 エージェントを読み込みます:
// 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 モジュールを使用している場合:
// main.js
import './newrelic.js';
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000);
フレームワーク別の設定例
// 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 でも同様に自動監視が開始されます:
require('newrelic');
const fastify = require('fastify')();
fastify.get('/api/data', async (request, reply) => {
const data = await fetchData();
return data;
});
fastify.listen(3000);
非同期処理の監視
Node.js エージェントは非同期処理を自動的に追跡しますが、カスタム監視も簡単に追加できます:
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;
}
}
カスタム計測の追加
カスタムメトリクスの記録
重要なビジネス指標を記録する場合:
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)
- エラー率
- メモリ使用量とガベージコレクション
よくある問題と解決方法
エージェントが動作しない場合
- インポート順序: newrelic モジュールが最初に読み込まれているか確認
- ライセンスキー: 正しいキーが設定されているか確認
- ネットワーク接続: New Relic サーバーへの接続を確認
パフォーマンスへの影響を最小化
本番環境での設定例:
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 コンテナでの使用例:
# マルチステージビルドでサイズ最小化
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"]
まとめ
# 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: {}
まずは基本設定でデータ収集を開始し、アプリケーションの特性に応じてカスタム監視を追加することで、効果的なパフォーマンス監視システムを構築できます。
セキュリティとパフォーマンスのベストプラクティス
セキュリティ考慮事項
推奨設定
- ライセンスキー管理: 環境変数で管理し、コードにハードコードしない
- 機密情報の除外: パスワード、トークン、APIキーをテレメトリから除外
- HTTPS通信: New Relicへのデータ送信を暗号化
- コンテナセキュリティ: 非特権ユーザーでアプリケーションを実行
初心者向けトラブルシューティング
エージェントがデータを送信しない場合
newrelic.jsが最初に読み込まれているか確認
javascript// app.jsの最初の行 require('./newrelic');
ライセンスキーの確認
bashecho $NEW_RELIC_LICENSE_KEY
Node.jsバージョンの確認
bashnode --version # 16.x 以上か確認
ネットワーク接続の確認
bashcurl -I https://collector.newrelic.com
パフォーマンス最適化
// 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_KEY | string | なし | New Relicライセンスキー(必須) | your_license_key_here |
NEW_RELIC_APP_NAME | string | My Application | アプリケーション名(セミコロン区切りで最大3個まで) | My Node App;My App (Staging) |
NEW_RELIC_ENABLED | boolean | true | エージェント全体の有効化 | false |
NEW_RELIC_LOG_LEVEL | string | info | ログレベル | trace , debug , info , warn , error |
NEW_RELIC_HOME | string | なし | 設定ファイル(newrelic.js)の場所 | /path/to/config |
NEW_RELIC_USE_ESM | boolean | false | ES Moduleサポート有効化 | true |
NEW_RELIC_DISTRIBUTED_TRACING_ENABLED | boolean | true | 分散トレーシング有効化 | true |
NEW_RELIC_SPAN_EVENTS_ENABLED | boolean | true | スパンイベント有効化 | true |
NEW_RELIC_NO_CONFIG_FILE | boolean | false | 設定ファイル不要モード | true |
NEW_RELIC_NATIVE_METRICS_ENABLED | boolean | true | ネイティブメトリクス収集有効化 | false |
プロキシ設定環境変数
パラメータ名 | データ型 | デフォルト値 | 説明 | 使用例 |
---|---|---|---|---|
NEW_RELIC_PROXY_URL | string | なし | プロキシURL(他のプロキシ設定をオーバーライド) | http://proxy.example.com:8080 |
NEW_RELIC_PROXY_HOST | string | なし | プロキシホスト名 | proxy.example.com |
NEW_RELIC_PROXY_PORT | int | なし | プロキシポート番号 | 8080 |
NEW_RELIC_PROXY_USER | string | なし | プロキシ認証ユーザー名 | proxy_user |
NEW_RELIC_PROXY_PASS | string | なし | プロキシ認証パスワード | proxy_password |
エラー処理・無視設定
パラメータ名 | データ型 | デフォルト値 | 説明 | 使用例 |
---|---|---|---|---|
NEW_RELIC_ERROR_COLLECTOR_ENABLED | boolean | true | エラーコレクター有効化 | true |
NEW_RELIC_ERROR_COLLECTOR_IGNORE_ERROR_CODES | string | なし | 無視するHTTPエラーコード(カンマ区切り) | 404,500,429 |
NEW_RELIC_IGNORING_RULES | string | なし | 無視するURLパターン(カンマ区切り) | ^/socket\.io/.*,ignore_me |
newrelic.js 設定ファイル
設定項目 | データ型 | デフォルト値 | 説明 | 設定例 |
---|---|---|---|---|
app_name | array | ['My Application'] | アプリケーション名配列 | ['My Node.js App', 'Staging'] |
license_key | string | なし | ライセンスキー | process.env.NEW_RELIC_LICENSE_KEY |
logging.level | string | info | ログレベル | debug , info , warn , error |
logging.filepath | string | stdout | ログファイルパス | /var/log/newrelic.log |
allow_all_headers | boolean | false | 全HTTPヘッダーの記録許可 | true |
distributed_tracing.enabled | boolean | true | 分散トレーシング有効化 | true |
span_events.enabled | boolean | true | スパンイベント有効化 | true |
span_events.max_samples_stored | int | 2000 | 最大スパンサンプル保存数 | 1000 |
トランザクション追跡設定
設定項目 | データ型 | デフォルト値 | 説明 | 設定例 |
---|---|---|---|---|
transaction_tracer.enabled | boolean | true | トランザクション追跡有効化 | true |
transaction_tracer.transaction_threshold | double | 2.0 | トランザクション追跡閾値(秒) | 1.0 |
transaction_tracer.top_n | int | 20 | 最上位トランザクション数 | 50 |
transaction_tracer.record_sql | string | obfuscated | SQL記録モード | off , obfuscated , raw |
エラー収集設定
設定項目 | データ型 | デフォルト値 | 説明 | 設定例 |
---|---|---|---|---|
error_collector.enabled | boolean | true | エラー収集有効化 | true |
error_collector.ignore_status_codes | array | [] | 無視するHTTPステータスコード | [404, 401] |
error_collector.expected_messages | object | {} | 期待されるエラーメッセージ | { 'Error': ['expected message'] } |
error_collector.capture_events | boolean | true | エラーイベント収集 | true |
error_collector.max_event_samples_stored | int | 100 | 最大エラーイベント保存数 | 200 |
カスタム属性設定
設定項目 | データ型 | デフォルト値 | 説明 | 設定例 |
---|---|---|---|---|
attributes.enabled | boolean | true | 属性収集有効化 | true |
attributes.include | array | [] | 含める属性パターン | ['request.parameters.*'] |
attributes.exclude | array | デフォルト除外設定 | 除外する属性パターン | ['request.headers.cookie'] |
セキュリティ設定
設定項目 | データ型 | デフォルト値 | 説明 | 設定例 |
---|---|---|---|---|
security.agent.enabled | boolean | true | セキュリティエージェント有効化 | true |
security.mode | string | IAST | セキュリティモード | IAST , RASP |
security.validator_service_url | string | デフォルトURL | セキュリティ検証サービスURL | 公式URL |
特殊環境設定
設定項目 | データ型 | デフォルト値 | 説明 | 設定例 |
---|---|---|---|---|
worker_threads.enabled | boolean | false | ワーカースレッド対応(v11.3.0+) | true |
heroku.use_dyno_names | boolean | false | Heroku dyno名をホスト名として使用 | true |
serverless_mode.enabled | boolean | false | サーバーレスモード有効化 | true |
パフォーマンス最適化設定
設定項目 | データ型 | デフォルト値 | 説明 | 推奨値 |
---|---|---|---|---|
transaction_tracer.max_segments_web | int | 2000 | Web最大セグメント数 | 1000 |
transaction_tracer.max_segments_cli | int | 100000 | CLI最大セグメント数 | 50000 |
slow_sql.enabled | boolean | true | 低速SQL追跡有効化 | true |
slow_sql.max_samples | int | 10 | 低速SQL最大サンプル数 | 20 |
関連記事