Node.js環境でのOpenTelemetry計装 - npmパッケージ設定とExpress対応
Node.js で実行されるアプリケーションに OpenTelemetry を導入するには、適切な npm パッケージの選定とその設定が重要です。本記事では、必要なパッケージから始まり、自動計装の仕組み、Express.js との連携、そして TypeScript 環境での対応方法までを段階的に説明します。
Node.js 計装に必要な NPM パッケージ
OpenTelemetry を Node.js で使用するには、複数のパッケージを組み合わせて利用します。それぞれのパッケージは明確な役割を持っており、適切に選定することで、効率的に計装できます。
コア パッケージの構成
Node.js アプリケーション向けの基本的なパッケージ構成は以下の通りです。まず @opentelemetry/api はトレーシングやメトリクスの標準 API を提供し、アプリケーションコードで直接使用します。次に @opentelemetry/sdk-node は Node.js 環境用の SDK で、テレメトリデータの収集と処理を担当します。
@opentelemetry/resources はアプリケーションのメタ情報(サービス名やバージョンなど)をテレメトリに付与し、@opentelemetry/semantic-conventions は業界標準の属性名を定義しています。これらを組み合わせることで、監視ツール側で一貫性のあるデータを受け取ることができます。
自動計装パッケージの選択肢
自動計装とは、アプリケーションコードを大きく変更することなく、ライブラリやフレームワークの動作を自動的に監視する仕組みです。OpenTelemetry では 2 つのアプローチが提供されています。
@opentelemetry/auto-instrumentations-node はメタパッケージで、HTTP、Express、データベースクライアント、その他の一般的なライブラリの計装を一括で提供します。このアプローチは利便性が高く、すぐに計装を開始できるメリットがあります。一方で依存関係が増加するため、本番環境では不要な計装を無効化することをお勧めします。
一方、個別のパッケージを選択することも可能です。たとえば @opentelemetry/instrumentation-http では HTTP リクエスト、@opentelemetry/instrumentation-express では Express ミドルウェアを計装します。この方法では依存関係を最小限に抑えられ、必要なものだけを導入できます。
エクスポーター パッケージ
テレメトリデータを外部の監視ツールに送信するには、エクスポーターが必要です。@opentelemetry/exporter-trace-otlp-http は OTLP(OpenTelemetry Protocol)形式でトレースを HTTP 経由で送信します。Jaeger、Grafana Tempo、Datadog、New Relic など、OTLP に対応した監視ツールであれば、このエクスポーターで統一的に送信できます。
インストール方法は npm コマンドで簡単です。基本的なセットアップでは、コアパッケージに自動計装パッケージ、そしてエクスポーターを組み合わせるだけで、機能的な計装環境が整います。
npm install @opentelemetry/api @opentelemetry/sdk-node \
@opentelemetry/resources @opentelemetry/semantic-conventions \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-http自動計装の設定とプロセス起動
OpenTelemetry SDK は、アプリケーションの起動時に初期化される必要があります。重要なのは、その他のすべてのモジュールよりも 前に SDK を初期化することです。SDK の初期化が遅れると、ライブラリが no-op(何もしない)実装を使用し、テレメトリが記録されなくなってしまいます。
SDK 初期化の基本
Node.js アプリケーションでは、エントリーポイント(通常は main.js)の最初の行で SDK を初期化します。以下の流れが標準的なパターンです。
// 最初にSDKをインポート
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
// 自動計装の登録
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter(),
instrumentations: [getNodeAutoInstrumentations()]
});
// SDKを開始(必ず他の処理より前に)
sdk.start();
// その後、アプリケーション固有のモジュールをインポート
import('./app.js');このパターンの要点は、SDK の初期化後に動的インポート(import())を使ってアプリケーションを読み込む点です。そうすることで、アプリケーション起動時にはすでにインストルメンテーション機構が活動状態になっており、その後読み込まれるすべてのライブラリが自動計装の対象になります。
自動計装の仕組み
自動計装は Node.js の require フック と呼ばれるメカニズムを使用しています。SDK 起動時に、モジュールの読み込み時に自動的に計装コードが注入されます。そのため、Express などのフレームワークのコードを直接変更する必要がなく、透過的にトレースが記録されるようになります。
また、自動計装パッケージに含まれる計装は、すべてを有効にする必要はありません。使用していないライブラリの計装は無効化して、パフォーマンスオーバーヘッドを削減することが本番環境では重要です。
// 必要なインストルメンテーションをインポート
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
// Express と HTTP 計装など、特定のインストルメンテーションのみを有効化する例
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter(),
instrumentations: [
new ExpressInstrumentation(),
new HttpInstrumentation()
]
});Express.js との連携
Express はシンプルで使いやすい Node.js ウェブフレームワークで、多くの本番アプリケーションで採用されています。OpenTelemetry の計装を Express に適用する場合、いくつかのポイントがあります。
自動計装による HTTP トレーシング
Express アプリケーション自体は、@opentelemetry/instrumentation-express により自動計装されます。自動計装を有効にすると、HTTP リクエストごとにスパンが自動的に作成され、リクエスト時刻、レスポンスステータス、処理時間などが記録されます。
実装者は通常、追加のセットアップをほぼ必要としません。自動計装が既に以下の情報を取得しています。
- HTTP メソッドと URL パス
- レスポンスのステータスコード
- リクエスト処理時間
- エラー発生時のエラー情報
ただし、アプリケーション固有の情報(ユーザー ID やリクエスト ID など)をスパンに追加したい場合には、リクエストフックを使用します。これにより、自動計装と手動計装の組み合わせが可能です。
リクエスト・レスポンス フック
Express 計装には、スパン作成後に追加情報を付与するためのフック機構が用意されています。
new ExpressInstrumentation({
requestHook: (span, request) => {
// 'enduser.id' は OpenTelemetry 標準規約で推奨される属性です
span.setAttribute('enduser.id', request.user?.id);
span.setAttribute('request.id', request.id);
},
responseHook: (span, response) => {
// 'http.response_content_length' は標準の属性名です
span.setAttribute('http.response_content_length',
response.get('content-length'));
}
});このようなフックを活用することで、リクエスト単位のトレーシングに必要なビジネスロジック固有の情報を記録できます。
エラーハンドリングとトレース
Express のエラーハンドリングミドルウェアで例外が処理される場合、自動計装はそれらのエラー情報をスパンに記録します。ただし、キャッチされない例外や意図的に投げられた例外は、適切にハンドルされる必要があります。
Express アプリケーションに OpenTelemetry を統合する際は、エラーハンドリングのタイミングを意識することが重要です。リクエスト処理中に発生したエラーは、自動計装により自動的に記録されるため、多くの場合は追加実装が不要です。
TypeScript 環境での対応
近年、Node.js プロジェクトの多くが TypeScript で実装されています。OpenTelemetry は TypeScript のネイティブサポートを提供しており、型安全な開発が可能です。
型定義と npm パッケージ
OpenTelemetry の公式パッケージは、すべて TypeScript の型定義(.d.ts ファイル)を含んでいます。別途 @types/* パッケージをインストールする必要はなく、パッケージをインストールするだけで型チェックが機能します。
IDE のインテリセンスも自動的に動作し、API の使用方法を開発時に確認できます。この環境では、トレーサーやメーターの型推論により、ランタイムエラーを事前に検出しやすくなります。
tsconfig.json の設定
TypeScript プロジェクトで OpenTelemetry を使用する際、tsconfig.json に特別な設定は通常不要です。標準的な設定で問題ありません。ただし、モジュール方式 には注意が必要です。
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true
}
}このように ES モジュール形式を使用する場合、OpenTelemetry のパッケージは問題なく動作します。CommonJS を使用している場合でも、ほぼ同様の設定で対応可能です。
実装パターン
TypeScript での実装は JavaScript と基本的に同じですが、型注釈により一層明確なコードになります。
import { NodeSDK } from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
const sdk: NodeSDK = new NodeSDK({
traceExporter: new OTLPTraceExporter(),
instrumentations: [getNodeAutoInstrumentations()]
});
sdk.start();
import('./app.js');TypeScript を使用することで、設定の誤りやパッケージ名の入力ミスが事前に検出され、デバッグ時間の削減につながります。
セットアップの全体的な流れ
以下の図は、Node.js アプリケーション起動から OpenTelemetry によるテレメトリ送信までの流れをまとめたものです。
このプロセスにより、アプリケーション側での追加実装を最小限に抑えながら、包括的なテレメトリ収集が実現します。
セットアップで気をつけるポイント
Node.js での OpenTelemetry セットアップには、いくつかの注意点があります。
SDK 初期化のタイミング が最も重要です。SDK の初期化が遅れると、その後で読み込まれるモジュールは no-op 実装となり、トレースが記録されません。エントリーポイント冒頭で初期化する習慣をつけることが大切です。
本番環境でのパフォーマンス も考慮が必要です。不要な計装を無効化し、サンプリングレートを調整することで、オーバーヘッドを最小限に保てます。初期段階では 100% でデータを収集し、問題がないことを確認してからサンプリングレートを下げるアプローチが一般的です。
OTLP エンドポイント の設定も重要です。エンドポイント URL が正しく、監視ツール側が OTLP に対応していることを確認してください。エンドポイントが不正な場合、テレメトリ送信が失敗しますが、アプリケーション自体は影響を受けないよう設計されています。
本記事では、Node.js アプリケーションへの OpenTelemetry 導入に必要なパッケージ選定、自動計装の仕組み、Express や TypeScript との連携を説明しました。これらの知識により、本番環境での導入準備が整います。次は実際に計装したアプリケーションから得られるトレースの活用方法や、より高度な設定方法を学んでいくことをお勧めします。