トレース - Node.jsにOpenTelemetryを導入する

MackerelはOpenTelemetryの仕組み (計装)を利用してデータを取得しています。

このページではNode.jsのデータをMackerelに送信する方法を解説します。

Node.js向けOpenTelemetry

OpenTelemetry には Node.js用のSDKが用意されています。

このSDKに加えて、ExpressやAWS用のSDKを使用すると、色々な範囲を計装することができます。

opentelemetry.io

Collectorを使用するべきか

データをMackerelに送信する際に、SDKから直接送信するだけではなく、Collectorを使うこともできます。

Collectorを使うかどうかを決める際は以下のページを参考にしてください。

Collectorを使うかどうかの判断について

導入方法

Node.jsには複数のWebフレームワークが存在しますが、このページでは Express への導入方法を説明します。 他のフレームワークを使っている場合もほぼ同じ方法で計装することができます。

以下のステップでMackerelトレーシング機能を導入できます。

  1. パッケージ追加
  2. 初期設定
  3. 独自の計装の追加 (任意)

1. パッケージ追加

以下のパッケージを使用します。

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

上のコマンドで追加した auto-instrumentations-node は多くのパッケージを内包しているため、Expressやhttpのように人気のライブラリは自動で計装されます。

含まれているパッケージはGitHubのページを参照してください。

また、足りない場合はOpenTelemetryのページからパッケージを探すことができます。

opentelemetry.io

2. 初期設定

OpenTelemetryのデータをMackerelに送信するためには、以下の項目を設定する必要があります。

  • Exporter
  • resource

例えば、以下のようにすると、SDKから直接Mackerelに送信することができます。

const { Resource, processDetector, hostDetector } = require('@opentelemetry/resources');
const { OTLPTraceExporter } = require("@opentelemetry/exporter-trace-otlp-proto");
const { SemanticResourceAttributes } = require("@opentelemetry/semantic-conventions");
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');

const exporter = new OTLPTraceExporter({
  maxQueueSize: 1000,
  url: "https://otlp-vaxila.mackerelio.com/v1/traces",
  headers: {
    "Accept": "*/*",
    "Mackerel-Api-Key": process.env.MACKEREL_API_KEY,
  }
})
// デバッグ時にはConsoleSpanExporterが便利
// const exporter = new ConsoleSpanExporter()

const sdk = new NodeSDK({
  traceExporter: exporter,
  instrumentations: instrumentations: [    
    getNodeAutoInstrumentations({
      // fsの計装はスタートアップ時に大量のトレースを作り出すので、必要がなければ外したほうが便利です。
      '@opentelemetry/instrumentation-fs': {
        enabled: false,
      },
    }),
  ],
  resource: Resource.default().merge(new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: "acme_service",
    [SemanticResourceAttributes.SERVICE_VERSION]: "vX.Y.Z",
    [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: "production"
  })),
  resourceDetectors: [processDetector, hostDetector]
});

sdk.start()

この例では次の項目を設定しています。

  • Exporter
    • url
      • https://otlp-vaxila.mackerelio.com/v1/traces と設定することで、データを直接Mackerelに送信するようになります。
      • Collectorを利用する場合は、Collectorのエンドポイント (http://localhost:4318/v1/traces など) を設定してください。
    • headers
      • Mackerel-Api-KeyAccept のヘッダーを設定することでMackerelと通信することができます。
      • Mackerel-Api-Key には、Mackerelで発行された書き込み権限のあるAPIキーを設定してください。APIキーの権限を変更した際は反映まで1分ほどお待ちください。
      • Collectorを利用する場合、ヘッダーは必要ないでしょう。
  • resource & resourceDetectors
    • NodeSDKのresourceを設定することで、データがどこから来たかわかるようになります。

3. 独自の計装の追加 (任意)

独自のSpanを追加することで、任意の範囲を計装することができます。

計装によって、変数の値や処理時間を記録することができるようになります。

具体的には、下のように startActiveSpan で囲むと計装が追加できます。

const tracer = opentelemetry.trace.getTracer(
  'my-service-tracer'
);
tracer.startActiveSpan('awesome_action', (span) => {
  // ... 既存の処理

  span.end();
});

計装の方法は他にも用意されています。詳細はOpenTelemetryのドキュメントを参照してください。

opentelemetry.io