OpenTelemetry Node-JS¶
OpenTelemetry Node.js の自動インスツルメンテーションモジュールは、起動パラメータによるプリロードを使用して、アプリケーションの依存関係が読み込まれる前にフックを登録します。ビジネスコードを変更することなく、サポートされている Web フレームワーク、HTTP クライアント、データベース、メッセージキューなどの呼び出しを収集できます。
標準の OpenTelemetry 機能に加えて、Guance は Node.js 向けにプロファイル拡張機能を提供します。この機能は @cloudcare/profiler-nodejs と @datadog/pprof に基づいており、wall、heap プロファイルを収集し、DataKit の /profiling/v1/input エンドポイントを通じて報告します。プロファイル拡張は OpenTelemetry の公式標準機能ではなく、本ドキュメントではコードレス接続以外の補足的なソリューションとして記載しています。
本ドキュメントでは、DataKit の OpenTelemetry コレクターを使用して OTLP データを受信し、Guance に転送します:
前提条件¶
- OpenTelemetry JavaScript が現在サポートしている Node.js LTS バージョンを使用していること;
- アプリケーションが npm、pnpm、または Yarn で依存関係を管理していること;
- DataKit がインストールされ、対象の Guance ワークスペースに接続されていること;
- Node.js アプリケーションから DataKit へのネットワーク到達性があること:OTLP/HTTP は DataKit HTTP ポート
9529を使用し、OTLP/gRPC はデフォルトで4317を使用します。
バージョンと拡張サポート¶
- Node.js:自動インスツルメンテーションパッケージは通常
^18.19.0または>=20.6.0を必要とし、本番環境では現在サポートされている LTS バージョンを使用し、実際にインストールされたパッケージのengines宣言に従うことを推奨します; - OpenTelemetry:現在の安定バージョンを使用し、ロックファイルで実際のデプロイバージョンを固定することを推奨します;
- プロファイル拡張パッケージ:
@cloudcare/profiler-nodejs; - デフォルトのプロファイリング報告先:
http://127.0.0.1:9529/profiling/v1/input。
1. OpenTelemetry コレクターを有効にする¶
DataKit のインストールディレクトリ内の conf.d/opentelemetry に移動します。コレクターの設定がまだ作成されていない場合は、サンプルファイルをコピーします:
opentelemetry.conf に少なくとも以下の受信設定が含まれていることを確認します:
[[inputs.opentelemetry]]
# Guance でタグとして保持するカスタム属性をホワイトリストに追加します。
customer_tags = ["team", "project"]
[inputs.opentelemetry.http]
http_status_ok = 200
trace_api = "/otel/v1/traces"
metric_api = "/otel/v1/metrics"
logs_api = "/otel/v1/logs"
[inputs.opentelemetry.grpc]
addr = "127.0.0.1:4317"
max_payload = 16777216
受信アドレスは以下の通りです:
| プロトコル | データタイプ | DataKit 受信アドレス |
|---|---|---|
| OTLP/HTTP + Protobuf | トレース | http://<DataKit-IP>:9529/otel/v1/traces |
| OTLP/HTTP + Protobuf | メトリクス | http://<DataKit-IP>:9529/otel/v1/metrics |
| OTLP/HTTP + Protobuf | ログ | http://<DataKit-IP>:9529/otel/v1/logs |
| OTLP/gRPC | トレース、メトリクス、ログ | http://<DataKit-IP>:4317 |
Node.js アプリケーションと DataKit が同一ホストにない場合は、実際のデプロイに合わせて DataKit のリスニングアドレス、ファイアウォール、またはその他のネットワークアクセス制御を調整してください。gRPC の場合は、addr をアプリケーションがアクセス可能なリスニングアドレス(例:0.0.0.0:4317)に変更できます。OTLP 受信ポートをパブリックネットワークに直接公開しないでください。
DataKit を再起動し、サービスを確認します:
2. アプリケーションを OpenTelemetry に接続する¶
自動インスツルメンテーションモジュールのインストール¶
アプリケーションプロジェクトのディレクトリで、npm 公式リポジトリから OpenTelemetry の公式パッケージをインストールします:
@opentelemetry/auto-instrumentations-node には、Node.js SDK、自動インスツルメンテーションライブラリ、および一般的なエクスポーターが含まれています。このパッケージは、サポートされており、かつ実際に読み込まれたライブラリに対してのみテレメトリデータを生成します。アプリケーションが使用するフレームワークやクライアントがサポートリストに含まれていない場合、対応するスパンは自動的に生成されません。
環境変数による起動¶
以下は OTLP/HTTP + Protobuf を例としています。デフォルトではトレースを有効にし、メトリクスとログは一時的に無効にします:
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="env=prod,version=1.0.0,team=backend"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="none"
export OTEL_LOGS_EXPORTER="none"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:9529/otel"
export OTEL_PROPAGATORS="tracecontext,baggage"
export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
node app.js
OTEL_EXPORTER_OTLP_ENDPOINT はベースアドレスです。OTLP/HTTP エクスポーターはデータタイプに応じて自動的に /v1/traces、/v1/metrics、または /v1/logs を追加し、最終的に DataKit の /otel/v1/* ルートに対応します。
アプリケーションに既に NODE_OPTIONS がある場合は、元のパラメータを保持した上で --require @opentelemetry/auto-instrumentations-node/register を追加し、元の値を直接上書きしないでください。PM2、systemd、Supervisor、または npm スクリプトのシナリオでは、OTEL_* と NODE_OPTIONS を実際のアプリケーションプロセスの起動環境に記述してください。
起動パラメータによるロード¶
NODE_OPTIONS を設定せずに、Node.js の起動コマンドでモジュールをプリロードすることもできます:
自動インスツルメンテーションモジュールは、アプリケーションコードとその依存関係が実行される前に読み込む必要があります。node app.js の起動後に動的にモジュールを読み込まないでください。既に読み込まれたライブラリがインスツルメンテーションされない可能性があります。
一般的な起動方法¶
npm スクリプトで起動:
PM2 で起動する場合は、変数を ecosystem.config.js の env 設定に配置するか、プロセス管理プラットフォームの環境変数機能を使用して注入します。設定を変更した後はアプリケーションプロセスを再起動する必要があります。ホットリロードだけではプリロードモジュールが再読み込みされない場合があります。
OTLP/gRPC の使用¶
OTLP/gRPC に変更する場合は、プロトコルとエンドポイントを置き換えるだけです:
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:4317"
gRPC エンドポイントには /v1/traces などの HTTP パスを追加できません。
3. データ報告パラメータ¶
基本パラメータ¶
| 環境変数 | 説明 | 推奨値または例 |
|---|---|---|
OTEL_SERVICE_NAME |
service.name を設定します。設定されていない場合、サービスは安定して識別できません。 |
order-service、本番環境では明示的に設定する必要があります。 |
OTEL_RESOURCE_ATTRIBUTES |
リソース属性。カンマ区切りの key=value 形式。 |
env=prod,version=1.0.0,team=backend |
OTEL_TRACES_EXPORTER |
トレースエクスポーター。 | DataKit に報告する場合は otlp を設定。無効にする場合は none を設定。 |
OTEL_METRICS_EXPORTER |
メトリクスエクスポーター。 | メトリクスを報告する必要がある場合は otlp、それ以外の場合は none を設定。 |
OTEL_LOGS_EXPORTER |
ログエクスポーター。 | ログを報告する必要がある場合は otlp、それ以外の場合は none を設定。 |
OTEL_PROPAGATORS |
サービス間のコンテキスト伝搬形式。 | デフォルト tracecontext,baggage。全チェーンで互換性を維持する必要があります。 |
OTEL_SDK_DISABLED |
OpenTelemetry SDK を無効にします。 | デフォルト false。緊急時に無効にする場合は true を設定。 |
service.name は Guance でのサービス所属に使用されます。env と version も併せて設定し、環境やバージョンによるフィルタリングを可能にすることを推奨します。その他のカスタムリソース属性は、タグとして保持されるために DataKit の customer_tags ホワイトリストに追加する必要があります。属性名の . は _ に変換されます。
Node.js 自動インスツルメンテーションパラメータ¶
| 環境変数 | 説明 | デフォルト値または例 |
|---|---|---|
NODE_OPTIONS |
アプリケーションの依存関係が読み込まれる前に、自動インスツルメンテーション登録モジュールをプリロードします。 | --require @opentelemetry/auto-instrumentations-node/register |
OTEL_NODE_RESOURCE_DETECTORS |
指定されたリソース検出器を有効にします。複数ある場合はカンマ区切り。 | デフォルト all。env,host,os,process または none に設定可能。 |
OTEL_NODE_ENABLED_INSTRUMENTATIONS |
リストされたインスツルメンテーションのみを有効にします。名前には @opentelemetry/instrumentation- プレフィックスは含めません。 |
http,express,pg |
OTEL_NODE_DISABLED_INSTRUMENTATIONS |
デフォルトリストから指定されたインスツルメンテーションを無効にします。 | fs,grpc |
OTEL_LOG_LEVEL |
OpenTelemetry 内部診断ログレベル。 | 本番環境では info を推奨。トラブルシューティング時に一時的に debug を使用。 |
有効化リストと無効化リストを同時に設定する場合、最初に OTEL_NODE_ENABLED_INSTRUMENTATIONS が適用され、次に無効化リストが適用されます。同じインスツルメンテーションが両方のリストに存在する場合、最終的には無効になります。複雑な個別のインスツルメンテーション設定は、環境変数だけでは完全に実行できません。これらは本ドキュメントのコードレス接続の範囲外です。
OTLP パラメータ¶
| 環境変数 | 説明 | 推奨値または例 |
|---|---|---|
OTEL_EXPORTER_OTLP_PROTOCOL |
すべてのシグナルの OTLP プロトコル。 | DataKit は http/protobuf または grpc をサポート。 |
OTEL_EXPORTER_OTLP_ENDPOINT |
すべてのシグナルで共通のベースアドレス。 | HTTP:http://datakit-host:9529/otel;gRPC:http://datakit-host:4317。 |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT |
トレースのみに使用されるアドレス。共通アドレスより優先。 | http://datakit-host:9529/otel/v1/traces |
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT |
メトリクスのみに使用されるアドレス。共通アドレスより優先。 | http://datakit-host:9529/otel/v1/metrics |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT |
ログのみに使用されるアドレス。共通アドレスより優先。 | http://datakit-host:9529/otel/v1/logs |
OTEL_EXPORTER_OTLP_HEADERS |
すべての OTLP リクエストに含まれるリクエストヘッダー。複数ある場合はカンマ区切り。 | x-tenant=tenant-a。DataKit の expected_headers と一致させる必要があります。 |
OTEL_EXPORTER_OTLP_COMPRESSION |
OTLP リクエストの圧縮方式。 | ホスト間の報告では gzip に設定可能。 |
OTEL_EXPORTER_OTLP_TIMEOUT |
1回のエクスポートのタイムアウト(ミリ秒)。 | 10000 |
DataKit の OTLP/HTTP 収集は Protobuf のみをサポートしています。http/protobuf を使用し、http/json は使用しないでください。統一エンドポイントと特定のデータタイプのエンドポイントが両方存在する場合、特定のデータタイプの設定が優先されます。
サンプリングとバッチ報告パラメータ¶
| 環境変数 | 説明 | デフォルト値または例 |
|---|---|---|
OTEL_TRACES_SAMPLER |
トレースヘッドサンプリング方式。 | デフォルト parentbased_always_on。比率サンプリングには parentbased_traceidratio を使用。 |
OTEL_TRACES_SAMPLER_ARG |
サンプリング方式のパラメータ。 | 0.1 はルートトレースを 10% サンプリングすることを意味します。 |
OTEL_BSP_SCHEDULE_DELAY |
スパンのバッチエクスポート間隔(ミリ秒)。 | デフォルト 5000。 |
OTEL_BSP_MAX_QUEUE_SIZE |
エクスポート待ちのスパンキューの上限。 | デフォルト 2048。 |
OTEL_BSP_MAX_EXPORT_BATCH_SIZE |
1バッチあたりの最大エクスポートスパン数。 | デフォルト 512。 |
OTEL_BSP_EXPORT_TIMEOUT |
スパンバッチエクスポートのタイムアウト(ミリ秒)。 | デフォルト 30000。 |
OTEL_METRIC_EXPORT_INTERVAL |
メトリクスエクスポート間隔(ミリ秒)。 | デフォルト 60000。 |
本番環境では、トラフィックとデータ予算に基づいてサンプリングレートを設定する必要があります。アプリケーション側のヘッドサンプリングと DataKit 側のサンプリングが同時に有効になっている場合、最終的な保持率は相乗効果で低下するため、サンプリングの場所を統一して計画する必要があります。
補足:コードによる接続¶
本ドキュメントでは、前述のコードレス方式を優先的に使用することを推奨します。Resource、Exporter、または個別のインスツルメンテーションを詳細に制御する必要がある場合は、従来の SDK コードによる接続方式も使用できます。
依存関係のインストール¶
npm install --save \
@opentelemetry/api \
@opentelemetry/sdk-node \
@opentelemetry/resources \
@opentelemetry/exporter-trace-otlp-proto \
@opentelemetry/instrumentation-http
サンプルコード¶
OpenTelemetry はビジネスモジュールが読み込まれる前に初期化する必要があります:
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const {
OTLPTraceExporter,
} = require('@opentelemetry/exporter-trace-otlp-proto');
const resource = resourceFromAttributes({
'service.name': 'orders-api',
'service.version': '1.0.0',
'deployment.environment.name': 'prod',
});
const sdk = new NodeSDK({
resource,
traceExporter: new OTLPTraceExporter({
url: 'http://127.0.0.1:9529/otel/v1/traces',
}),
instrumentations: [new HttpInstrumentation()],
});
async function main() {
await sdk.start();
require('./app');
}
process.once('SIGTERM', async () => {
await sdk.shutdown();
process.exit(0);
});
main().catch(error => {
console.error(error);
process.exit(1);
});
コード方式と NODE_OPTIONS=--require .../register で 2 つの SDK を重複して初期化しないでください。コード方式を選択した場合は、コードレス登録モジュールのプリロードパラメータを削除する必要があります。
補足:Node.js プロファイル拡張¶
Node.js プロファイルは、標準の OpenTelemetry トレースとメトリクス以外のパフォーマンスプロファイリングデータを補完するために使用されます。現在サポートされているプロファイルタイプ:
wall;heap。
実際の接続時には、まず wall を有効にし、収集オーバーヘッドと報告パイプラインの安定性を確認した後、必要に応じて heap を有効にすることを推奨します。
プロファイル拡張のインストール¶
最小接続例¶
const { resourceFromAttributes } = require('@opentelemetry/resources');
const {
DatakitProfilingExporter,
NodeProfiling,
} = require('@cloudcare/profiler-nodejs');
const profiler = new NodeProfiling({
resource: resourceFromAttributes({
'service.name': 'orders-api',
'service.version': '1.2.3',
'deployment.environment.name': 'prod',
}),
exporter: new DatakitProfilingExporter({
endpoint: 'http://127.0.0.1:9529/profiling/v1/input',
}),
profileTypes: ['wall'],
cpuProfilingEnabled: true,
});
async function main() {
await profiler.start();
require('./app');
}
process.once('SIGTERM', async () => {
await profiler.shutdown();
process.exit(0);
});
main().catch(error => {
console.error(error);
process.exit(1);
});
OpenTelemetry SDK との併用¶
アプリケーションが前のセクションの SDK コード方式を採用している場合、同じ Resource を再利用できます:
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const {
DatakitProfilingExporter,
NodeProfiling,
} = require('@cloudcare/profiler-nodejs');
const resource = resourceFromAttributes({
'service.name': 'orders-api',
'service.version': '1.2.3',
'deployment.environment.name': 'prod',
});
const sdk = new NodeSDK({ resource });
const profiling = new NodeProfiling({
resource,
exporter: new DatakitProfilingExporter({
endpoint: 'http://127.0.0.1:9529/profiling/v1/input',
}),
});
async function main() {
await sdk.start();
await profiling.start();
require('./app');
}
process.once('SIGTERM', async () => {
await profiling.shutdown();
await sdk.shutdown();
process.exit(0);
});
main().catch(error => {
console.error(error);
process.exit(1);
});
パイプラインを検証する際に、手動で一度収集をトリガーできます:
プロファイル推奨設定¶
| パラメータ | デフォルト値 | 説明 |
|---|---|---|
endpoint |
http://127.0.0.1:9529/profiling/v1/input |
プロファイルのアップロード先アドレス。 |
profileTypes |
['wall', 'heap'] |
収集タイプ。最初は ['wall'] を使用することを推奨。 |
intervalMillis |
60000 |
定期収集の間隔。 |
wallDurationMillis |
10000 |
1回の wall プロファイルの継続時間。 |
デフォルトでは、拡張機能は 60 秒ごとに収集を実行し、wall プロファイルは 10 秒間継続し、データを /profiling/v1/input に送信します。現在のエクスポーターは、wall.pprof、space.pprof、および今回の収集を説明する event.json を送信します。ここで、profiler は ddtrace、family は nodejs、format は pprof であり、Guance の Node.js プロファイル解析パイプラインとの互換性のために使用されます。
実行環境に globalThis.fetch がない場合は、fetch の実装を明示的に提供する必要があります。プロセス終了前にプロファイルが失われるのを防ぐために、終了シグナルハンドラで shutdown() を呼び出す必要があります。トレースとメトリクスのみが必要な場合は、プロファイル拡張をインストールする必要はありません。
接続の確認¶
サポートされているインスツルメンテーションライブラリによって処理されたアプリケーションのルートにリクエストを送信し、DataKit ホストで受信ログを確認します:
/otel/v1/traces への POST リクエストがあり、応答コードが 200 の場合、DataKit がトレースを受信したことを示します。その後、Guance の「APM > トレース」に移動し、service:order-service で検索します。
データがない場合は、以下の順序で確認します:自動インスツルメンテーションパッケージがアプリケーションプロジェクトにインストールされているか、NODE_OPTIONS が実際の Node.js プロセスに渡されているか、登録モジュールがアプリケーションの依存関係の前に読み込まれているか、コードパスがサポートされているインスツルメンテーションライブラリにヒットしているか、OTLP エンドポイントに到達可能か。トラブルシューティング時は、一時的に OTEL_LOG_LEVEL=debug を設定し、確認が完了したら info に戻します。
プロファイルエンドポイントの到達可能性を確認するには、次を実行します:
プロファイルの報告が成功すると、拡張機能のデバッグログに通常 Datakit profiling export succeeded が表示されます。その後、Guance でサービスごとに Node.js プロファイルデータを確認できます。