コンテンツにスキップ

OpenTelemetry Node.js

OTEL を使用して Trace / Metric を DataKit に送信する前に、収集器の設定が完了していることを確認してください。

OpenTelemetry Node.js は、Node.js アプリケーションの Trace と Metric データを収集し、OTLP プロトコルで DataKit に送信してから、Guance で統合表示できます。

標準の OpenTelemetry 機能に加えて、Guance は Node.js 向けに Profile 拡張機能 も提供します。この機能は、Guance が保守・公開している @cloudcare/profiler-nodejs@datadog/pprof を基盤としており、wall / heap profile を収集して、DataKit の /profiling/v1/input インターフェース経由で Guance に送信できます。

バージョンサポート

  • Node.js:^18.19.0 または >=20.6.0
  • OpenTelemetry:現在の安定版の使用を推奨
  • Profile 拡張パッケージ:@cloudcare/profiler-nodejs
  • デフォルトの Profiling 送信先:http://127.0.0.1:9529/profiling/v1/input

自動インストゥルメンテーション方式

Node.js では、もっとも一般的なのは自動インストゥルメンテーションで素早く導入する方法です。

1) 依存関係のインストール

npm install \
  @opentelemetry/api \
  @opentelemetry/sdk-node \
  @opentelemetry/auto-instrumentations-node \
  @opentelemetry/exporter-trace-otlp-proto \
  @opentelemetry/exporter-metrics-otlp-proto

2) 環境変数で設定する方法

export OTEL_SERVICE_NAME="nodejs-demo"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
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 NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"

その後、アプリケーションをそのまま起動します。

node app.js

デフォルトの HTTP パスを使う場合、Trace / Metric の実際の送信先はそれぞれ次のとおりです。

  • Trace:http://127.0.0.1:9529/otel/v1/traces
  • Metric:http://127.0.0.1:9529/otel/v1/metrics

3) コマンドライン起動方式

環境変数の注入を使いたくない場合は、起動コマンド内で直接設定することもできます。

OTEL_SERVICE_NAME=nodejs-demo \
OTEL_TRACES_EXPORTER=otlp \
OTEL_METRICS_EXPORTER=otlp \
OTEL_LOGS_EXPORTER=none \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:9529/otel \
NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register" \
node app.js

4) PM2 / Systemd の場合

アプリケーションを PM2、Systemd、またはその他のプロセスマネージャーで起動している場合は、上記の OTEL_* 環境変数と NODE_OPTIONS を対応する起動設定に書き込むことを推奨します。

基本設定は通常 2 つだけです。

  • OTEL_SERVICE_NAME
  • NODE_OPTIONS=--require @opentelemetry/auto-instrumentations-node/register

残りの OTLP パラメータは、実際の DataKit のアドレスに合わせて追加してください。

コードで導入する方法

自動インストゥルメンテーションが適さない場合は、コードで OpenTelemetry SDK を統合できます。

依存関係のインストール

npm install \
  @opentelemetry/api \
  @opentelemetry/sdk-node \
  @opentelemetry/resources \
  @opentelemetry/semantic-conventions \
  @opentelemetry/exporter-trace-otlp-proto \
  @opentelemetry/exporter-metrics-otlp-proto \
  @opentelemetry/instrumentation-http

サンプルコード

const { NodeSDK } = require('@opentelemetry/sdk-node');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const {
  ATTR_SERVICE_NAME,
  ATTR_SERVICE_VERSION,
  SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
} = require('@opentelemetry/semantic-conventions');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const {
  OTLPTraceExporter,
} = require('@opentelemetry/exporter-trace-otlp-proto');

const resource = resourceFromAttributes({
  [ATTR_SERVICE_NAME]: 'orders-api',
  [ATTR_SERVICE_VERSION]: '1.0.0',
  [SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: '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();
  console.log('OpenTelemetry Node.js started');
}

main().catch(err => {
  console.error(err);
  process.exit(1);
});

Node.js Profile 拡張

Node.js Profile は、Guance が現在 Node.js シナリオ向けに提供している拡張機能であり、標準の OTel Trace / Metric に加えて profile データの収集を補完します。

この機能は OpenTelemetry 公式の npm パッケージの一部ではなく、Guance が OpenTelemetry Node.js を基に拡張して公開しているものです。

現在サポートしている profile の種類は次のとおりです。

  • wall
  • heap

実際に導入する際は、まず wall を有効にして接続が安定していることを確認し、その後必要に応じて heap を有効にすることを推奨します。

@cloudcare/profiler-nodejs の取得

現在の Node.js Profile 拡張パッケージ名は次のとおりです。

@cloudcare/profiler-nodejs

npm の公開リポジトリに直接アクセスできる場合は、次を実行できます。

npm install @cloudcare/profiler-nodejs

依存関係のインストール

npm install \
  @cloudcare/profiler-nodejs \
  @datadog/pprof \
  @opentelemetry/resources \
  @opentelemetry/semantic-conventions

最小導入例

const { resourceFromAttributes } = require('@opentelemetry/resources');
const {
  ATTR_SERVICE_NAME,
  ATTR_SERVICE_VERSION,
  SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
} = require('@opentelemetry/semantic-conventions');
const {
  DatakitProfilingExporter,
  NodeProfiling,
} = require('@cloudcare/profiler-nodejs');

const profiler = new NodeProfiling({
  resource: resourceFromAttributes({
    [ATTR_SERVICE_NAME]: 'orders-api',
    [ATTR_SERVICE_VERSION]: '1.2.3',
    [SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: 'prod',
  }),
  exporter: new DatakitProfilingExporter({
    endpoint: 'http://127.0.0.1:9529/profiling/v1/input',
  }),
  profileTypes: ['wall'],
  cpuProfilingEnabled: true,
});

async function main() {
  await profiler.start();
}

main().catch(err => {
  console.error(err);
  process.exit(1);
});

OpenTelemetry SDK と一緒に使う

アプリケーションですでに OpenTelemetry SDK を導入している場合は、profiler を同時に初期化できます。

const { NodeSDK } = require('@opentelemetry/sdk-node');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const {
  ATTR_SERVICE_NAME,
  ATTR_SERVICE_VERSION,
  SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
} = require('@opentelemetry/semantic-conventions');
const {
  DatakitProfilingExporter,
  NodeProfiling,
} = require('@cloudcare/profiler-nodejs');

const resource = resourceFromAttributes({
  [ATTR_SERVICE_NAME]: 'orders-api',
  [ATTR_SERVICE_VERSION]: '1.2.3',
  [SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: '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();
}

process.on('SIGTERM', async () => {
  await profiling.shutdown();
  await sdk.shutdown();
  process.exit(0);
});

main().catch(err => {
  console.error(err);
  process.exit(1);
});

手動で 1 回収集する

接続確認の際は、直接次を実行できます。

await profiling.collectOnce();

これは通常、次の用途に適しています。

  • Profiling インターフェースに初回接続できるかの確認
  • profile が正常に生成・送信されるかの確認
  • 特定の負荷テスト時間帯に、1 回だけ profile を取得する

推奨 Profile 設定

多くのケースでは、次の主要パラメータだけを把握しておけば十分です。

パラメータ デフォルト値 説明
endpoint http://127.0.0.1:9529/profiling/v1/input Profile のアップロード先
profileTypes ['wall', 'heap'] 収集する profile の種類。まずは ['wall'] の使用を推奨
intervalMillis 60000 周期収集の間隔
wallDurationMillis 10000 1 回の wall profile の継続時間

特別な性能チューニングの必要がなければ、通常はデフォルト値のままで問題ありません。

デフォルト動作

デフォルトでは、Node.js Profile 拡張は次のように動作します。

  • 60 秒ごとに 1 回収集する
  • 各ラウンドで wallheap の 2 種類の profile を収集する
  • wall profile はデフォルトで 10 秒収集する
  • cpuProfilingEnabled をデフォルトで有効にする
  • profile を http://127.0.0.1:9529/profiling/v1/input に送信する

現在の exporter は 2 つの pprof 添付ファイルを送信します。

  • wall.pprof
  • space.pprof

それぞれの内容は次のとおりです。

  • wall.pprofsample/count、オプションの cpu/nanosecondswall/nanoseconds を含む
  • space.pprofobjects/countspace/bytes を含む

あわせて event.json も付与され、そこでは次の値が設定されます。

  • profiler は固定で ddtrace
  • family は固定で nodejs
  • format は固定で pprof

この構成は、Guance の現在の Node.js Profile 解析チェーンとの互換性のために使われます。

検証

Trace / Metric 送信の検証

アプリケーションが DataKit の OTLP HTTP エンドポイントにアクセスできることを確認します。

curl -i http://127.0.0.1:9529/otel/v1/traces
curl -i http://127.0.0.1:9529/otel/v1/metrics

Profile 送信の検証

アプリケーションが Profiling インターフェースにアクセスできることを確認します。

curl -i http://127.0.0.1:9529/profiling/v1/input

ログの検証

profile の送信に成功した場合、デバッグログには通常次のような情報が表示されます。

Datakit profiling export succeeded for 1 profile(s)

Guance 側データの検証

導入後は、Guance で次を確認できます。

  1. Trace がサービスごとに正常送信されているか
  2. Metric が対応するメトリクスセットに入っているか
  3. Node.js Profile がサービス単位で表示されているか

注意事項

  1. Node.js Profile は Guance の拡張機能であり、OpenTelemetry の公式標準機能ではありません。
  2. 現在サポートしている profile は wallheap の 2 種類のみです。
  3. 実行環境に globalThis.fetch がない場合は、fetch 実装を明示的に渡してください。
  4. プロセス終了前に profile が失われるのを避けるため、終了時に shutdown() を呼び出すことを推奨します。
  5. Trace / Metric のみが必要な場合は、@cloudcare/profiler-nodejs をインストールする必要はありません。

参考

フィードバック

このページは役に立ちましたか?