はじめに
この投稿では、 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 上で新しいアプリケーションを作成
の手順を実行すると以下の画像のようにアプリケーションのビルドとデプロイが開始します。
アプリケーションのデプロイが完了後、上記画面のアプリケーションのテスト
、 アプリケーションのURL
の順番にクリックすると下記画像のように Index
という文字がブラウザに表示されます。
もし、Code Engineに不慣れな場合は、数分でアプリがデプロイできるコンテナ環境!IBM Cloud Code Engine で素振りすると良いでしょう。
OpenTelemetryを有効にするための手順
Instanaでは、OpenTelemetryでモニターされたアプリケーションのテレメトリデータ(メトリクス、ログ、およびトレース)をホスト・エージェントを介して、テレメトリーをバックエンドサーバに送信します。(下図エージェントタイプ)
しかし、Code Engineのようなサーバーレス環境(エージェントが存在しない環境)で実行されている場合は、Instana OpenTelemetry Exporterを使用して、エージェントを介さずに直接、バックエンドサーバに送信する仕組みになっています。
※ 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
を読み込んで起動
- node起動時に、トレースモジュール
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のプロジェクト、アプリケーションの画面を開き、 ①構成
、②環境変数
、③編集
して新規リビジョンを作成を開きます。
環境変数の追加をクリックして、 下記赤枠の様に INSTANA_ENDPOINT_URL
、 と INSTANA_AGENT_KEY
の環境変数を作成します。
上記、環境変数の追加をする際は、定義タイプリテラル値
を選択して、環境変数を作成してください。
アプリケーションのビルド&デプロイ
前の手順で、環境変数を作成した後、①コード
タブの ②ビルドの再実行
をクリックして、ビルドを実行します。
そして、上記画像の ③保存して作成
を押すことで、下記画像の様に、ビルド完了後、デプロイが実施されます。
アプリケーションのデプロイが完了後、上記画面のアプリケーションのテスト
、 アプリケーションのURL
の順番にクリックすると下記画像のように Index
という文字がブラウザに表示されます。
ここまでの作業で、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
が検出され、呼び出し数、待ち時間、エラーのある呼び出し率が下記画像のように表示します。
以降、InstanaでOpenTelemetryのテレメトリデータをどのように表示するのかスクリーンショットを貼っておきます。
アプリケーション画面 呼び出し、エラーのある呼び出し率、待ち時間、処理時間などが表示
トレースの詳細(キャプチャーされたトレースのリスト)
OpenTelemetryで収集したスパン
個々のトレースの詳細
最後に
この投稿ではCode Endingeで動作するNode.jsのアプリケーションをOpenTelemetryでモニターして、Instanaのバックエンドサーバの画面で、テレメトリデータを可視化する事を確認しました。
今回は、簡単に、OpenTelemetry & Instanaの動作確認するために、サービスは1つ(Node.jsサーバ1つ)で行いましたが、
DBサーバなど、複数のサービスとの連携も行うことができます。
この投稿をきっかけにぜひ、お試しください。