IBM TechXchange AIOps Group Japan

 View Only

Code Engineで Node.jsサーバーを試して OpenTelemetryで Instanaにトレースを送るメモ

By Daisuke Hiraoka posted Tue December 13, 2022 02:37 AM

  

はじめに

この投稿では、 Code Engineを使ってアプリケーションの開発・運用する際のモニタリングツールとして、
OpenTelemetry と APMツールのInstanaでアプリケーションの性能情報(呼び出し数、エラー数、遅延)を可視化する方法を試した時のメモになります。

OpenTelemetryとは

OpenTelemetryは、テレメトリデータ(メトリクス、ログ、およびトレース)を計測、生成、収集、そしてエクスポートを行うOSSのオブザーバビリティのフレームワークです。 OpenTelemetryはテレメトリデータを分析する機能がありません。ですので、今回は、Instanaにテレメトリデータを送信して表示・分析することにします。

前提作業

IBM Cloud Advent Calendar 20229日目 @tseigo さんの記事で作成したNode.jsサーバで動くアプリケーションに、OpenTelemetryで Instanaにトレースを送る機能を追加します。

事前に、 Code Engine で Node.js サーバーを試して Vue + Vite の連携までやってみるメモ の手順でCode Engineでアプリが起動している状態まで準備してください。

具体的には、Express を動くようにする の手順で

  • npmでExpressをインストール
  • public フォルダを作って public/index.html を作成
  • 変更したソースコードをコミット
  • 再度 Code Engine 上で新しいアプリケーションを作成
    の手順を実行すると以下の画像のようにアプリケーションのビルドとデプロイが開始します。
    image.png

アプリケーションのデプロイが完了後、上記画面のアプリケーションのテスト  アプリケーションのURL の順番にクリックすると下記画像のように Index という文字がブラウザに表示されます。
image.png

もし、Code Engineに不慣れな場合は、数分でアプリがデプロイできるコンテナ環境!IBM Cloud Code Engine で素振りすると良いでしょう。

OpenTelemetryを有効にするための手順

Instanaでは、OpenTelemetryでモニターされたアプリケーションのテレメトリデータ(メトリクス、ログ、およびトレース)をホスト・エージェントを介して、テレメトリーをバックエンドサーバに送信します。(下図エージェントタイプ)
image.png

しかし、Code Engineのようなサーバーレス環境(エージェントが存在しない環境)で実行されている場合は、Instana OpenTelemetry Exporterを使用して、エージェントを介さずに直接、バックエンドサーバに送信する仕組みになっています。
image.png
※ AWSのLambda、Fargate、Azure FunctionsなどのServerlessも同じ仕組みで利用します。

具体的には、以下の作業が必要になります。

  • Dockerfileの編集
  • パッケージのインストール
  • Instana OpenTelemetry Exporter(tracer.js)の設定
  • Instanaの環境変数を定義
    • INSTANA_AGENT_KEY
    • INSTANA_ENDPOINT_URL
  • アプリケーションのビルド&デプロイ

それでは、順番に設定を行っていきましょう。

Dockerfile

Dockerfileを下記のように書き換えます。

FROM icr.io/codeengine/node:12-alpine
COPY package.json .
RUN npm install
RUN mkdir public
COPY public/ public/
COPY server.js .
COPY tracer.js .
EXPOSE 8080
CMD [ "node", "--require", "./tracer.js", "server.js" ]

変更した内容は、以下の2つに

  • (追加) COPY tracer.js .
    • トレースモジュールの tracer.jsを追加すること
  • (変更) CMD [ "node", "--require", "./tracer.js", "server.js" ]
    • node起動時に、トレースモジュール tracer.js を読み込んで起動

OpenTelemeryでサポートしているNode.jsのバージョンは14以上になってます。
Support一覧: https://github.com/open-telemetry/opentelemetry-js#supported-runtimes
Dockerfileのコンテナイメージが node:12-alpine と古いバージョンですが、今回は、動作したのでそのまま使用しています。

パッケージのインストール

以下のOpenTelemetryと InstanaのOpenTeremetry Exporterをインストールします。

  • OpenTelemetry
    • @opentelemetry/api
    • @opentelemetry/sdk-node
    • @opentelemetry/auto-instrumentations-node
    • @opentelemetry/resources
    • @opentelemetry/semantic-conventions
  • Instana
    • @instana/opentelemetry-exporter

npmコマンドでインストールを実行します。

$ npm i @opentelemetry/sdk-node @opentelemetry/api \
@opentelemetry/auto-instrumentations-node @opentelemetry/resources \
@opentelemetry/semantic-conventions @instana/opentelemetry-exporter

インストールが完了すると package.json  dependencies に OpenTelemetryとInstanaのパッケージが出力されます。

  "dependencies": {
    "@instana/opentelemetry-exporter": "^2.13.1",
    "@opentelemetry/api": "^1.3.0",
    "@opentelemetry/auto-instrumentations-node": "^0.35.0",
    "@opentelemetry/resources": "^1.8.0",
    "@opentelemetry/sdk-node": "^0.34.0",
    "@opentelemetry/semantic-conventions": "^1.8.0",
    "express": "^4.18.2"
  }

Instana OpenTelemetry Exporter(tracer.js)の設定

Instana OpenTelemetry Exporter(tracer.js)は、Node.jsのアプリケーションが実行すると OpenTelemetryでテレメトリデータを生成して、そしてInstana Exporterが OpenTelemetry Spanを Instana Spanに変換して、 Instanaのバックエンドサーバーに送信します。

下記のソースコードが、Instana OpenTelemetry Exporter(tracer.js)のソースコードでInstanaドキュメントからコピー&ペーストすることが可能です。

  • tracer.js
'use strict';

const process = require('process');
require('@opentelemetry/api');
const opentelemetry = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');

// Import the Instana OpenTelemetry Exporter
const { InstanaExporter } = require('@instana/opentelemetry-exporter');

// Instantiate the Instana Exporter.
// Make sure to provide the proper agent key and backend endpoint URL.
// You can provide the agent key and backend endpoint URL via the following environment variables:
// * INSTANA_AGENT_KEY
// * INSTANA_ENDPOINT_URL
//
// Alternatively, you can pass these values as an argument to the constructor (see bellow), although it is strongly
// recommended that such sensitive data is not hard coded in the code base.
// Eg: const instanaTraceExporter = new InstanaExporter({ agentKey: 'agent_key', endpointUrl: 'endpoint_url' });
const instanaTraceExporter = new InstanaExporter();

const nodeAutoInstrumentations = getNodeAutoInstrumentations();

const sdk = new opentelemetry.NodeSDK({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'サービス名'
  }),
  // Configure OpenTelemetry to use the Instana Exporter
  traceExporter: instanaTraceExporter,
  instrumentations: [nodeAutoInstrumentations]
});

sdk
  .start()
  .then(() => console.log('Tracing initialized'))
  .catch(error => console.log('Error initializing tracing', error));

process.on('SIGTERM', () => {
  sdk
    .shutdown()
    .then(() => console.log('Tracing terminated'))
    .catch(error => console.log('Error terminating tracing', error))
    .finally(() => process.exit(0));
});

上記、Instana OpenTelemetry Exporter(tracer.js)のソースコードの中で、

[SemanticResourceAttributes.SERVICE_NAME]: 'サービス名' のサービス名を以下の様にサービス名を定義します。
[SemanticResourceAttributes.SERVICE_NAME]: 'CodeEngineApps'

Instanaの環境変数を定義

Instanaのバックエンドサーバに接続するために必要な エンドポイントのURL (INSTANA_ENDPOINT_URL) と Agent Key(INSTANA_AGENT_KEY) の環境変数を作成します。

Code Engineのプロジェクト、アプリケーションの画面を開き、 ①構成 ②環境変数 ③編集 して新規リビジョンを作成を開きます。
image.png

環境変数の追加をクリックして、 下記赤枠の様に INSTANA_ENDPOINT_URL 、 と INSTANA_AGENT_KEY の環境変数を作成します。
image.png

上記、環境変数の追加をする際は、定義タイプリテラル値を選択して、環境変数を作成してください。
image.png

アプリケーションのビルド&デプロイ

前の手順で、環境変数を作成した後、①コード タブの ②ビルドの再実行 をクリックして、ビルドを実行します。
image.png

そして、上記画像の ③保存して作成を押すことで、下記画像の様に、ビルド完了後、デプロイが実施されます。
image.png

アプリケーションのデプロイが完了後、上記画面のアプリケーションのテスト  アプリケーションのURL の順番にクリックすると下記画像のように Index という文字がブラウザに表示されます。
image.png

ここまでの作業で、Node.jsのアプリケーションを OpenTelemetryでモニターしたテレメトリデータをInstanaのバックエンドサーバに送る設定は完了しました。
この後は、Node.jsのアプリケーションに負荷をかけて、Instanaのバックエンドサーバの画面で、テレメトリデータを確認します。

Node.jsのアプリケーションに負荷生成

アプリケーションのアクセスが発生しないとテレメトリデータは生成されません。
今回は、シンプルにcurlを使って、連続的に負荷を生成させて、次の手順のInstanaのバックエンドサーバでの画面確認を行います。

while true
do
    curl --silent https://application-21.xxx.jp-tok.codeengine.appdomain.cloud/index.html
    sleep 1
done

Instanaバックエンドサーバでの画面確認

これまでの手順が正常で、Node.jsのアプリケーションに負荷を発生させると、
Instanaのアプリケーションの画面では、Exporter設定(tracer.js)で定義したサービス名CodeEndgineAppsが検出され、呼び出し数、待ち時間、エラーのある呼び出し率が下記画像のように表示します。
image.png

以降、InstanaでOpenTelemetryのテレメトリデータをどのように表示するのかスクリーンショットを貼っておきます。

アプリケーション画面 呼び出し、エラーのある呼び出し率、待ち時間、処理時間などが表示

image.png

トレースの詳細(キャプチャーされたトレースのリスト)

image.png

OpenTelemetryで収集したスパン

image.png

個々のトレースの詳細

image.png

最後に

この投稿ではCode Endingeで動作するNode.jsのアプリケーションをOpenTelemetryでモニターして、Instanaのバックエンドサーバの画面で、テレメトリデータを可視化する事を確認しました。

今回は、簡単に、OpenTelemetry & Instanaの動作確認するために、サービスは1つ(Node.jsサーバ1つ)で行いましたが、
DBサーバなど、複数のサービスとの連携も行うことができます。

この投稿をきっかけにぜひ、お試しください。

0 comments
4 views

Permalink