12
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

IBM Cloud Advent Calendar 2022

Day 11

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

Last updated at Posted at 2022-12-12

はじめに

この投稿では、 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.jsondependencies に 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サーバなど、複数のサービスとの連携も行うことができます。

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

12
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?