LoginSignup
1
0

More than 3 years have passed since last update.

Node.jsをOpenTelemetryでメトリック収集してみる

Posted at

はじめに

前回、Node.js(JavaScript)でOpenTelemetryによるトレースデータ収集を行なったので、今度はカウンタ値のようなメトリックデータ収集についてまとめてみました。

OpenTelemetryの概要やトレースデータ収集の記事はこちらを参照。

やってみること

Node.jsアプリケーション上で収集したメトリックデータ(今回は3種類のカウンタの数値)を、Prometheusでグラフ化してみます。
architecture.png

実行環境

  • MacOS X
  • node: v13.8.0
  • npm: v7.5.3
  • express: v4.17.1
  • OpenTelemetry: v0.18

1. サンプル構成の作成

まずはベースとなるサンプルアプリケーションを作成します。

サンプルの内容は、URLにアクセスすると3種類の色(red, blue, yellow)のいずれかを返す単純なロジックとなります。

1.1 サンプル作成

プロジェクトにExpressをインストールします。

$ npm install express

アプリケーション(app.js)を作成します。

app.js
'use strict';

const express = require('express');
const app = express();
const PORT = process.env.PORT || '8080';

app.use(function(req, res, next) {
  // ランダムで色を選ぶ
  const color = ['red', 'blue', 'blue', 'yellow', 'yellow', 'yellow'];
  res.locals.color = color[Math.floor(Math.random() * color.length)];
  next();
});

app.get('/', (req, res, next) => {
  res.send(res.locals.color);
  next();
});

app.listen(parseInt(PORT, 10), () => {
  console.log(`Listening for requests on http://localhost:${PORT}`);
});

1.2 サンプルの動作確認

サンプルを実行すると、localhost:8080でクライアントからのリクエストを待ち受けるようになります。

$ node app.js
Listening for requests on http://localhost:8080

別のターミナルからサンプルのURLにアクセスします。

$ curl localhost:8080
red

上記のようにred, blue, yellowのいずれかが返却されます。

2. Prometheusの起動

メトリック収集の準備として、メトリックデータのグラフ化を行うPrometheusを構築します。

今回はDockerコンテナ版を使用します。

コンテナ起動前に、まずprometheus.ymlを作成します。

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'opentelemetry'
    static_configs:
      - targets: 
        - 'host.docker.internal:9464'

targetsはPrometheusにおけるメトリックデータの収集先となります。
今回はホストとなりますが、コンテナから見たホストはlocalhostではなくhost.docker.internalとなります(localhostはコンテナを指す)。
なおhost.docker.internalはLinuxでは使えないため(MacやWindowsなら可)、Linux環境の場合はホストのIPアドレスに置き換えてください。

docker run \
    -d \
    -p 9090:9090 \
    -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus

localhost:9090にアクセスし、PrometheusのGUI画面が表示されたら起動OKです。

prometheus1.png

3. OpenTelemetryの組み込み

それでは先ほど作成したサンプルに、メトリックデータ収集を行うOpenTelemetryを組み込んでいきます。

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

$ npm install @opentelemetry/metrics @opentelemetry/exporter-prometheus

3.2 monitoring.jsの作成

サンプルに組み込むカウンタのロジックを作成します。

monitoring.js
'use strict';

const { MeterProvider } = require('@opentelemetry/metrics');
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');

const prometheusPort = PrometheusExporter.DEFAULT_OPTIONS.port
const prometheusEndpoint = PrometheusExporter.DEFAULT_OPTIONS.endpoint
const exporter = new PrometheusExporter(
  {
    startServer: true,
  },
  () => {
    console.log(
      `prometheus scrape endpoint: http://localhost:${prometheusPort}${prometheusEndpoint}`,
    );
  },
);

const meter = new MeterProvider({
  exporter,
  interval: 1000,
}).getMeter('color-meter');

const colorCount = meter.createCounter('colors', {
  description: 'Count each color'
});

// 色ごとにCounterを生成する
const redCounter = colorCount.bind({ color: 'red'});
const blueCounter = colorCount.bind({ color: 'blue'});
const yellowCounter = colorCount.bind({ color: 'yellow'});

module.exports.countColorRequests = () => {
  return (req, res, next) => {
    switch (res.locals.color) {
      case 'red':
        redCounter.add(1);
        break;
      case 'blue':
        blueCounter.add(1);
        break;
      case 'yellow':
        yellowCounter.add(1);
        break;
    }
    next();
  };
};

カウンタはmeter.createCounter()で作成します。

引数で指定した文字列が、メトリックデータのテーブル名に相当します。

また今回は返却した色ごとのカウンタ値をグラフ化したいので、以下のようにmeter.createCounter()で作成したカウンタにラベルをbindし、3色分のカウンタを作成します。
ここで指定する color: 'red'はグラフの系列名に相当します。

const redCounter = colorCount.bind({ color: 'red'});

3.3 サンプルへの組み込み

先ほど作成したmonitoring.jsをサンプルに組み込みます。

app.js
'use strict';

const express = require('express');
const app = express();
const PORT = process.env.PORT || '8080';

+ const { countColorRequests } = require("./monitoring");

app.use(function(req, res, next) {
  // ランダムで色を選ぶ
  const color = ['red', 'blue', 'blue', 'yellow', 'yellow', 'yellow'];
  res.locals.color = color[Math.floor(Math.random() * color.length)];
  next();
});

+ app.use(countColorRequests());

app.get('/', (req, res, next) => {
  res.send(res.locals.color);
  next();
});

app.listen(parseInt(PORT, 10), () => {
  console.log(`Listening for requests on http://localhost:${PORT}`);
});

Math.random()で色を選択した後、countColorRequests()を呼び出し、選択した色のカウンタをインクリメントしています。

3.4 動作確認

1章と同様に、サンプルを起動します。
起動すると、localhost:8080のリクエスト待ち受けに加え、localhost:9464/metricsでもPrometheusからのメトリックデータ収集(Pull)を待ち受けるようになります。

$ node app.js 
Listening for requests on http://localhost:8080
prometheus scrape endpoint: http://localhost:9464/metrics

サンプルへのリクエスト送信を100回連続で行い、カウンタ値を増やしてみます。

$ for var in `seq 100`; do curl localhost:8080; done

カウンタ値は、localhost:9464/metricsにアクセスすると参照できます。
(Prometheusはこの内容を定期的に収集します)

$ curl http://localhost:9464/metrics
# HELP colors Count each color
# TYPE colors counter
colors{color="red"} 14 1615214799584
colors{color="blue"} 32 1615214799558
colors{color="yellow"} 54 1615214799597

それではPrometheusでグラフ表示してみます。

Graphタブを選択し、テキストボックスにcolorsと入力、Executeボタンを実行します。
すると、下図のようなグラフが出力され、カウンタ値のインクリメントの推移を確認することができます。

prometheus.png

おわりに

メトリック収集はOpenTelemetryを使わなくてもさまざまな方法で実現できますが、ユーザアプリケーション独自のメトリックを収集する場合にOpenTelemetryは強みを発揮しそうです。

OpenTelemetryについて、他にも面白そうな機能があれば試していきたいと思います。

1
0
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
1
0